Merge branch 'master' into wine-wayland
This commit is contained in:
@@ -61,9 +61,6 @@ trim_trailing_whitespace = unset
|
||||
[nixos/modules/services/networking/ircd-hybrid/*.{conf,in}]
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[nixos/tests/systemd-networkd-vrf.nix]
|
||||
trim_trailing_whitespace = unset
|
||||
|
||||
[pkgs/build-support/dotnetenv/Wrapper/**]
|
||||
end_of_line = unset
|
||||
indent_style = unset
|
||||
|
||||
+47
-4
@@ -118,7 +118,7 @@
|
||||
|
||||
# Rust
|
||||
/pkgs/development/compilers/rust @Mic92 @LnL7 @zowoq
|
||||
/pkgs/build-support/rust @andir @zowoq
|
||||
/pkgs/build-support/rust @zowoq
|
||||
|
||||
# Darwin-related
|
||||
/pkgs/stdenv/darwin @NixOS/darwin-maintainers
|
||||
@@ -141,6 +141,15 @@
|
||||
/pkgs/development/tools/build-managers/rebar3 @gleber
|
||||
/pkgs/development/tools/erlang @gleber
|
||||
|
||||
# Audio
|
||||
/nixos/modules/services/audio/botamusique.nix @mweinelt
|
||||
/nixos/modules/services/audio/snapserver.nix @mweinelt
|
||||
/nixos/tests/modules/services/audio/botamusique.nix @mweinelt
|
||||
/nixos/tests/snapcast.nix @mweinelt
|
||||
|
||||
# Browsers
|
||||
/pkgs/applications/networking/browsers/firefox @mweinelt
|
||||
|
||||
# Jetbrains
|
||||
/pkgs/applications/editors/jetbrains @edwtjo
|
||||
|
||||
@@ -167,12 +176,30 @@
|
||||
/nixos/tests/hardened.nix @joachifm
|
||||
/pkgs/os-specific/linux/kernel/hardened-config.nix @joachifm
|
||||
|
||||
# Home Automation
|
||||
/nixos/modules/services/misc/home-assistant.nix @mweinelt
|
||||
/nixos/modules/services/misc/zigbee2mqtt.nix @mweinelt
|
||||
/nixos/tests/home-assistant.nix @mweinelt
|
||||
/nixos/tests/zigbee2mqtt.nix @mweinelt
|
||||
/pkgs/servers/home-assistant @mweinelt
|
||||
/pkgs/tools/misc/esphome @mweinelt
|
||||
|
||||
# Network Time Daemons
|
||||
/pkgs/tools/networking/chrony @thoughtpolice
|
||||
/pkgs/tools/networking/ntp @thoughtpolice
|
||||
/pkgs/tools/networking/openntpd @thoughtpolice
|
||||
/nixos/modules/services/networking/ntp @thoughtpolice
|
||||
|
||||
# Network
|
||||
/pkgs/tools/networking/kea/default.nix @mweinelt
|
||||
/pkgs/tools/networking/babeld/default.nix @mweinelt
|
||||
/nixos/modules/services/networking/babeld.nix @mweinelt
|
||||
/nixos/modules/services/networking/kea.nix @mweinelt
|
||||
/nixos/modules/services/networking/knot.nix @mweinelt
|
||||
/nixos/tests/babeld.nix @mweinelt
|
||||
/nixos/tests/kea.nix @mweinelt
|
||||
/nixos/tests/knot.nix @mweinelt
|
||||
|
||||
# Dhall
|
||||
/pkgs/development/dhall-modules @Gabriel439 @Profpatsch @ehmry
|
||||
/pkgs/development/interpreters/dhall @Gabriel439 @Profpatsch @ehmry
|
||||
@@ -245,10 +272,26 @@
|
||||
# Cinnamon
|
||||
/pkgs/desktops/cinnamon @mkg20001
|
||||
|
||||
#nim
|
||||
/pkgs/development/compilers/nim @ehmry
|
||||
/pkgs/development/nim-packages @ehmry
|
||||
# nim
|
||||
/pkgs/development/compilers/nim @ehmry
|
||||
/pkgs/development/nim-packages @ehmry
|
||||
/pkgs/top-level/nim-packages.nix @ehmry
|
||||
|
||||
# terraform providers
|
||||
/pkgs/applications/networking/cluster/terraform-providers @zowoq
|
||||
|
||||
# kubernetes
|
||||
/nixos/doc/manual/configuration/kubernetes.chapter.md @zowoq
|
||||
/nixos/modules/services/cluster/kubernetes @zowoq
|
||||
/nixos/tests/kubernetes @zowoq
|
||||
/pkgs/applications/networking/cluster/kubernetes @zowoq
|
||||
|
||||
# Matrix
|
||||
/pkgs/servers/heisenbridge @piegamesde
|
||||
/pkgs/servers/matrix-conduit @piegamesde @pstn
|
||||
/pkgs/servers/matrix-synapse/matrix-appservice-irc @piegamesde
|
||||
/nixos/modules/services/misc/heisenbridge.nix @piegamesde
|
||||
/nixos/modules/services/misc/matrix-appservice-irc.nix @piegamesde
|
||||
/nixos/modules/services/misc/matrix-conduit.nix @piegamesde @pstn
|
||||
/nixos/tests/matrix-appservice-irc.nix @piegamesde
|
||||
/nixos/tests/matrix-conduit.nix @piegamesde @pstn
|
||||
|
||||
+5
-1
@@ -11,6 +11,10 @@ under the terms of [COPYING](COPYING), which is an MIT-like license.
|
||||
|
||||
## Submitting changes
|
||||
|
||||
Read the ["Submitting changes"](https://nixos.org/nixpkgs/manual/#chap-submitting-changes) section of the nixpkgs manual. It explains how to write, test, and iterate on your change, and which branch to base your pull request against.
|
||||
|
||||
Below is a short excerpt of some points in there:
|
||||
|
||||
* Format the commit messages in the following way:
|
||||
|
||||
```
|
||||
@@ -40,7 +44,7 @@ under the terms of [COPYING](COPYING), which is an MIT-like license.
|
||||
* If there is no upstream license, `meta.license` should default to `lib.licenses.unfree`.
|
||||
* `meta.maintainers` must be set.
|
||||
|
||||
See the nixpkgs manual for more details on [standard meta-attributes](https://nixos.org/nixpkgs/manual/#sec-standard-meta-attributes) and on how to [submit changes to nixpkgs](https://nixos.org/nixpkgs/manual/#chap-submitting-changes).
|
||||
See the nixpkgs manual for more details on [standard meta-attributes](https://nixos.org/nixpkgs/manual/#sec-standard-meta-attributes).
|
||||
|
||||
## Writing good commit messages
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2003-2021 Eelco Dolstra and the Nixpkgs/NixOS contributors
|
||||
Copyright (c) 2003-2022 Eelco Dolstra and the Nixpkgs/NixOS contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
# pkgs.mkShell {#sec-pkgs-mkShell}
|
||||
|
||||
`pkgs.mkShell` is a special kind of derivation that is only useful when using
|
||||
it combined with `nix-shell`. It will in fact fail to instantiate when invoked
|
||||
with `nix-build`.
|
||||
`pkgs.mkShell` is a specialized `stdenv.mkDerivation` that removes some
|
||||
repetition when using it with `nix-shell` (or `nix develop`).
|
||||
|
||||
## Usage {#sec-pkgs-mkShell-usage}
|
||||
|
||||
Here is a common usage example:
|
||||
|
||||
```nix
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
pkgs.mkShell {
|
||||
# specify which packages to add to the shell environment
|
||||
packages = [ pkgs.gnumake ];
|
||||
# add all the dependencies, of the given packages, to the shell environment
|
||||
inputsFrom = with pkgs; [ hello gnutar ];
|
||||
|
||||
inputsFrom = [ pkgs.hello pkgs.gnutar ];
|
||||
|
||||
shellHook = ''
|
||||
export DEBUG=1
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
* `name` (default: `nix-shell`). Set the name of the derivation.
|
||||
* `packages` (default: `[]`). Add executable packages to the `nix-shell` environment.
|
||||
* `inputsFrom` (default: `[]`). Add build dependencies of the listed derivations to the `nix-shell` environment.
|
||||
* `shellHook` (default: `""`). Bash statements that are executed by `nix-shell`.
|
||||
|
||||
... all the attributes of `stdenv.mkDerivation`.
|
||||
|
||||
## Building the shell
|
||||
|
||||
This derivation output will contain a text file that contains a reference to
|
||||
all the build inputs. This is useful in CI where we want to make sure that
|
||||
every derivation, and its dependencies, build properly. Or when creating a GC
|
||||
root so that the build dependencies don't get garbage-collected.
|
||||
|
||||
@@ -47,6 +47,88 @@ These functions write `text` to the Nix store. This is useful for creating scrip
|
||||
|
||||
Many more commands wrap `writeTextFile` including `writeText`, `writeTextDir`, `writeScript`, and `writeScriptBin`. These are convenience functions over `writeTextFile`.
|
||||
|
||||
Here are a few examples:
|
||||
```nix
|
||||
# Writes my-file to /nix/store/<store path>
|
||||
writeTextFile {
|
||||
name = "my-file";
|
||||
text = ''
|
||||
Contents of File
|
||||
'';
|
||||
}
|
||||
# See also the `writeText` helper function below.
|
||||
|
||||
# Writes executable my-file to /nix/store/<store path>/bin/my-file
|
||||
writeTextFile {
|
||||
name = "my-file";
|
||||
text = ''
|
||||
Contents of File
|
||||
'';
|
||||
executable = true;
|
||||
destination = "/bin/my-file";
|
||||
}
|
||||
# Writes contents of file to /nix/store/<store path>
|
||||
writeText "my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
# Writes contents of file to /nix/store/<store path>/share/my-file
|
||||
writeTextDir "share/my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
# Writes my-file to /nix/store/<store path> and makes executable
|
||||
writeScript "my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
# Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
|
||||
writeScriptBin "my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
# Writes my-file to /nix/store/<store path> and makes executable.
|
||||
writeShellScript "my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
# Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
|
||||
writeShellScriptBin "my-file"
|
||||
''
|
||||
Contents of File
|
||||
'';
|
||||
|
||||
```
|
||||
|
||||
## `concatTextFile`, `concatText`, `concatScript` {#trivial-builder-concatText}
|
||||
|
||||
These functions concatenate `files` to the Nix store in a single file. This is useful for configuration files structured in lines of text. `concatTextFile` takes an attribute set and expects two arguments, `name` and `files`. `name` corresponds to the name used in the Nix store path. `files` will be the files to be concatenated. You can also set `executable` to true to make this file have the executable bit set.
|
||||
`concatText` and`concatScript` are simple wrappers over `concatTextFile`.
|
||||
|
||||
Here are a few examples:
|
||||
```nix
|
||||
|
||||
# Writes my-file to /nix/store/<store path>
|
||||
concatTextFile {
|
||||
name = "my-file";
|
||||
files = [ drv1 "${drv2}/path/to/file" ];
|
||||
}
|
||||
# See also the `concatText` helper function below.
|
||||
|
||||
# Writes executable my-file to /nix/store/<store path>/bin/my-file
|
||||
concatTextFile {
|
||||
name = "my-file";
|
||||
files = [ drv1 "${drv2}/path/to/file" ];
|
||||
executable = true;
|
||||
destination = "/bin/my-file";
|
||||
}
|
||||
# Writes contents of files to /nix/store/<store path>
|
||||
concatText "my-file" [ file1 file2 ]
|
||||
|
||||
# Writes contents of files to /nix/store/<store path>
|
||||
concatScript "my-file" [ file1 file2 ]
|
||||
```
|
||||
|
||||
## `writeShellApplication` {#trivial-builder-writeShellApplication}
|
||||
|
||||
This can be used to easily produce a shell script that has some dependencies (`runtimeInputs`). It automatically sets the `PATH` of the script to contain all of the listed inputs, sets some sanity shellopts (`errexit`, `nounset`, `pipefail`), and checks the resulting script with [`shellcheck`](https://github.com/koalaman/shellcheck).
|
||||
@@ -72,6 +154,26 @@ validation.
|
||||
## `symlinkJoin` {#trivial-builder-symlinkJoin}
|
||||
|
||||
This can be used to put many derivations into the same directory structure. It works by creating a new derivation and adding symlinks to each of the paths listed. It expects two arguments, `name`, and `paths`. `name` is the name used in the Nix store path for the created derivation. `paths` is a list of paths that will be symlinked. These paths can be to Nix store derivations or any other subdirectory contained within.
|
||||
Here is an example:
|
||||
```nix
|
||||
# adds symlinks of hello and stack to current build and prints "links added"
|
||||
symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; }
|
||||
```
|
||||
This creates a derivation with a directory structure like the following:
|
||||
```
|
||||
/nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample
|
||||
|-- bin
|
||||
| |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello
|
||||
| `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack
|
||||
`-- share
|
||||
|-- bash-completion
|
||||
| `-- completions
|
||||
| `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack
|
||||
|-- fish
|
||||
| `-- vendor_completions.d
|
||||
| `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish
|
||||
...
|
||||
```
|
||||
|
||||
## `writeReferencesToFile` {#trivial-builder-writeReferencesToFile}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ digraph {
|
||||
}
|
||||
```
|
||||
|
||||
[This GitHub Action](https://github.com/NixOS/nixpkgs/blob/master/.github/workflows/merge-staging.yml) brings changes from `master` to `staging-next` and from `staging-next` to `staging` every 6 hours.
|
||||
[This GitHub Action](https://github.com/NixOS/nixpkgs/blob/master/.github/workflows/periodic-merge-6h.yml) brings changes from `master` to `staging-next` and from `staging-next` to `staging` every 6 hours.
|
||||
|
||||
|
||||
### Master branch {#submitting-changes-master-branch}
|
||||
|
||||
@@ -84,7 +84,7 @@ To package Dotnet applications, you can use `buildDotnetModule`. This has simila
|
||||
<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 `[]`.
|
||||
* `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 `[]`. This gets done in the `preFixup` phase.
|
||||
* `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`.
|
||||
* `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used.
|
||||
|
||||
@@ -18,28 +18,13 @@
|
||||
in
|
||||
{
|
||||
lib = lib.extend (final: prev: {
|
||||
|
||||
nixos = import ./nixos/lib { lib = final; };
|
||||
|
||||
nixosSystem = { modules, ... } @ args:
|
||||
import ./nixos/lib/eval-config.nix (args // {
|
||||
modules =
|
||||
let
|
||||
vmConfig = (import ./nixos/lib/eval-config.nix
|
||||
(args // {
|
||||
modules = modules ++ [ ./nixos/modules/virtualisation/qemu-vm.nix ];
|
||||
})).config;
|
||||
|
||||
vmWithBootLoaderConfig = (import ./nixos/lib/eval-config.nix
|
||||
(args // {
|
||||
modules = modules ++ [
|
||||
./nixos/modules/virtualisation/qemu-vm.nix
|
||||
{ virtualisation.useBootLoader = true; }
|
||||
({ config, ... }: {
|
||||
virtualisation.useEFIBoot =
|
||||
config.boot.loader.systemd-boot.enable ||
|
||||
config.boot.loader.efi.canTouchEfiVariables;
|
||||
})
|
||||
];
|
||||
})).config;
|
||||
|
||||
moduleDeclarationFile =
|
||||
let
|
||||
# Even though `modules` is a mandatory argument for `nixosSystem`, it doesn't
|
||||
@@ -64,10 +49,9 @@
|
||||
".${final.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}.${self.shortRev or "dirty"}";
|
||||
system.nixos.revision = final.mkIf (self ? rev) self.rev;
|
||||
|
||||
system.build = {
|
||||
vm = vmConfig.system.build.vm;
|
||||
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
|
||||
};
|
||||
# NOTE: This assumes that `nixpkgs.config` is _not_ used when
|
||||
# nixpkgs.pkgs is set OR _module.args.pkgs is set.
|
||||
nixpkgs.config.path = self.outPath;
|
||||
}
|
||||
];
|
||||
});
|
||||
@@ -82,7 +66,7 @@
|
||||
}).nixos.manual.x86_64-linux;
|
||||
};
|
||||
|
||||
legacyPackages = forAllSystems (system: import ./. { inherit system; });
|
||||
legacyPackages = forAllSystems (system: import ./. { inherit system; config.path = self.outPath; });
|
||||
|
||||
nixosModules = {
|
||||
notDetected = import ./nixos/modules/installer/scan/not-detected.nix;
|
||||
|
||||
+10
-12
@@ -2,35 +2,33 @@
|
||||
|
||||
rec {
|
||||
|
||||
/* Print a trace message if pred is false.
|
||||
/* Throw if pred is false, else return pred.
|
||||
Intended to be used to augment asserts with helpful error messages.
|
||||
|
||||
Example:
|
||||
assertMsg false "nope"
|
||||
=> false
|
||||
stderr> trace: nope
|
||||
stderr> error: nope
|
||||
|
||||
assert (assertMsg ("foo" == "bar") "foo is not bar, silly"); ""
|
||||
stderr> trace: foo is not bar, silly
|
||||
stderr> assert failed at …
|
||||
assert assertMsg ("foo" == "bar") "foo is not bar, silly"; ""
|
||||
stderr> error: foo is not bar, silly
|
||||
|
||||
Type:
|
||||
assertMsg :: Bool -> String -> Bool
|
||||
*/
|
||||
# TODO(Profpatsch): add tests that check stderr
|
||||
assertMsg = pred: msg:
|
||||
if pred
|
||||
then true
|
||||
else builtins.trace msg false;
|
||||
pred || builtins.throw msg;
|
||||
|
||||
/* Specialized `assertMsg` for checking if val is one of the elements
|
||||
of a list. Useful for checking enums.
|
||||
|
||||
Example:
|
||||
let sslLibrary = "libressl"
|
||||
let sslLibrary = "libressl";
|
||||
in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ]
|
||||
=> false
|
||||
stderr> trace: sslLibrary must be one of "openssl", "bearssl", but is: "libressl"
|
||||
stderr> error: sslLibrary must be one of [
|
||||
stderr> "openssl"
|
||||
stderr> "bearssl"
|
||||
stderr> ], but is: "libressl"
|
||||
|
||||
Type:
|
||||
assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool
|
||||
|
||||
+16
-18
@@ -3,9 +3,9 @@
|
||||
|
||||
let
|
||||
inherit (builtins) head tail length;
|
||||
inherit (lib.trivial) and;
|
||||
inherit (lib.trivial) id;
|
||||
inherit (lib.strings) concatStringsSep sanitizeDerivationName;
|
||||
inherit (lib.lists) foldr foldl' concatMap concatLists elemAt;
|
||||
inherit (lib.lists) foldr foldl' concatMap concatLists elemAt all;
|
||||
in
|
||||
|
||||
rec {
|
||||
@@ -73,9 +73,9 @@ rec {
|
||||
getAttrFromPath ["z" "z"] x
|
||||
=> error: cannot find attribute `z.z'
|
||||
*/
|
||||
getAttrFromPath = attrPath: set:
|
||||
getAttrFromPath = attrPath:
|
||||
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
|
||||
in attrByPath attrPath (abort errorMsg) set;
|
||||
in attrByPath attrPath (abort errorMsg);
|
||||
|
||||
|
||||
/* Return the specified attributes from a set.
|
||||
@@ -154,12 +154,12 @@ rec {
|
||||
foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }]
|
||||
=> { a = [ 2 3 ]; }
|
||||
*/
|
||||
foldAttrs = op: nul: list_of_attrs:
|
||||
foldAttrs = op: nul:
|
||||
foldr (n: a:
|
||||
foldr (name: o:
|
||||
o // { ${name} = op n.${name} (a.${name} or nul); }
|
||||
) a (attrNames n)
|
||||
) {} list_of_attrs;
|
||||
) {};
|
||||
|
||||
|
||||
/* Recursively collect sets that verify a given predicate named `pred'
|
||||
@@ -295,14 +295,14 @@ rec {
|
||||
*/
|
||||
mapAttrsRecursiveCond = cond: f: set:
|
||||
let
|
||||
recurse = path: set:
|
||||
recurse = path:
|
||||
let
|
||||
g =
|
||||
name: value:
|
||||
if isAttrs value && cond value
|
||||
then recurse (path ++ [name]) value
|
||||
else f (path ++ [name]) value;
|
||||
in mapAttrs g set;
|
||||
in mapAttrs g;
|
||||
in recurse [] set;
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ rec {
|
||||
value = f name (catAttrs name sets);
|
||||
}) names);
|
||||
|
||||
/* Implementation note: Common names appear multiple times in the list of
|
||||
/* Implementation note: Common names appear multiple times in the list of
|
||||
names, hopefully this does not affect the system because the maximal
|
||||
laziness avoid computing twice the same expression and listToAttrs does
|
||||
not care about duplicated attribute names.
|
||||
@@ -378,7 +378,8 @@ rec {
|
||||
zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
|
||||
=> { a = ["x" "y"]; b = ["z"] }
|
||||
*/
|
||||
zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets;
|
||||
zipAttrsWith =
|
||||
builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
|
||||
/* Like `zipAttrsWith' with `(name: values: values)' as the function.
|
||||
|
||||
Example:
|
||||
@@ -419,8 +420,8 @@ rec {
|
||||
let f = attrPath:
|
||||
zipAttrsWith (n: values:
|
||||
let here = attrPath ++ [n]; in
|
||||
if tail values == []
|
||||
|| pred here (head (tail values)) (head values) then
|
||||
if length values == 1
|
||||
|| pred here (elemAt values 1) (head values) then
|
||||
head values
|
||||
else
|
||||
f here values
|
||||
@@ -446,10 +447,7 @@ rec {
|
||||
}
|
||||
|
||||
*/
|
||||
recursiveUpdate = lhs: rhs:
|
||||
recursiveUpdateUntil (path: lhs: rhs:
|
||||
!(isAttrs lhs && isAttrs rhs)
|
||||
) lhs rhs;
|
||||
recursiveUpdate = recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs));
|
||||
|
||||
/* Returns true if the pattern is contained in the set. False otherwise.
|
||||
|
||||
@@ -458,8 +456,8 @@ rec {
|
||||
=> true
|
||||
*/
|
||||
matchAttrs = pattern: attrs: assert isAttrs pattern;
|
||||
foldr and true (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
||||
let pat = head values; val = head (tail values); in
|
||||
all id (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
||||
let pat = head values; val = elemAt values 1; in
|
||||
if length values == 1 then false
|
||||
else if isAttrs pat then isAttrs val && matchAttrs pat val
|
||||
else pat == val
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ let
|
||||
stringLength sub substring tail trace;
|
||||
inherit (self.trivial) id const pipe concat or and bitAnd bitOr bitXor
|
||||
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
|
||||
importJSON importTOML warn warnIf throwIfNot
|
||||
importJSON importTOML warn warnIf throwIfNot checkListOfEnum
|
||||
info showWarnings nixpkgsVersion version
|
||||
mod compare splitByAndCompare functionArgs setFunctionArgs isFunction
|
||||
toHexString toBaseDigits;
|
||||
|
||||
@@ -67,6 +67,11 @@ in mkLicense lset) ({
|
||||
free = false;
|
||||
};
|
||||
|
||||
aom = {
|
||||
fullName = "Alliance for Open Media Patent License 1.0";
|
||||
url = "https://aomedia.org/license/patent-license/";
|
||||
};
|
||||
|
||||
apsl20 = {
|
||||
spdxId = "APSL-2.0";
|
||||
fullName = "Apple Public Source License 2.0";
|
||||
|
||||
+7
-8
@@ -37,6 +37,7 @@ let
|
||||
toList
|
||||
types
|
||||
warnIf
|
||||
zipAttrsWith
|
||||
;
|
||||
inherit (lib.options)
|
||||
isOption
|
||||
@@ -442,10 +443,11 @@ rec {
|
||||
}
|
||||
*/
|
||||
byName = attr: f: modules:
|
||||
foldl' (acc: module:
|
||||
if !(builtins.isAttrs module.${attr}) then
|
||||
zipAttrsWith (n: concatLists)
|
||||
(map (module: let subtree = module.${attr}; in
|
||||
if !(builtins.isAttrs subtree) then
|
||||
throw ''
|
||||
You're trying to declare a value of type `${builtins.typeOf module.${attr}}'
|
||||
You're trying to declare a value of type `${builtins.typeOf subtree}'
|
||||
rather than an attribute-set for the option
|
||||
`${builtins.concatStringsSep "." prefix}'!
|
||||
|
||||
@@ -454,11 +456,8 @@ rec {
|
||||
this option by e.g. referring to `man 5 configuration.nix'!
|
||||
''
|
||||
else
|
||||
acc // (mapAttrs (n: v:
|
||||
(acc.${n} or []) ++ f module v
|
||||
) module.${attr}
|
||||
)
|
||||
) {} modules;
|
||||
mapAttrs (n: f module) subtree
|
||||
) modules);
|
||||
# an attrset 'name' => list of submodules that declare ‘name’.
|
||||
declsByName = byName "options" (module: option:
|
||||
[{ inherit (module) _file; options = option; }]
|
||||
|
||||
@@ -347,6 +347,23 @@ rec {
|
||||
*/
|
||||
throwIfNot = cond: msg: if cond then x: x else throw msg;
|
||||
|
||||
/* Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
|
||||
|
||||
Example:
|
||||
let colorVariants = ["bright" "dark" "black"]
|
||||
in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
|
||||
=>
|
||||
error: color variants: bright, black unexpected; valid ones: standard, light, dark
|
||||
|
||||
Type: String -> List ComparableVal -> List ComparableVal -> a -> a
|
||||
*/
|
||||
checkListOfEnum = msg: valid: given:
|
||||
let
|
||||
unexpected = lib.subtractLists valid given;
|
||||
in
|
||||
lib.throwIfNot (unexpected == [])
|
||||
"${msg}: ${builtins.concatStringsSep ", " (builtins.map builtins.toString unexpected)} unexpected; valid ones: ${builtins.concatStringsSep ", " (builtins.map builtins.toString valid)}";
|
||||
|
||||
info = msg: builtins.trace "INFO: ${msg}";
|
||||
|
||||
showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
|
||||
|
||||
@@ -300,6 +300,19 @@ rec {
|
||||
inherit (str) merge;
|
||||
};
|
||||
|
||||
# Allow a newline character at the end and trim it in the merge function.
|
||||
singleLineStr =
|
||||
let
|
||||
inherit (strMatching "[^\n\r]*\n?") check merge;
|
||||
in
|
||||
mkOptionType {
|
||||
name = "singleLineStr";
|
||||
description = "(optionally newline-terminated) single-line string";
|
||||
inherit check;
|
||||
merge = loc: defs:
|
||||
lib.removeSuffix "\n" (merge loc defs);
|
||||
};
|
||||
|
||||
strMatching = pattern: mkOptionType {
|
||||
name = "strMatching ${escapeNixString pattern}";
|
||||
description = "string matching the pattern ${pattern}";
|
||||
|
||||
+185
-14
@@ -1950,6 +1950,12 @@
|
||||
githubId = 543423;
|
||||
name = "Alex Wied";
|
||||
};
|
||||
cfhammill = {
|
||||
email = "cfhammill@gmail.com";
|
||||
github = "cfhammill";
|
||||
githubId = 7467038;
|
||||
name = "Chris Hammill";
|
||||
};
|
||||
cfouche = {
|
||||
email = "chaddai.fouche@gmail.com";
|
||||
github = "Chaddai";
|
||||
@@ -2285,6 +2291,12 @@
|
||||
githubId = 34317;
|
||||
name = "Corey O'Connor";
|
||||
};
|
||||
CodeLongAndProsper90 = {
|
||||
github = "CodeLongAndProsper90";
|
||||
githubId = 50145141;
|
||||
email = "jupiter@m.rdis.dev";
|
||||
name = "Scott Little";
|
||||
};
|
||||
codsl = {
|
||||
email = "codsl@riseup.net";
|
||||
github = "codsl";
|
||||
@@ -2854,6 +2866,12 @@
|
||||
githubId = 706758;
|
||||
name = "Christian Gerbrandt";
|
||||
};
|
||||
derekcollison = {
|
||||
email = "derek@nats.io";
|
||||
github = "derekcollison";
|
||||
githubId = 90097;
|
||||
name = "Derek Collison";
|
||||
};
|
||||
DerGuteMoritz = {
|
||||
email = "moritz@twoticketsplease.de";
|
||||
github = "DerGuteMoritz";
|
||||
@@ -3188,6 +3206,12 @@
|
||||
githubId = 24791219;
|
||||
name = "Jakob Neufeld";
|
||||
};
|
||||
dsalaza4 = {
|
||||
email = "podany270895@gmail.com";
|
||||
github = "dsalaza4";
|
||||
githubId = 11205987;
|
||||
name = "Daniel Salazar";
|
||||
};
|
||||
dschrempf = {
|
||||
name = "Dominik Schrempf";
|
||||
email = "dominik.schrempf@gmail.com";
|
||||
@@ -3429,6 +3453,12 @@
|
||||
githubId = 4742;
|
||||
name = "Aaron Bull Schaefer";
|
||||
};
|
||||
elatov = {
|
||||
email = "elatov@gmail.com";
|
||||
github = "elatov";
|
||||
githubId = 7494394;
|
||||
name = "Karim Elatov";
|
||||
};
|
||||
eleanor = {
|
||||
email = "dejan@proteansec.com";
|
||||
github = "proteansec";
|
||||
@@ -4110,12 +4140,6 @@
|
||||
githubId = 7551358;
|
||||
name = "Frede Emil";
|
||||
};
|
||||
freepotion = {
|
||||
email = "42352817+freepotion@users.noreply.github.com";
|
||||
github = "freepotion";
|
||||
githubId = 42352817;
|
||||
name = "Free Potion";
|
||||
};
|
||||
freezeboy = {
|
||||
email = "freezeboy@users.noreply.github.com";
|
||||
github = "freezeboy";
|
||||
@@ -4238,6 +4262,16 @@
|
||||
githubId = 1313787;
|
||||
name = "Gabriel Gonzalez";
|
||||
};
|
||||
gador = {
|
||||
email = "florian.brandes@posteo.de";
|
||||
github = "gador";
|
||||
githubId = 1883533;
|
||||
name = "Florian Brandes";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0xBBB3E40E53797FD9";
|
||||
fingerprint = "0200 3EF8 8D2B CF2D 8F00 FFDC BBB3 E40E 5379 7FD9";
|
||||
}];
|
||||
};
|
||||
gal_bolle = {
|
||||
email = "florent.becker@ens-lyon.org";
|
||||
github = "FlorentBecker";
|
||||
@@ -4437,6 +4471,16 @@
|
||||
githubId = 1621335;
|
||||
name = "Andrew Trachenko";
|
||||
};
|
||||
gordias = {
|
||||
name = "Gordias";
|
||||
email = "gordias@disroot.org";
|
||||
github = "NotGordias";
|
||||
githubId = 94724133;
|
||||
keys = [{
|
||||
longkeyid = "ed25519/0x5D47284830FAA4FA";
|
||||
fingerprint = "C006 B8A0 0618 F3B6 E0E4 2ECD 5D47 2848 30FA A4FA";
|
||||
}];
|
||||
};
|
||||
govanify = {
|
||||
name = "Gauvain 'GovanifY' Roussel-Tarbouriech";
|
||||
email = "gauvain@govanify.com";
|
||||
@@ -5670,14 +5714,12 @@
|
||||
github = "jmc-figueira";
|
||||
githubId = 6634716;
|
||||
name = "João Figueira";
|
||||
keys = [
|
||||
|
||||
keys = [r
|
||||
# GitHub signing key
|
||||
{
|
||||
longkeyid = "rsa4096/0xDC7AE56AE98E02D7";
|
||||
fingerprint = "EC08 7AA3 DEAD A972 F015 6371 DC7A E56A E98E 02D7";
|
||||
}
|
||||
|
||||
# Email encryption
|
||||
{
|
||||
longkeyid = "ed25519/0x197F9A632D139E30";
|
||||
@@ -5971,6 +6013,12 @@
|
||||
githubId = 11947756;
|
||||
name = "Julien Dehos";
|
||||
};
|
||||
julienmalka = {
|
||||
email = "julien.malka@me.com";
|
||||
github = "JulienMalka";
|
||||
githubId = 1792886;
|
||||
name = "Julien Malka";
|
||||
};
|
||||
julm = {
|
||||
email = "julm+nixpkgs@sourcephile.fr";
|
||||
github = "ju1m";
|
||||
@@ -6069,6 +6117,13 @@
|
||||
github = "k4leg";
|
||||
githubId = 39882583;
|
||||
};
|
||||
k900 = {
|
||||
name = "Ilya K.";
|
||||
email = "me@0upti.me";
|
||||
github = "K900";
|
||||
githubId = 386765;
|
||||
matrix = "@k900:0upti.me";
|
||||
};
|
||||
kaction = {
|
||||
name = "Dmitry Bogatov";
|
||||
email = "KAction@disroot.org";
|
||||
@@ -6375,7 +6430,7 @@
|
||||
};
|
||||
|
||||
kmein = {
|
||||
email = "kieran.meinhardt@gmail.com";
|
||||
email = "kmein@posteo.de";
|
||||
name = "Kierán Meinhardt";
|
||||
github = "kmein";
|
||||
githubId = 10352507;
|
||||
@@ -6573,7 +6628,7 @@
|
||||
};
|
||||
kylesferrazza = {
|
||||
name = "Kyle Sferrazza";
|
||||
email = "kyle.sferrazza@gmail.com";
|
||||
email = "nixpkgs@kylesferrazza.com";
|
||||
|
||||
github = "kylesferrazza";
|
||||
githubId = 6677292;
|
||||
@@ -6617,6 +6672,12 @@
|
||||
githubId = 55911173;
|
||||
name = "Gwendolyn Quasebarth";
|
||||
};
|
||||
lammermann = {
|
||||
email = "k.o.b.e.r@web.de";
|
||||
github = "lammermann";
|
||||
githubId = 695526;
|
||||
name = "Benjamin Kober";
|
||||
};
|
||||
larsr = {
|
||||
email = "Lars.Rasmusson@gmail.com";
|
||||
github = "larsr";
|
||||
@@ -6757,6 +6818,17 @@
|
||||
fingerprint = "CC50 F82C 985D 2679 0703 AF15 19B0 82B3 DEFE 5451";
|
||||
}];
|
||||
};
|
||||
leixb = {
|
||||
email = "abone9999+nixpkgs@gmail.com";
|
||||
matrix = "@leix_b:matrix.org";
|
||||
github = "LeixB";
|
||||
githubId = 17183803;
|
||||
name = "Aleix Boné";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0xFC035BB2BB28E15D";
|
||||
fingerprint = "63D3 F436 EDE8 7E1F 1292 24AF FC03 5BB2 BB28 E15D";
|
||||
}];
|
||||
};
|
||||
lejonet = {
|
||||
email = "daniel@kuehn.se";
|
||||
github = "lejonet";
|
||||
@@ -6944,6 +7016,12 @@
|
||||
githubId = 22085373;
|
||||
name = "Luis Hebendanz";
|
||||
};
|
||||
lunarequest = {
|
||||
email = "nullarequest@vivlaid.net";
|
||||
github = "Lunarequest";
|
||||
githubId = 30698906;
|
||||
name = "Advaith Madhukar"; #this is my legal name, I prefer Luna; please keep that in mind!
|
||||
};
|
||||
lionello = {
|
||||
email = "lio@lunesu.com";
|
||||
github = "lionello";
|
||||
@@ -7133,6 +7211,12 @@
|
||||
githubId = 13791;
|
||||
name = "Luke Gorrie";
|
||||
};
|
||||
luker = {
|
||||
email = "luker@fenrirproject.org";
|
||||
github = "LucaFulchir";
|
||||
githubId = 2486026;
|
||||
name = "Luca Fulchir";
|
||||
};
|
||||
lumi = {
|
||||
email = "lumi@pew.im";
|
||||
github = "lumi-me-not";
|
||||
@@ -7184,6 +7268,12 @@
|
||||
email = "wheatdoge@gmail.com";
|
||||
name = "Tim Liou";
|
||||
};
|
||||
m00wl = {
|
||||
name = "Moritz Lumme";
|
||||
email = "moritz.lumme@gmail.com";
|
||||
github = "m00wl";
|
||||
githubId = 46034439;
|
||||
};
|
||||
m1cr0man = {
|
||||
email = "lucas+nix@m1cr0man.com";
|
||||
github = "m1cr0man";
|
||||
@@ -8487,10 +8577,10 @@
|
||||
name = "Xinhao Luo";
|
||||
};
|
||||
newam = {
|
||||
email = "alexmgit@protonmail.com";
|
||||
email = "alex@thinglab.org";
|
||||
github = "newAM";
|
||||
githubId = 7845120;
|
||||
name = "Alex M.";
|
||||
name = "Alex Martens";
|
||||
};
|
||||
nikitavoloboev = {
|
||||
email = "nikita.voloboev@gmail.com";
|
||||
@@ -8894,6 +8984,12 @@
|
||||
githubId = 72201;
|
||||
name = "Ole Jørgen Brønner";
|
||||
};
|
||||
ollieB = {
|
||||
email = "1237862+oliverbunting@users.noreply.github.com";
|
||||
github = "oliverbunting";
|
||||
githubId = 1237862;
|
||||
name = "Ollie Bunting";
|
||||
};
|
||||
olynch = {
|
||||
email = "owen@olynch.me";
|
||||
github = "olynch";
|
||||
@@ -9797,6 +9893,13 @@
|
||||
githubId = 1016742;
|
||||
name = "Rafael García";
|
||||
};
|
||||
raitobezarius = {
|
||||
email = "ryan@lahfa.xyz";
|
||||
matrix = "@raitobezarius:matrix.org";
|
||||
github = "RaitoBezarius";
|
||||
githubId = 314564;
|
||||
name = "Ryan Lahfa";
|
||||
};
|
||||
raquelgb = {
|
||||
email = "raquel.garcia.bautista@gmail.com";
|
||||
github = "raquelgb";
|
||||
@@ -10040,6 +10143,13 @@
|
||||
githubId = 16779;
|
||||
name = "Rickard Nilsson";
|
||||
};
|
||||
ricochet = {
|
||||
email = "behayes2@gmail.com";
|
||||
github = "ricochet";
|
||||
githubId = 974323;
|
||||
matrix = "@ricochetcode:matrix.org";
|
||||
name = "Bailey Hayes";
|
||||
};
|
||||
riey = {
|
||||
email = "creeper844@gmail.com";
|
||||
github = "Riey";
|
||||
@@ -10801,6 +10911,16 @@
|
||||
githubId = 6720672;
|
||||
name = "Shane Pearlman";
|
||||
};
|
||||
shanesveller = {
|
||||
email = "shane@sveller.dev";
|
||||
github = "shanesveller";
|
||||
githubId = 831;
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x9210C218023C15CD";
|
||||
fingerprint = "F83C 407C ADC4 5A0F 1F2F 44E8 9210 C218 023C 15CD";
|
||||
}];
|
||||
name = "Shane Sveller";
|
||||
};
|
||||
shawndellysse = {
|
||||
email = "sdellysse@gmail.com";
|
||||
github = "shawndellysse";
|
||||
@@ -10914,7 +11034,7 @@
|
||||
name = "Yann Hodique";
|
||||
};
|
||||
sikmir = {
|
||||
email = "sikmir@gmail.com";
|
||||
email = "sikmir@disroot.org";
|
||||
github = "sikmir";
|
||||
githubId = 688044;
|
||||
name = "Nikolay Korotkiy";
|
||||
@@ -11059,6 +11179,12 @@
|
||||
fingerprint = "4242 834C D401 86EF 8281 4093 86E3 0E5A 0F5F C59C";
|
||||
}];
|
||||
};
|
||||
smasher164 = {
|
||||
email = "aindurti@gmail.com";
|
||||
github = "smasher164";
|
||||
githubId = 12636891;
|
||||
name = "Akhil Indurti";
|
||||
};
|
||||
smironov = {
|
||||
email = "grrwlf@gmail.com";
|
||||
github = "grwlf";
|
||||
@@ -11740,6 +11866,12 @@
|
||||
githubId = 378734;
|
||||
name = "TG ⊗ Θ";
|
||||
};
|
||||
tgunnoe = {
|
||||
email = "t@gvno.net";
|
||||
github = "tgunnoe";
|
||||
githubId = 7254833;
|
||||
name = "Taylor Gunnoe";
|
||||
};
|
||||
th0rgal = {
|
||||
email = "thomas.marchand@tuta.io";
|
||||
github = "Th0rgal";
|
||||
@@ -12138,6 +12270,12 @@
|
||||
githubId = 1183303;
|
||||
name = "Jakob Klepp";
|
||||
};
|
||||
trundle = {
|
||||
name = "Andreas Stührk";
|
||||
email = "andy@hammerhartes.de";
|
||||
github = "Trundle";
|
||||
githubId = 332418;
|
||||
};
|
||||
tscholak = {
|
||||
email = "torsten.scholak@googlemail.com";
|
||||
github = "tscholak";
|
||||
@@ -12623,6 +12761,16 @@
|
||||
githubId = 3889405;
|
||||
name = "vyp";
|
||||
};
|
||||
wackbyte = {
|
||||
name = "wackbyte";
|
||||
email = "wackbyte@pm.me";
|
||||
github = "wackbyte";
|
||||
githubId = 29505620;
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x937F2AE5CCEFBF59";
|
||||
fingerprint = "E595 7FE4 FEF6 714B 1AD3 1483 937F 2AE5 CCEF BF59";
|
||||
}];
|
||||
};
|
||||
wakira = {
|
||||
name = "Sheng Wang";
|
||||
email = "sheng@a64.work";
|
||||
@@ -12655,6 +12803,12 @@
|
||||
email = "kirill.wedens@gmail.com";
|
||||
name = "wedens";
|
||||
};
|
||||
wegank = {
|
||||
name = "Weijia Wang";
|
||||
email = "contact@weijia.wang";
|
||||
github = "wegank";
|
||||
githubId = 9713184;
|
||||
};
|
||||
weihua = {
|
||||
email = "luwh364@gmail.com";
|
||||
github = "weihua-lu";
|
||||
@@ -13590,10 +13744,27 @@
|
||||
github = "jpagex";
|
||||
githubId = 635768;
|
||||
};
|
||||
portothree = {
|
||||
name = "Gustavo Porto";
|
||||
email = "gustavoporto@ya.ru";
|
||||
github = "portothree";
|
||||
githubId = 3718120;
|
||||
};
|
||||
pwoelfel = {
|
||||
name = "Philipp Woelfel";
|
||||
email = "philipp.woelfel@gmail.com";
|
||||
github = "PhilippWoelfel";
|
||||
githubId = 19400064;
|
||||
};
|
||||
qbit = {
|
||||
name = "Aaron Bieber";
|
||||
email = "aaron@bolddaemon.com";
|
||||
github = "qbit";
|
||||
githubId = 68368;
|
||||
matrix = "@qbit:tapenet.org";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x1F81112D62A9ADCE";
|
||||
fingerprint = "3586 3350 BFEA C101 DB1A 4AF0 1F81 112D 62A9 ADCE";
|
||||
}];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,29 +81,71 @@ def make_request(url: str) -> urllib.request.Request:
|
||||
headers["Authorization"] = f"token {token}"
|
||||
return urllib.request.Request(url, headers=headers)
|
||||
|
||||
@dataclass
|
||||
class PluginDesc:
|
||||
owner: str
|
||||
repo: str
|
||||
branch: str
|
||||
alias: Optional[str]
|
||||
|
||||
|
||||
class Repo:
|
||||
def __init__(
|
||||
self, owner: str, name: str, branch: str, alias: Optional[str]
|
||||
self, uri: str, branch: str, alias: Optional[str]
|
||||
) -> None:
|
||||
self.owner = owner
|
||||
self.name = name
|
||||
self.uri = uri
|
||||
'''Url to the repo'''
|
||||
self.branch = branch
|
||||
self.alias = alias
|
||||
self.redirect: Dict[str, str] = {}
|
||||
|
||||
def url(self, path: str) -> str:
|
||||
return urljoin(f"https://github.com/{self.owner}/{self.name}/", path)
|
||||
@property
|
||||
def name(self):
|
||||
return self.uri.split('/')[-1]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Repo({self.owner}, {self.name})"
|
||||
return f"Repo({self.name}, {self.uri})"
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def has_submodules(self) -> bool:
|
||||
return True
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def latest_commit(self) -> Tuple[str, datetime]:
|
||||
loaded = self._prefetch(None)
|
||||
updated = datetime.strptime(loaded['date'], "%Y-%m-%dT%H:%M:%S%z")
|
||||
|
||||
return loaded['rev'], updated
|
||||
|
||||
def _prefetch(self, ref: Optional[str]):
|
||||
cmd = ["nix-prefetch-git", "--quiet", "--fetch-submodules", self.uri]
|
||||
if ref is not None:
|
||||
cmd.append(ref)
|
||||
log.debug(cmd)
|
||||
data = subprocess.check_output(cmd)
|
||||
loaded = json.loads(data)
|
||||
return loaded
|
||||
|
||||
def prefetch(self, ref: Optional[str]) -> str:
|
||||
loaded = self._prefetch(ref)
|
||||
return loaded["sha256"]
|
||||
|
||||
def as_nix(self, plugin: "Plugin") -> str:
|
||||
return f'''fetchgit {{
|
||||
url = "{self.uri}";
|
||||
rev = "{plugin.commit}";
|
||||
sha256 = "{plugin.sha256}";
|
||||
}}'''
|
||||
|
||||
|
||||
class RepoGitHub(Repo):
|
||||
def __init__(
|
||||
self, owner: str, repo: str, branch: str, alias: Optional[str]
|
||||
) -> None:
|
||||
self.owner = owner
|
||||
self.repo = repo
|
||||
'''Url to the repo'''
|
||||
super().__init__(self.url(""), branch, alias)
|
||||
log.debug("Instantiating github repo %s/%s", self.owner, self.repo)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.repo
|
||||
|
||||
def url(self, path: str) -> str:
|
||||
return urljoin(f"https://github.com/{self.owner}/{self.name}/", path)
|
||||
|
||||
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
|
||||
def has_submodules(self) -> bool:
|
||||
@@ -122,7 +164,7 @@ class Repo:
|
||||
commit_url = self.url(f"commits/{self.branch}.atom")
|
||||
commit_req = make_request(commit_url)
|
||||
with urllib.request.urlopen(commit_req, timeout=10) as req:
|
||||
self.check_for_redirect(commit_url, req)
|
||||
self._check_for_redirect(commit_url, req)
|
||||
xml = req.read()
|
||||
root = ET.fromstring(xml)
|
||||
latest_entry = root.find(ATOM_ENTRY)
|
||||
@@ -137,7 +179,7 @@ class Repo:
|
||||
updated = datetime.strptime(updated_tag.text, "%Y-%m-%dT%H:%M:%SZ")
|
||||
return Path(str(url.path)).name, updated
|
||||
|
||||
def check_for_redirect(self, url: str, req: http.client.HTTPResponse):
|
||||
def _check_for_redirect(self, url: str, req: http.client.HTTPResponse):
|
||||
response_url = req.geturl()
|
||||
if url != response_url:
|
||||
new_owner, new_name = (
|
||||
@@ -150,11 +192,13 @@ class Repo:
|
||||
new_plugin = plugin_line.format(owner=new_owner, name=new_name)
|
||||
self.redirect[old_plugin] = new_plugin
|
||||
|
||||
def prefetch_git(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
["nix-prefetch-git", "--fetch-submodules", self.url(""), ref]
|
||||
)
|
||||
return json.loads(data)["sha256"]
|
||||
|
||||
def prefetch(self, commit: str) -> str:
|
||||
if self.has_submodules():
|
||||
sha256 = super().prefetch(commit)
|
||||
else:
|
||||
sha256 = self.prefetch_github(commit)
|
||||
return sha256
|
||||
|
||||
def prefetch_github(self, ref: str) -> str:
|
||||
data = subprocess.check_output(
|
||||
@@ -162,6 +206,33 @@ class Repo:
|
||||
)
|
||||
return data.strip().decode("utf-8")
|
||||
|
||||
def as_nix(self, plugin: "Plugin") -> str:
|
||||
if plugin.has_submodules:
|
||||
submodule_attr = "\n fetchSubmodules = true;"
|
||||
else:
|
||||
submodule_attr = ""
|
||||
|
||||
return f'''fetchFromGitHub {{
|
||||
owner = "{self.owner}";
|
||||
repo = "{self.repo}";
|
||||
rev = "{plugin.commit}";
|
||||
sha256 = "{plugin.sha256}";{submodule_attr}
|
||||
}}'''
|
||||
|
||||
|
||||
@dataclass
|
||||
class PluginDesc:
|
||||
repo: Repo
|
||||
branch: str
|
||||
alias: Optional[str]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self.alias is None:
|
||||
return self.repo.name
|
||||
else:
|
||||
return self.alias
|
||||
|
||||
|
||||
class Plugin:
|
||||
def __init__(
|
||||
@@ -193,6 +264,7 @@ class Plugin:
|
||||
return copy
|
||||
|
||||
|
||||
|
||||
class Editor:
|
||||
"""The configuration of the update script."""
|
||||
|
||||
@@ -241,9 +313,9 @@ class Editor:
|
||||
|
||||
def create_parser(self):
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
f"Updates nix derivations for {self.name} plugins"
|
||||
f"By default from {self.default_in} to {self.default_out}"
|
||||
description=(f"""
|
||||
Updates nix derivations for {self.name} plugins.\n
|
||||
By default from {self.default_in} to {self.default_out}"""
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
@@ -273,7 +345,7 @@ class Editor:
|
||||
dest="proc",
|
||||
type=int,
|
||||
default=30,
|
||||
help="Number of concurrent processes to spawn.",
|
||||
help="Number of concurrent processes to spawn. Export GITHUB_API_TOKEN allows higher values.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-commit", "-n", action="store_true", default=False,
|
||||
@@ -305,7 +377,7 @@ class CleanEnvironment(object):
|
||||
|
||||
def get_current_plugins(editor: Editor) -> List[Plugin]:
|
||||
with CleanEnvironment():
|
||||
cmd = ["nix", "eval", "--impure", "--json", "--expr", editor.get_plugins]
|
||||
cmd = ["nix", "eval", "--extra-experimental-features", "nix-command", "--impure", "--json", "--expr", editor.get_plugins]
|
||||
log.debug("Running command %s", cmd)
|
||||
out = subprocess.check_output(cmd)
|
||||
data = json.loads(out)
|
||||
@@ -320,26 +392,24 @@ def prefetch_plugin(
|
||||
p: PluginDesc,
|
||||
cache: "Optional[Cache]" = None,
|
||||
) -> Tuple[Plugin, Dict[str, str]]:
|
||||
user, repo_name, branch, alias = p.owner, p.repo, p.branch, p.alias
|
||||
log.info(f"Fetching last commit for plugin {user}/{repo_name}@{branch}")
|
||||
repo = Repo(user, repo_name, branch, alias)
|
||||
repo, branch, alias = p.repo, p.branch, p.alias
|
||||
name = alias or p.repo.name
|
||||
commit = None
|
||||
log.info(f"Fetching last commit for plugin {name} from {repo.uri}@{branch}")
|
||||
commit, date = repo.latest_commit()
|
||||
has_submodules = repo.has_submodules()
|
||||
cached_plugin = cache[commit] if cache else None
|
||||
if cached_plugin is not None:
|
||||
log.debug("Cache hit !")
|
||||
cached_plugin.name = alias or repo_name
|
||||
cached_plugin.name = name
|
||||
cached_plugin.date = date
|
||||
return cached_plugin, repo.redirect
|
||||
|
||||
print(f"prefetch {user}/{repo_name}")
|
||||
if has_submodules:
|
||||
sha256 = repo.prefetch_git(commit)
|
||||
else:
|
||||
sha256 = repo.prefetch_github(commit)
|
||||
has_submodules = repo.has_submodules()
|
||||
print(f"prefetch {name}")
|
||||
sha256 = repo.prefetch(commit)
|
||||
|
||||
return (
|
||||
Plugin(alias or repo_name, commit, has_submodules, sha256, date=date),
|
||||
Plugin(name, commit, has_submodules, sha256, date=date),
|
||||
repo.redirect,
|
||||
)
|
||||
|
||||
@@ -360,16 +430,17 @@ def print_download_error(plugin: str, ex: Exception):
|
||||
|
||||
|
||||
def check_results(
|
||||
results: List[Tuple[str, str, Union[Exception, Plugin], Dict[str, str]]]
|
||||
) -> Tuple[List[Tuple[str, str, Plugin]], Dict[str, str]]:
|
||||
results: List[Tuple[PluginDesc, Union[Exception, Plugin], Dict[str, str]]]
|
||||
) -> Tuple[List[Tuple[PluginDesc, Plugin]], Dict[str, str]]:
|
||||
''' '''
|
||||
failures: List[Tuple[str, Exception]] = []
|
||||
plugins = []
|
||||
redirects: Dict[str, str] = {}
|
||||
for (owner, name, result, redirect) in results:
|
||||
for (pdesc, result, redirect) in results:
|
||||
if isinstance(result, Exception):
|
||||
failures.append((name, result))
|
||||
failures.append((pdesc.name, result))
|
||||
else:
|
||||
plugins.append((owner, name, result))
|
||||
plugins.append((pdesc, result))
|
||||
redirects.update(redirect)
|
||||
|
||||
print(f"{len(results) - len(failures)} plugins were checked", end="")
|
||||
@@ -384,17 +455,29 @@ def check_results(
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
def make_repo(uri, branch, alias) -> Repo:
|
||||
'''Instantiate a Repo with the correct specialization depending on server (gitub spec)'''
|
||||
# dumb check to see if it's of the form owner/repo (=> github) or https://...
|
||||
res = uri.split('/')
|
||||
if len(res) <= 2:
|
||||
repo = RepoGitHub(res[0], res[1], branch, alias)
|
||||
else:
|
||||
repo = Repo(uri.strip(), branch, alias)
|
||||
return repo
|
||||
|
||||
def parse_plugin_line(line: str) -> PluginDesc:
|
||||
branch = "HEAD"
|
||||
alias = None
|
||||
name, repo = line.split("/")
|
||||
if " as " in repo:
|
||||
repo, alias = repo.split(" as ")
|
||||
uri = line
|
||||
if " as " in uri:
|
||||
uri, alias = uri.split(" as ")
|
||||
alias = alias.strip()
|
||||
if "@" in repo:
|
||||
repo, branch = repo.split("@")
|
||||
if "@" in uri:
|
||||
uri, branch = uri.split("@")
|
||||
|
||||
return PluginDesc(name.strip(), repo.strip(), branch.strip(), alias)
|
||||
repo = make_repo(uri.strip(), branch.strip(), alias)
|
||||
|
||||
return PluginDesc(repo, branch.strip(), alias)
|
||||
|
||||
|
||||
def load_plugin_spec(plugin_file: str) -> List[PluginDesc]:
|
||||
@@ -404,10 +487,6 @@ def load_plugin_spec(plugin_file: str) -> List[PluginDesc]:
|
||||
if line.startswith("#"):
|
||||
continue
|
||||
plugin = parse_plugin_line(line)
|
||||
if not plugin.owner:
|
||||
msg = f"Invalid repository {line}, must be in the format owner/repo[ as alias]"
|
||||
print(msg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
plugins.append(plugin)
|
||||
return plugins
|
||||
|
||||
@@ -467,14 +546,13 @@ class Cache:
|
||||
|
||||
def prefetch(
|
||||
pluginDesc: PluginDesc, cache: Cache
|
||||
) -> Tuple[str, str, Union[Exception, Plugin], dict]:
|
||||
owner, repo = pluginDesc.owner, pluginDesc.repo
|
||||
) -> Tuple[PluginDesc, Union[Exception, Plugin], dict]:
|
||||
try:
|
||||
plugin, redirect = prefetch_plugin(pluginDesc, cache)
|
||||
cache[plugin.commit] = plugin
|
||||
return (owner, repo, plugin, redirect)
|
||||
return (pluginDesc, plugin, redirect)
|
||||
except Exception as e:
|
||||
return (owner, repo, e, {})
|
||||
return (pluginDesc, e, {})
|
||||
|
||||
|
||||
def rewrite_input(
|
||||
|
||||
@@ -166,6 +166,17 @@ with lib.maintainers; {
|
||||
scope = "Maintain Jitsi.";
|
||||
};
|
||||
|
||||
kubernetes = {
|
||||
members = [
|
||||
johanot
|
||||
offline
|
||||
saschagrunert
|
||||
srhb
|
||||
zowoq
|
||||
];
|
||||
scope = "Maintain the Kubernetes package and module";
|
||||
};
|
||||
|
||||
kodi = {
|
||||
members = [
|
||||
aanderse
|
||||
@@ -229,6 +240,7 @@ with lib.maintainers; {
|
||||
php = {
|
||||
members = [
|
||||
aanderse
|
||||
drupol
|
||||
etu
|
||||
globin
|
||||
ma27
|
||||
|
||||
+1
-24
@@ -9,27 +9,6 @@ let
|
||||
modules = [ configuration ];
|
||||
};
|
||||
|
||||
# This is for `nixos-rebuild build-vm'.
|
||||
vmConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules = [ configuration ./modules/virtualisation/qemu-vm.nix ];
|
||||
}).config;
|
||||
|
||||
# This is for `nixos-rebuild build-vm-with-bootloader'.
|
||||
vmWithBootLoaderConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ configuration
|
||||
./modules/virtualisation/qemu-vm.nix
|
||||
{ virtualisation.useBootLoader = true; }
|
||||
({ config, ... }: {
|
||||
virtualisation.useEFIBoot =
|
||||
config.boot.loader.systemd-boot.enable ||
|
||||
config.boot.loader.efi.canTouchEfiVariables;
|
||||
})
|
||||
];
|
||||
}).config;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
@@ -37,7 +16,5 @@ in
|
||||
|
||||
system = eval.config.system.build.toplevel;
|
||||
|
||||
vm = vmConfig.system.build.vm;
|
||||
|
||||
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
|
||||
inherit (eval.config.system.build) vm vmWithBootLoader;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ in rec {
|
||||
|
||||
manualEpub = runCommand "nixos-manual-epub"
|
||||
{ inherit sources;
|
||||
buildInputs = [ libxml2.bin libxslt.bin zip ];
|
||||
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin buildPackages.zip ];
|
||||
}
|
||||
''
|
||||
# Generate the epub manual.
|
||||
|
||||
@@ -88,6 +88,8 @@ starting them in parallel:
|
||||
start_all()
|
||||
```
|
||||
|
||||
## Machine objects {#ssec-machine-objects}
|
||||
|
||||
The following methods are available on machine objects:
|
||||
|
||||
`start`
|
||||
@@ -313,3 +315,52 @@ repository):
|
||||
# fmt: on
|
||||
'';
|
||||
```
|
||||
|
||||
## Failing tests early {#ssec-failing-tests-early}
|
||||
|
||||
To fail tests early when certain invariables are no longer met (instead of waiting for the build to time out), the decorator `polling_condition` is provided. For example, if we are testing a program `foo` that should not quit after being started, we might write the following:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
|
||||
|
||||
machine.succeed("foo --start")
|
||||
machine.wait_until_succeeds("pgrep -x foo")
|
||||
|
||||
with foo_running:
|
||||
... # Put `foo` through its paces
|
||||
```
|
||||
|
||||
|
||||
`polling_condition` takes the following (optional) arguments:
|
||||
|
||||
`seconds_interval`
|
||||
|
||||
:
|
||||
specifies how often the condition should be polled:
|
||||
|
||||
```py
|
||||
@polling_condition(seconds_interval=10)
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
`description`
|
||||
|
||||
:
|
||||
is used in the log when the condition is checked. If this is not provided, the description is pulled from the docstring of the function. These two are therefore equivalent:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
"check that foo is running"
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
```py
|
||||
@polling_condition(description="check that foo is running")
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
@@ -117,407 +117,413 @@ if not "Linux" in machine.succeed("uname"):
|
||||
<programlisting language="python">
|
||||
start_all()
|
||||
</programlisting>
|
||||
<para>
|
||||
The following methods are available on machine objects:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>start</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Start the virtual machine. This method is asynchronous — it
|
||||
does not wait for the machine to finish booting.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>shutdown</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Shut down the machine, waiting for the VM to exit.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>crash</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate a sudden power failure, by telling the VM to exit
|
||||
immediately.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>block</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate unplugging the Ethernet cable that connects the
|
||||
machine to the other machines.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>unblock</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Undo the effect of <literal>block</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>screenshot</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Take a picture of the display of the virtual machine, in PNG
|
||||
format. The screenshot is linked from the HTML log.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>get_screen_text_variants</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Return a list of different interpretations of what is
|
||||
currently visible on the machine's screen using optical
|
||||
character recognition. The number and order of the
|
||||
interpretations is not specified and is subject to change, but
|
||||
if no exception is raised at least one will be returned.
|
||||
</para>
|
||||
<note>
|
||||
<section xml:id="ssec-machine-objects">
|
||||
<title>Machine objects</title>
|
||||
<para>
|
||||
The following methods are available on machine objects:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>start</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
Start the virtual machine. This method is asynchronous — it
|
||||
does not wait for the machine to finish booting.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>get_screen_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Return a textual representation of what is currently visible
|
||||
on the machine's screen using optical character recognition.
|
||||
</para>
|
||||
<note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>shutdown</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
Shut down the machine, waiting for the VM to exit.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_monitor_command</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Send a command to the QEMU monitor. This is rarely used, but
|
||||
allows doing stuff such as attaching virtual USB disks to a
|
||||
running machine.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_key</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate pressing keys on the virtual keyboard, e.g.,
|
||||
<literal>send_key("ctrl-alt-delete")</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_chars</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate typing a sequence of characters on the virtual
|
||||
keyboard, e.g.,
|
||||
<literal>send_chars("foobar\n")</literal> will type
|
||||
the string <literal>foobar</literal> followed by the Enter
|
||||
key.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>execute</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute a shell command, returning a list
|
||||
<literal>(status, stdout)</literal>. If the command detaches,
|
||||
it must close stdout, as <literal>execute</literal> will wait
|
||||
for this to consume all output reliably. This can be achieved
|
||||
by redirecting stdout to stderr <literal>>&2</literal>,
|
||||
to <literal>/dev/console</literal>,
|
||||
<literal>/dev/null</literal> or a file. Examples of detaching
|
||||
commands are <literal>sleep 365d &</literal>, where the
|
||||
shell forks a new process that can write to stdout and
|
||||
<literal>xclip -i</literal>, where the
|
||||
<literal>xclip</literal> command itself forks without closing
|
||||
stdout. Takes an optional parameter
|
||||
<literal>check_return</literal> that defaults to
|
||||
<literal>True</literal>. Setting this parameter to
|
||||
<literal>False</literal> will not check for the return code
|
||||
and return -1 instead. This can be used for commands that shut
|
||||
down the VM and would therefore break the pipe that would be
|
||||
used for retrieving the return code.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>succeed</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute a shell command, raising an exception if the exit
|
||||
status is not zero, otherwise returning the standard output.
|
||||
Commands are run with <literal>set -euo pipefail</literal>
|
||||
set:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
If several commands are separated by <literal>;</literal>
|
||||
and one fails, the command as a whole will fail.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
For pipelines, the last non-zero exit status will be
|
||||
returned (if there is one, zero will be returned
|
||||
otherwise).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Dereferencing unset variables fail the command.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
It will wait for stdout to be closed. See
|
||||
<literal>execute</literal> for the implications.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>fail</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Like <literal>succeed</literal>, but raising an exception if
|
||||
the command returns a zero status.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_until_succeeds</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Repeat a shell command with 1-second intervals until it
|
||||
succeeds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_until_fails</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Repeat a shell command with 1-second intervals until it fails.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_unit</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the specified systemd unit has reached the
|
||||
<quote>active</quote> state.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_file</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the specified file exists.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_open_port</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until a process is listening on the given TCP port (on
|
||||
<literal>localhost</literal>, at least).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_closed_port</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until nobody is listening on the given TCP port.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_x</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the X11 server is accepting connections.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the supplied regular expressions matches the
|
||||
textual contents of the screen by using optical character
|
||||
recognition (see <literal>get_screen_text</literal> and
|
||||
<literal>get_screen_text_variants</literal>).
|
||||
</para>
|
||||
<note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>crash</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
Simulate a sudden power failure, by telling the VM to exit
|
||||
immediately.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_console_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the supplied regular expressions match a line of
|
||||
the serial console output. This method is useful when OCR is
|
||||
not possibile or accurate enough.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_window</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until an X11 window has appeared whose name matches the
|
||||
given regular expression, e.g.,
|
||||
<literal>wait_for_window("Terminal")</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>copy_from_host</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Copies a file from host to machine, e.g.,
|
||||
<literal>copy_from_host("myfile", "/etc/my/important/file")</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The first argument is the file on the host. The file needs to
|
||||
be accessible while building the nix derivation. The second
|
||||
argument is the location of the file on the machine.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>systemctl</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Runs <literal>systemctl</literal> commands with optional
|
||||
support for <literal>systemctl --user</literal>
|
||||
</para>
|
||||
<programlisting language="python">
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>block</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate unplugging the Ethernet cable that connects the
|
||||
machine to the other machines.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>unblock</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Undo the effect of <literal>block</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>screenshot</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Take a picture of the display of the virtual machine, in PNG
|
||||
format. The screenshot is linked from the HTML log.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>get_screen_text_variants</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Return a list of different interpretations of what is
|
||||
currently visible on the machine's screen using optical
|
||||
character recognition. The number and order of the
|
||||
interpretations is not specified and is subject to change,
|
||||
but if no exception is raised at least one will be returned.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>get_screen_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Return a textual representation of what is currently visible
|
||||
on the machine's screen using optical character recognition.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_monitor_command</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Send a command to the QEMU monitor. This is rarely used, but
|
||||
allows doing stuff such as attaching virtual USB disks to a
|
||||
running machine.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_key</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate pressing keys on the virtual keyboard, e.g.,
|
||||
<literal>send_key("ctrl-alt-delete")</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>send_chars</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Simulate typing a sequence of characters on the virtual
|
||||
keyboard, e.g.,
|
||||
<literal>send_chars("foobar\n")</literal> will
|
||||
type the string <literal>foobar</literal> followed by the
|
||||
Enter key.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>execute</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute a shell command, returning a list
|
||||
<literal>(status, stdout)</literal>. If the command
|
||||
detaches, it must close stdout, as
|
||||
<literal>execute</literal> will wait for this to consume all
|
||||
output reliably. This can be achieved by redirecting stdout
|
||||
to stderr <literal>>&2</literal>, to
|
||||
<literal>/dev/console</literal>,
|
||||
<literal>/dev/null</literal> or a file. Examples of
|
||||
detaching commands are <literal>sleep 365d &</literal>,
|
||||
where the shell forks a new process that can write to stdout
|
||||
and <literal>xclip -i</literal>, where the
|
||||
<literal>xclip</literal> command itself forks without
|
||||
closing stdout. Takes an optional parameter
|
||||
<literal>check_return</literal> that defaults to
|
||||
<literal>True</literal>. Setting this parameter to
|
||||
<literal>False</literal> will not check for the return code
|
||||
and return -1 instead. This can be used for commands that
|
||||
shut down the VM and would therefore break the pipe that
|
||||
would be used for retrieving the return code.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>succeed</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute a shell command, raising an exception if the exit
|
||||
status is not zero, otherwise returning the standard output.
|
||||
Commands are run with <literal>set -euo pipefail</literal>
|
||||
set:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
If several commands are separated by
|
||||
<literal>;</literal> and one fails, the command as a
|
||||
whole will fail.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
For pipelines, the last non-zero exit status will be
|
||||
returned (if there is one, zero will be returned
|
||||
otherwise).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Dereferencing unset variables fail the command.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
It will wait for stdout to be closed. See
|
||||
<literal>execute</literal> for the implications.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>fail</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Like <literal>succeed</literal>, but raising an exception if
|
||||
the command returns a zero status.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_until_succeeds</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Repeat a shell command with 1-second intervals until it
|
||||
succeeds.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_until_fails</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Repeat a shell command with 1-second intervals until it
|
||||
fails.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_unit</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the specified systemd unit has reached the
|
||||
<quote>active</quote> state.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_file</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the specified file exists.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_open_port</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until a process is listening on the given TCP port (on
|
||||
<literal>localhost</literal>, at least).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_closed_port</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until nobody is listening on the given TCP port.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_x</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the X11 server is accepting connections.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the supplied regular expressions matches the
|
||||
textual contents of the screen by using optical character
|
||||
recognition (see <literal>get_screen_text</literal> and
|
||||
<literal>get_screen_text_variants</literal>).
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This requires passing <literal>enableOCR</literal> to the
|
||||
test attribute set.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_console_text</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until the supplied regular expressions match a line of
|
||||
the serial console output. This method is useful when OCR is
|
||||
not possibile or accurate enough.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>wait_for_window</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Wait until an X11 window has appeared whose name matches the
|
||||
given regular expression, e.g.,
|
||||
<literal>wait_for_window("Terminal")</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>copy_from_host</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Copies a file from host to machine, e.g.,
|
||||
<literal>copy_from_host("myfile", "/etc/my/important/file")</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The first argument is the file on the host. The file needs
|
||||
to be accessible while building the nix derivation. The
|
||||
second argument is the location of the file on the machine.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>systemctl</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Runs <literal>systemctl</literal> commands with optional
|
||||
support for <literal>systemctl --user</literal>
|
||||
</para>
|
||||
<programlisting language="python">
|
||||
machine.systemctl("list-jobs --no-pager") # runs `systemctl list-jobs --no-pager`
|
||||
machine.systemctl("list-jobs --no-pager", "any-user") # spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager`
|
||||
</programlisting>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>shell_interact</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allows you to directly interact with the guest shell. This
|
||||
should only be used during test development, not in production
|
||||
tests. Killing the interactive session with
|
||||
<literal>Ctrl-d</literal> or <literal>Ctrl-c</literal> also
|
||||
ends the guest session.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
To test user units declared by
|
||||
<literal>systemd.user.services</literal> the optional
|
||||
<literal>user</literal> argument can be used:
|
||||
</para>
|
||||
<programlisting language="python">
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>shell_interact</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Allows you to directly interact with the guest shell. This
|
||||
should only be used during test development, not in
|
||||
production tests. Killing the interactive session with
|
||||
<literal>Ctrl-d</literal> or <literal>Ctrl-c</literal> also
|
||||
ends the guest session.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
To test user units declared by
|
||||
<literal>systemd.user.services</literal> the optional
|
||||
<literal>user</literal> argument can be used:
|
||||
</para>
|
||||
<programlisting language="python">
|
||||
machine.start()
|
||||
machine.wait_for_x()
|
||||
machine.wait_for_unit("xautolock.service", "x-session-user")
|
||||
</programlisting>
|
||||
<para>
|
||||
This applies to <literal>systemctl</literal>,
|
||||
<literal>get_unit_info</literal>, <literal>wait_for_unit</literal>,
|
||||
<literal>start_job</literal> and <literal>stop_job</literal>.
|
||||
</para>
|
||||
<para>
|
||||
For faster dev cycles it's also possible to disable the code-linters
|
||||
(this shouldn't be commited though):
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
<para>
|
||||
This applies to <literal>systemctl</literal>,
|
||||
<literal>get_unit_info</literal>,
|
||||
<literal>wait_for_unit</literal>, <literal>start_job</literal> and
|
||||
<literal>stop_job</literal>.
|
||||
</para>
|
||||
<para>
|
||||
For faster dev cycles it's also possible to disable the
|
||||
code-linters (this shouldn't be commited though):
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
import ./make-test-python.nix {
|
||||
skipLint = true;
|
||||
machine =
|
||||
@@ -531,13 +537,13 @@ import ./make-test-python.nix {
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
This will produce a Nix warning at evaluation time. To fully disable
|
||||
the linter, wrap the test script in comment directives to disable
|
||||
the Black linter directly (again, don't commit this within the
|
||||
Nixpkgs repository):
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
<para>
|
||||
This will produce a Nix warning at evaluation time. To fully
|
||||
disable the linter, wrap the test script in comment directives to
|
||||
disable the Black linter directly (again, don't commit this within
|
||||
the Nixpkgs repository):
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
testScript =
|
||||
''
|
||||
# fmt: off
|
||||
@@ -545,4 +551,66 @@ import ./make-test-python.nix {
|
||||
# fmt: on
|
||||
'';
|
||||
</programlisting>
|
||||
</section>
|
||||
<section xml:id="ssec-failing-tests-early">
|
||||
<title>Failing tests early</title>
|
||||
<para>
|
||||
To fail tests early when certain invariables are no longer met
|
||||
(instead of waiting for the build to time out), the decorator
|
||||
<literal>polling_condition</literal> is provided. For example, if
|
||||
we are testing a program <literal>foo</literal> that should not
|
||||
quit after being started, we might write the following:
|
||||
</para>
|
||||
<programlisting language="python">
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
|
||||
|
||||
machine.succeed("foo --start")
|
||||
machine.wait_until_succeeds("pgrep -x foo")
|
||||
|
||||
with foo_running:
|
||||
... # Put `foo` through its paces
|
||||
</programlisting>
|
||||
<para>
|
||||
<literal>polling_condition</literal> takes the following
|
||||
(optional) arguments:
|
||||
</para>
|
||||
<para>
|
||||
<literal>seconds_interval</literal>
|
||||
</para>
|
||||
<para>
|
||||
: specifies how often the condition should be polled:
|
||||
</para>
|
||||
<programlisting>
|
||||
```py
|
||||
@polling_condition(seconds_interval=10)
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
</programlisting>
|
||||
<para>
|
||||
<literal>description</literal>
|
||||
</para>
|
||||
<para>
|
||||
: is used in the log when the condition is checked. If this is not
|
||||
provided, the description is pulled from the docstring of the
|
||||
function. These two are therefore equivalent:
|
||||
</para>
|
||||
<programlisting>
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
"check that foo is running"
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
```py
|
||||
@polling_condition(description="check that foo is running")
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1420,6 +1420,15 @@ Superuser created successfully.
|
||||
for those who want to have all RetroArch cores available.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The Linux kernel for security reasons now restricts access to
|
||||
BPF syscalls via <literal>BPF_UNPRIV_DEFAULT_OFF=y</literal>.
|
||||
Unprivileged access can be reenabled via the
|
||||
<literal>kernel.unprivileged_bpf_disabled</literal> sysctl
|
||||
knob.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-21.11-notable-changes">
|
||||
|
||||
@@ -32,10 +32,14 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Mattermost has been updated to version 6.2. Migrations may
|
||||
take a while, see the
|
||||
<link xlink:href="https://docs.mattermost.com/install/self-managed-changelog.html#release-v6.2-feature-release">upgrade
|
||||
notes</link>.
|
||||
Mattermost has been updated to extended support release 6.3,
|
||||
as the previously packaged extended support release 5.37 is
|
||||
<link xlink:href="https://docs.mattermost.com/upgrade/extended-support-release.html">reaching
|
||||
its end of life</link>. Migrations may take a while, see the
|
||||
<link xlink:href="https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release">changelog</link>
|
||||
and
|
||||
<link xlink:href="https://docs.mattermost.com/upgrade/important-upgrade-notes.html">important
|
||||
upgrade notes</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@@ -75,6 +79,14 @@
|
||||
<link linkend="opt-services.filebeat.enable">services.filebeat</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://frrouting.org/">FRRouting</link>, a
|
||||
popular suite of Internet routing protocol daemons (BGP, BFD,
|
||||
OSPF, IS-IS, VVRP and others). Available as
|
||||
<link linkend="opt-services.ffr.babel.enable">services.frr</link>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/hifi/heisenbridge">heisenbridge</link>,
|
||||
@@ -82,6 +94,13 @@
|
||||
<link xlink:href="options.html#opt-services.heisenbridge.enable">services.heisenbridge</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://ergo.chat">ergochat</link>, a modern
|
||||
IRC with IRCv3 features. Available as
|
||||
<link xlink:href="options.html#opt-services.ergochat.enable">services.ergochat</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
|
||||
@@ -89,6 +108,14 @@
|
||||
<link xlink:href="options.html#opt-services.powerdns-admin.enable">services.powerdns-admin</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://invoiceplane.com">InvoicePlane</link>,
|
||||
web application for managing and creating invoices. Available
|
||||
at
|
||||
<link xlink:href="options.html#opt-services.invoiceplane.enable">services.invoiceplane</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://maddy.email">maddy</link>, a
|
||||
@@ -96,6 +123,13 @@
|
||||
<link xlink:href="options.html#opt-services.maddy.enable">services.maddy</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/mgumz/mtr-exporter">mtr-exporter</link>,
|
||||
a Prometheus exporter for mtr metrics. Available as
|
||||
<link xlink:href="options.html#opt-services.mtr-exporter.enable">services.mtr-exporter</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://tetrd.app">tetrd</link>, share your
|
||||
@@ -104,6 +138,53 @@
|
||||
<link linkend="opt-services.tetrd.enable">services.tetrd</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm">ArchiSteamFarm</link>,
|
||||
a C# application with primary purpose of idling Steam cards
|
||||
from multiple accounts simultaneously. Available as
|
||||
<link xlink:href="options.html#opt-services.archisteamfarm.enable">services.archisteamfarm</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://goteleport.com">teleport</link>,
|
||||
allows engineers and security professionals to unify access
|
||||
for SSH servers, Kubernetes clusters, web applications, and
|
||||
databases across all environments. Available at
|
||||
<link linkend="opt-services.teleport.enable">services.teleport</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://loic-sharma.github.io/BaGet/">BaGet</link>,
|
||||
a lightweight NuGet and symbol server. Available at
|
||||
<link linkend="opt-services.baget.enable">services.baget</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/ThomasLeister/prosody-filer">prosody-filer</link>,
|
||||
a server for handling XMPP HTTP Upload requests. Available at
|
||||
<link linkend="opt-services.prosody-filer.enable">services.prosody-filer</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://timetagger.app">timetagger</link>,
|
||||
an open source time-tracker with an intuitive user experience
|
||||
and powerful reporting.
|
||||
<link xlink:href="options.html#opt-services.timetagger.enable">services.timetagger</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://www.rstudio.com/products/rstudio/#rstudio-server">rstudio-server</link>,
|
||||
a browser-based version of the RStudio IDE for the R
|
||||
programming language. Available as
|
||||
<link xlink:href="options.html#opt-services.rstudio-server.enable">services.rstudio-server</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-22.05-incompatibilities">
|
||||
@@ -147,6 +228,13 @@
|
||||
removed due to it being an outdated version.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>mailpile</literal> email webclient
|
||||
(<literal>services.mailpile</literal>) has been removed due to
|
||||
its reliance on python2.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The MoinMoin wiki engine
|
||||
@@ -191,6 +279,28 @@
|
||||
<literal>virtualisation.docker.daemon.settings</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The backward compatibility in
|
||||
<literal>services.wordpress</literal> to configure sites with
|
||||
the old interface has been removed. Please use
|
||||
<literal>services.wordpress.sites</literal> instead.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The backward compatibility in
|
||||
<literal>services.dokuwiki</literal> to configure sites with
|
||||
the old interface has been removed. Please use
|
||||
<literal>services.dokuwiki.sites</literal> instead.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
opensmtpd-extras is no longer build with python2 scripting
|
||||
support due to python2 deprecation in nixpkgs
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>autorestic</literal> package has been upgraded
|
||||
@@ -228,6 +338,116 @@
|
||||
to your configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Normal users (with <literal>isNormalUser = true</literal>)
|
||||
which have non-empty <literal>subUidRanges</literal> or
|
||||
<literal>subGidRanges</literal> set no longer have additional
|
||||
implicit ranges allocated. To enable automatic allocation back
|
||||
set <literal>autoSubUidGidRange = true</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>idris2</literal> now requires
|
||||
<literal>--package</literal> when using packages
|
||||
<literal>contrib</literal> and <literal>network</literal>,
|
||||
while previously these idris2 packages were automatically
|
||||
loaded.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>services.thelounge.private</literal> was removed in
|
||||
favor of <literal>services.thelounge.public</literal>, to
|
||||
follow with upstream changes.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>pkgs.docbookrx</literal> was removed since it’s
|
||||
unmaintained
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The options
|
||||
<literal>networking.interfaces.<name>.ipv4.routes</literal>
|
||||
and
|
||||
<literal>networking.interfaces.<name>.ipv6.routes</literal>
|
||||
are no longer ignored when using networkd instead of the
|
||||
default scripted network backend by setting
|
||||
<literal>networking.useNetworkd</literal> to
|
||||
<literal>true</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
MultiMC has been replaced with the fork PolyMC due to upstream
|
||||
developers being hostile to 3rd party package maintainers.
|
||||
PolyMC removes all MultiMC branding and is aimed at providing
|
||||
proper 3rd party packages like the one contained in Nixpkgs.
|
||||
This change affects the data folder where game instances and
|
||||
other save and configuration files are stored. Users with
|
||||
existing installations should rename
|
||||
<literal>~/.local/share/multimc</literal> to
|
||||
<literal>~/.local/share/polymc</literal>. The main config
|
||||
file’s path has also moved from
|
||||
<literal>~/.local/share/multimc/multimc.cfg</literal> to
|
||||
<literal>~/.local/share/polymc/polymc.cfg</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>pkgs.noto-fonts-cjk</literal> is now deprecated in
|
||||
favor of <literal>pkgs.noto-fonts-cjk-sans</literal> and
|
||||
<literal>pkgs.noto-fonts-cjk-serif</literal> because they each
|
||||
have different release schedules. To maintain compatibility
|
||||
with prior releases of Nixpkgs,
|
||||
<literal>pkgs.noto-fonts-cjk</literal> is currently an alias
|
||||
of <literal>pkgs.noto-fonts-cjk-sans</literal> and doesn’t
|
||||
include serif fonts.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The interface that allows activation scripts to restart units
|
||||
has been reworked. Restarting and reloading is now done by a
|
||||
single file
|
||||
<literal>/run/nixos/activation-restart-list</literal> that
|
||||
honors <literal>restartIfChanged</literal> and
|
||||
<literal>reloadIfChanged</literal> of the units.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>services.bookstack.cacheDir</literal> option has
|
||||
been removed, since the cache directory is now handled by
|
||||
systemd.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>services.bookstack.extraConfig</literal> option
|
||||
has been replaced by
|
||||
<literal>services.bookstack.config</literal> which implements
|
||||
a
|
||||
<link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">settings-style</link>
|
||||
configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>lib.assertMsg</literal> and
|
||||
<literal>lib.assertOneOf</literal> no longer return
|
||||
<literal>false</literal> if the passed condition is
|
||||
<literal>false</literal>, <literal>throw</literal>ing the
|
||||
given error message instead (which makes the resulting error
|
||||
message less cluttered). This will not impact the behaviour of
|
||||
code using these functions as intended, namely as top-level
|
||||
wrapper for <literal>assert</literal> conditions.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-22.05-notable-changes">
|
||||
@@ -258,6 +478,28 @@
|
||||
socket <literal>/run/redis-${serverName}/redis.sock</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
<link linkend="opt-virtualisation.vmVariant">virtualisation.vmVariant</link>
|
||||
was added to allow users to make changes to the
|
||||
<literal>nixos-rebuild build-vm</literal> configuration that
|
||||
do not apply to their normal system.
|
||||
</para>
|
||||
<para>
|
||||
The <literal>config.system.build.vm</literal> attribute now
|
||||
always exists and defaults to the value from
|
||||
<literal>vmVariant</literal>. Configurations that import the
|
||||
<literal>virtualisation/qemu-vm.nix</literal> module
|
||||
themselves will override this value, such that
|
||||
<literal>vmVariant</literal> is not used.
|
||||
</para>
|
||||
<para>
|
||||
Similarly
|
||||
<link linkend="opt-virtualisation.vmVariantWithBootLoader">virtualisation.vmVariantWithBootloader</link>
|
||||
was added.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The
|
||||
@@ -300,6 +542,19 @@
|
||||
will now correctly remove those domains during rebuild/renew.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
MariaDB is now offered in several versions, not just the
|
||||
newest one. So if you have a need for running MariaDB 10.4 for
|
||||
example, you can now just set
|
||||
<literal>services.mysql.package = pkgs.mariadb_104;</literal>.
|
||||
In general, it is recommended to run the newest version, to
|
||||
get the newest features, while sticking with an LTS version
|
||||
will most likely provide a more stable experience. Sometimes
|
||||
software is also incompatible with the newest version of
|
||||
MariaDB.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
@@ -310,6 +565,15 @@
|
||||
usage in non-X11 environments, e.g. Wayland.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link linkend="opt-programs.ssh.knownHosts">programs.ssh.knownHosts</link>
|
||||
has gained an <literal>extraHostNames</literal> option to
|
||||
replace <literal>hostNames</literal>.
|
||||
<literal>hostNames</literal> is deprecated, but still
|
||||
available for now.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>services.stubby</literal> module was converted to
|
||||
@@ -334,6 +598,81 @@
|
||||
<literal>true</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option <literal>services.thelounge.plugins</literal> has
|
||||
been added to allow installing plugins for The Lounge. Plugins
|
||||
can be found in
|
||||
<literal>pkgs.theLoungePlugins.plugins</literal> and
|
||||
<literal>pkgs.theLoungePlugins.themes</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>firmwareLinuxNonfree</literal> package has been
|
||||
renamed to <literal>linux-firmware</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>services.mbpfan</literal> module was converted to
|
||||
a
|
||||
<link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
|
||||
0042</link> configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A new module was added for the
|
||||
<link xlink:href="https://starship.rs/">Starship</link> shell
|
||||
prompt, providing the options
|
||||
<literal>programs.starship.enable</literal> and
|
||||
<literal>programs.starship.settings</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>services.mattermost.plugins</literal> has been added
|
||||
to allow the declarative installation of Mattermost plugins.
|
||||
Plugins are automatically repackaged using autoPatchelf.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>zrepl</literal> package has been updated from
|
||||
0.4.0 to 0.5:
|
||||
</para>
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para>
|
||||
The RPC protocol version was bumped; all zrepl daemons in
|
||||
a setup must be updated and restarted before replication
|
||||
can resume.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A bug involving encrypt-on-receive has been fixed. Read
|
||||
the
|
||||
<link xlink:href="https://zrepl.github.io/configuration/sendrecvoptions.html#job-recv-options-placeholder">zrepl
|
||||
documentation</link> and check the output of
|
||||
<literal>zfs get -r encryption,zrepl:placeholder PATH_TO_ROOTFS</literal>
|
||||
on the receiver.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Renamed option
|
||||
<literal>services.openssh.challengeResponseAuthentication</literal>
|
||||
to
|
||||
<literal>services.openssh.kbdInteractiveAuthentication</literal>.
|
||||
Reason is that the old name has been deprecated upstream.
|
||||
Using the old option name will still work, but produce a
|
||||
warning.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -417,6 +417,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- `retroArchCores` has been removed. This means that using `nixpkgs.config.retroarch` to customize RetroArch cores is not supported anymore. Instead, use package overrides, for example: `retroarch.override { cores = with libretro; [ citra snes9x ]; };`. Also, `retroarchFull` derivation is available for those who want to have all RetroArch cores available.
|
||||
|
||||
- The Linux kernel for security reasons now restricts access to BPF syscalls via `BPF_UNPRIV_DEFAULT_OFF=y`. Unprivileged access can be reenabled via the `kernel.unprivileged_bpf_disabled` sysctl knob.
|
||||
|
||||
## Other Notable Changes {#sec-release-21.11-notable-changes}
|
||||
|
||||
|
||||
|
||||
@@ -13,26 +13,50 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- PHP 8.1 is now available
|
||||
|
||||
- Mattermost has been updated to version 6.2. Migrations may take a while,
|
||||
see the [upgrade notes](https://docs.mattermost.com/install/self-managed-changelog.html#release-v6.2-feature-release).
|
||||
- Mattermost has been updated to extended support release 6.3, as the previously packaged extended support release 5.37 is [reaching its end of life](https://docs.mattermost.com/upgrade/extended-support-release.html).
|
||||
Migrations may take a while, see the [changelog](https://docs.mattermost.com/install/self-managed-changelog.html#release-v6-3-extended-support-release)
|
||||
and [important upgrade notes](https://docs.mattermost.com/upgrade/important-upgrade-notes.html).
|
||||
|
||||
## 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).
|
||||
|
||||
- [rootless Docker](https://docs.docker.com/engine/security/rootless/), a `systemd --user` Docker service which runs without root permissions. Available as [virtualisation.docker.rootless.enable](options.html#opt-virtualisation.docker.rootless.enable).
|
||||
|
||||
- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
|
||||
|
||||
- [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).
|
||||
|
||||
- [FRRouting](https://frrouting.org/), a popular suite of Internet routing protocol daemons (BGP, BFD, OSPF, IS-IS, VVRP and others). Available as [services.frr](#opt-services.ffr.babel.enable)
|
||||
|
||||
- [heisenbridge](https://github.com/hifi/heisenbridge), a bouncer-style Matrix IRC bridge. Available as [services.heisenbridge](options.html#opt-services.heisenbridge.enable).
|
||||
|
||||
- [ergochat](https://ergo.chat), a modern IRC with IRCv3 features. Available as [services.ergochat](options.html#opt-services.ergochat.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).
|
||||
|
||||
- [InvoicePlane](https://invoiceplane.com), web application for managing and creating invoices. Available at [services.invoiceplane](options.html#opt-services.invoiceplane.enable).
|
||||
|
||||
- [maddy](https://maddy.email), a composable all-in-one mail server. Available as [services.maddy](options.html#opt-services.maddy.enable).
|
||||
|
||||
- [mtr-exporter](https://github.com/mgumz/mtr-exporter), a Prometheus exporter for mtr metrics. Available as [services.mtr-exporter](options.html#opt-services.mtr-exporter.enable).
|
||||
|
||||
- [tetrd](https://tetrd.app), share your internet connection from your device to your PC and vice versa through a USB cable. Available at [services.tetrd](#opt-services.tetrd.enable).
|
||||
|
||||
- [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm), a C# application with primary purpose of idling Steam cards from multiple accounts simultaneously. Available as [services.archisteamfarm](options.html#opt-services.archisteamfarm.enable).
|
||||
|
||||
- [teleport](https://goteleport.com), allows engineers and security professionals to unify access for SSH servers, Kubernetes clusters, web applications, and databases across all environments. Available at [services.teleport](#opt-services.teleport.enable).
|
||||
|
||||
- [BaGet](https://loic-sharma.github.io/BaGet/), a lightweight NuGet and symbol server. Available at [services.baget](#opt-services.baget.enable).
|
||||
|
||||
- [prosody-filer](https://github.com/ThomasLeister/prosody-filer), a server for handling XMPP HTTP Upload requests. Available at [services.prosody-filer](#opt-services.prosody-filer.enable).
|
||||
|
||||
- [timetagger](https://timetagger.app), an open source time-tracker with an intuitive user experience and powerful reporting. [services.timetagger](options.html#opt-services.timetagger.enable).
|
||||
|
||||
- [rstudio-server](https://www.rstudio.com/products/rstudio/#rstudio-server), a browser-based version of the RStudio IDE for the R programming language. Available as [services.rstudio-server](options.html#opt-services.rstudio-server.enable).
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
|
||||
|
||||
- `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
|
||||
@@ -54,6 +78,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- `services.kubernetes.addons.dashboard` was removed due to it being an outdated version.
|
||||
|
||||
- The `mailpile` email webclient (`services.mailpile`) has been removed due to its reliance on python2.
|
||||
|
||||
- The MoinMoin wiki engine (`services.moinmoin`) has been removed, because Python 2 is being retired from nixpkgs.
|
||||
|
||||
- The `wafHook` hook now honors `NIX_BUILD_CORES` when `enableParallelBuilding` is not set explicitly. Packages can restore the old behaviour by setting `enableParallelBuilding=false`.
|
||||
@@ -66,6 +92,15 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- If you previously used `/etc/docker/daemon.json`, you need to incorporate the changes into the new option `virtualisation.docker.daemon.settings`.
|
||||
|
||||
- The backward compatibility in `services.wordpress` to configure sites with
|
||||
the old interface has been removed. Please use `services.wordpress.sites`
|
||||
instead.
|
||||
|
||||
- The backward compatibility in `services.dokuwiki` to configure sites with the
|
||||
old interface has been removed. Please use `services.dokuwiki.sites` instead.
|
||||
|
||||
- opensmtpd-extras is no longer build with python2 scripting support due to python2 deprecation in nixpkgs
|
||||
|
||||
- The `autorestic` package has been upgraded from 1.3.0 to 1.5.0 which introduces breaking changes in config file, check [their migration guide](https://autorestic.vercel.app/migration/1.4_1.5) for more details.
|
||||
|
||||
- For `pkgs.python3.pkgs.ipython`, its direct dependency `pkgs.python3.pkgs.matplotlib-inline`
|
||||
@@ -77,6 +112,38 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- `documentation.man` has been refactored to support choosing a man implementation other than GNU's `man-db`. For this, `documentation.man.manualPages` has been renamed to `documentation.man.man-db.manualPages`. If you want to use the new alternative man implementation `mandoc`, add `documentation.man = { enable = true; man-db.enable = false; mandoc.enable = true; }` to your configuration.
|
||||
|
||||
- Normal users (with `isNormalUser = true`) which have non-empty `subUidRanges` or `subGidRanges` set no longer have additional implicit ranges allocated. To enable automatic allocation back set `autoSubUidGidRange = true`.
|
||||
|
||||
- `idris2` now requires `--package` when using packages `contrib` and `network`, while previously these idris2 packages were automatically loaded.
|
||||
|
||||
- `services.thelounge.private` was removed in favor of `services.thelounge.public`, to follow with upstream changes.
|
||||
|
||||
- `pkgs.docbookrx` was removed since it's unmaintained
|
||||
|
||||
- The options `networking.interfaces.<name>.ipv4.routes` and `networking.interfaces.<name>.ipv6.routes` are no longer ignored when using networkd instead of the default scripted network backend by setting `networking.useNetworkd` to `true`.
|
||||
|
||||
- MultiMC has been replaced with the fork PolyMC due to upstream developers being hostile to 3rd party package maintainers. PolyMC removes all MultiMC branding and is aimed at providing proper 3rd party packages like the one contained in Nixpkgs. This change affects the data folder where game instances and other save and configuration files are stored. Users with existing installations should rename `~/.local/share/multimc` to `~/.local/share/polymc`. The main config file's path has also moved from `~/.local/share/multimc/multimc.cfg` to `~/.local/share/polymc/polymc.cfg`.
|
||||
|
||||
- `pkgs.noto-fonts-cjk` is now deprecated in favor of `pkgs.noto-fonts-cjk-sans`
|
||||
and `pkgs.noto-fonts-cjk-serif` because they each have different release
|
||||
schedules. To maintain compatibility with prior releases of Nixpkgs,
|
||||
`pkgs.noto-fonts-cjk` is currently an alias of `pkgs.noto-fonts-cjk-sans` and
|
||||
doesn't include serif fonts.
|
||||
|
||||
- The interface that allows activation scripts to restart units has been reworked. Restarting and reloading is now done by a single file `/run/nixos/activation-restart-list` that honors `restartIfChanged` and `reloadIfChanged` of the units.
|
||||
|
||||
- The `services.bookstack.cacheDir` option has been removed, since the
|
||||
cache directory is now handled by systemd.
|
||||
|
||||
- The `services.bookstack.extraConfig` option has been replaced by
|
||||
`services.bookstack.config` which implements a
|
||||
[settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md)
|
||||
configuration.
|
||||
|
||||
- `lib.assertMsg` and `lib.assertOneOf` no longer return `false` if the passed condition is `false`, `throw`ing the given error message instead (which makes the resulting error message less cluttered). This will not impact the behaviour of code using these functions as intended, namely as top-level wrapper for `assert` conditions.
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
## Other Notable Changes {#sec-release-22.05-notable-changes}
|
||||
|
||||
- The option [services.redis.servers](#opt-services.redis.servers) was added
|
||||
@@ -95,6 +162,16 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
to the members of the Unix group `redis-${serverName}`
|
||||
through the Unix socket `/run/redis-${serverName}/redis.sock`.
|
||||
|
||||
- The option [virtualisation.vmVariant](#opt-virtualisation.vmVariant) was added
|
||||
to allow users to make changes to the `nixos-rebuild build-vm` configuration
|
||||
that do not apply to their normal system.
|
||||
|
||||
The `config.system.build.vm` attribute now always exists and defaults to the
|
||||
value from `vmVariant`. Configurations that import the `virtualisation/qemu-vm.nix`
|
||||
module themselves will override this value, such that `vmVariant` is not used.
|
||||
|
||||
Similarly [virtualisation.vmVariantWithBootloader](#opt-virtualisation.vmVariantWithBootLoader) was added.
|
||||
|
||||
- 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
|
||||
@@ -111,12 +188,20 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
- Removing domains from `security.acme.certs._name_.extraDomainNames`
|
||||
will now correctly remove those domains during rebuild/renew.
|
||||
|
||||
- MariaDB is now offered in several versions, not just the newest one.
|
||||
So if you have a need for running MariaDB 10.4 for example, you can now just set `services.mysql.package = pkgs.mariadb_104;`.
|
||||
In general, it is recommended to run the newest version, to get the newest features, while sticking with an LTS version will most likely provide a more stable experience.
|
||||
Sometimes software is also incompatible with the newest version of MariaDB.
|
||||
|
||||
- The option
|
||||
[programs.ssh.enableAskPassword](#opt-programs.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.
|
||||
|
||||
- [programs.ssh.knownHosts](#opt-programs.ssh.knownHosts) has gained an `extraHostNames`
|
||||
option to replace `hostNames`. `hostNames` is deprecated, but still available for now.
|
||||
|
||||
- The `services.stubby` module was converted to a [settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration.
|
||||
|
||||
- The option `services.duplicati.dataDir` has been added to allow changing the location of duplicati's files.
|
||||
@@ -124,3 +209,25 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
- `fetchFromSourcehut` now allows fetching repositories recursively
|
||||
using `fetchgit` or `fetchhg` if the argument `fetchSubmodules`
|
||||
is set to `true`.
|
||||
|
||||
- The option `services.thelounge.plugins` has been added to allow installing plugins for The Lounge. Plugins can be found in `pkgs.theLoungePlugins.plugins` and `pkgs.theLoungePlugins.themes`.
|
||||
|
||||
- The `firmwareLinuxNonfree` package has been renamed to `linux-firmware`.
|
||||
|
||||
- The `services.mbpfan` module was converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration.
|
||||
|
||||
- A new module was added for the [Starship](https://starship.rs/) shell prompt,
|
||||
providing the options `programs.starship.enable` and `programs.starship.settings`.
|
||||
|
||||
- `services.mattermost.plugins` has been added to allow the declarative installation of Mattermost plugins.
|
||||
Plugins are automatically repackaged using autoPatchelf.
|
||||
|
||||
- The `zrepl` package has been updated from 0.4.0 to 0.5:
|
||||
* The RPC protocol version was bumped; all zrepl daemons in a setup must be updated and restarted before replication can resume.
|
||||
* A bug involving encrypt-on-receive has been fixed. Read the [zrepl documentation](https://zrepl.github.io/configuration/sendrecvoptions.html#job-recv-options-placeholder) and check the output of `zfs get -r encryption,zrepl:placeholder PATH_TO_ROOTFS` on the receiver.
|
||||
|
||||
- Renamed option `services.openssh.challengeResponseAuthentication` to `services.openssh.kbdInteractiveAuthentication`.
|
||||
Reason is that the old name has been deprecated upstream.
|
||||
Using the old option name will still work, but produce a warning.
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
let
|
||||
# The warning is in a top-level let binding so it is only printed once.
|
||||
minimalModulesWarning = warn "lib.nixos.evalModules is experimental and subject to change. See nixos/lib/default.nix" null;
|
||||
inherit (nonExtendedLib) warn;
|
||||
nonExtendedLib = import ../../lib;
|
||||
in
|
||||
{ # Optional. Allows an extended `lib` to be used instead of the regular Nixpkgs lib.
|
||||
lib ? nonExtendedLib,
|
||||
|
||||
# Feature flags allow you to opt in to unfinished code. These may change some
|
||||
# behavior or disable warnings.
|
||||
featureFlags ? {},
|
||||
|
||||
# This file itself is rather new, so we accept unknown parameters to be forward
|
||||
# compatible. This is generally not recommended, because typos go undetected.
|
||||
...
|
||||
}:
|
||||
let
|
||||
seqIf = cond: if cond then builtins.seq else a: b: b;
|
||||
# If cond, force `a` before returning any attr
|
||||
seqAttrsIf = cond: a: lib.mapAttrs (_: v: seqIf cond a v);
|
||||
|
||||
eval-config-minimal = import ./eval-config-minimal.nix { inherit lib; };
|
||||
in
|
||||
/*
|
||||
This attribute set appears as lib.nixos in the flake, or can be imported
|
||||
using a binding like `nixosLib = import (nixpkgs + "/nixos/lib") { }`.
|
||||
*/
|
||||
{
|
||||
inherit (seqAttrsIf (!featureFlags?minimalModules) minimalModulesWarning eval-config-minimal)
|
||||
evalModules
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
# DO NOT IMPORT. Use nixpkgsFlake.lib.nixos, or import (nixpkgs + "/nixos/lib")
|
||||
{ lib }: # read -^
|
||||
|
||||
let
|
||||
|
||||
/*
|
||||
Invoke NixOS. Unlike traditional NixOS, this does not include all modules.
|
||||
Any such modules have to be explicitly added via the `modules` parameter,
|
||||
or imported using `imports` in a module.
|
||||
|
||||
A minimal module list improves NixOS evaluation performance and allows
|
||||
modules to be independently usable, supporting new use cases.
|
||||
|
||||
Parameters:
|
||||
|
||||
modules: A list of modules that constitute the configuration.
|
||||
|
||||
specialArgs: An attribute set of module arguments. Unlike
|
||||
`config._module.args`, these are available for use in
|
||||
`imports`.
|
||||
`config._module.args` should be preferred when possible.
|
||||
|
||||
Return:
|
||||
|
||||
An attribute set containing `config.system.build.toplevel` among other
|
||||
attributes. See `lib.evalModules` in the Nixpkgs library.
|
||||
|
||||
*/
|
||||
evalModules = {
|
||||
prefix ? [],
|
||||
modules ? [],
|
||||
specialArgs ? {},
|
||||
}:
|
||||
# NOTE: Regular NixOS currently does use this function! Don't break it!
|
||||
# Ideally we don't diverge, unless we learn that we should.
|
||||
# In other words, only the public interface of nixos.evalModules
|
||||
# is experimental.
|
||||
lib.evalModules {
|
||||
inherit prefix modules;
|
||||
specialArgs = {
|
||||
modulesPath = builtins.toString ../modules;
|
||||
} // specialArgs;
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
inherit evalModules;
|
||||
}
|
||||
+10
-11
@@ -33,6 +33,12 @@ let pkgs_ = pkgs;
|
||||
in
|
||||
|
||||
let
|
||||
evalModulesMinimal = (import ./default.nix {
|
||||
inherit lib;
|
||||
# Implicit use of feature is noted in implementation.
|
||||
featureFlags.minimalModules = { };
|
||||
}).evalModules;
|
||||
|
||||
pkgsModule = rec {
|
||||
_file = ./eval-config.nix;
|
||||
key = _file;
|
||||
@@ -70,11 +76,9 @@ let
|
||||
};
|
||||
allUserModules = modules ++ legacyModules;
|
||||
|
||||
noUserModules = lib.evalModules ({
|
||||
inherit prefix;
|
||||
noUserModules = evalModulesMinimal ({
|
||||
inherit prefix specialArgs;
|
||||
modules = baseModules ++ extraModules ++ [ pkgsModule modulesModule ];
|
||||
specialArgs =
|
||||
{ modulesPath = builtins.toString ../modules; } // specialArgs;
|
||||
});
|
||||
|
||||
# Extra arguments that are useful for constructing a similar configuration.
|
||||
@@ -88,13 +92,8 @@ let
|
||||
|
||||
nixosWithUserModules = noUserModules.extendModules { modules = allUserModules; };
|
||||
|
||||
in withWarnings {
|
||||
|
||||
# Merge the option definitions in all modules, forming the full
|
||||
# system configuration.
|
||||
inherit (nixosWithUserModules) config options _module type;
|
||||
|
||||
in
|
||||
withWarnings nixosWithUserModules // {
|
||||
inherit extraArgs;
|
||||
|
||||
inherit (nixosWithUserModules._module.args) pkgs;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ rec {
|
||||
''-netdev vde,id=vlan${toString nic},sock="$QEMU_VDE_SOCKET_${toString net}"''
|
||||
];
|
||||
|
||||
qemuSerialDevice = if pkgs.stdenv.hostPlatform.isx86 then "ttyS0"
|
||||
qemuSerialDevice = if pkgs.stdenv.hostPlatform.isx86 || pkgs.stdenv.hostPlatform.isRiscV then "ttyS0"
|
||||
else if (with pkgs.stdenv.hostPlatform; isAarch32 || isAarch64 || isPower) then "ttyAMA0"
|
||||
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
|
||||
|
||||
|
||||
@@ -228,9 +228,7 @@ in rec {
|
||||
mkdir -p $out/getty.target.wants/
|
||||
ln -s ../autovt@tty1.service $out/getty.target.wants/
|
||||
|
||||
ln -s ../local-fs.target ../remote-fs.target \
|
||||
../nss-lookup.target ../nss-user-lookup.target ../swap.target \
|
||||
$out/multi-user.target.wants/
|
||||
ln -s ../remote-fs.target $out/multi-user.target.wants/
|
||||
''}
|
||||
''; # */
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "nixos-test-driver";
|
||||
version = "1.0";
|
||||
version = "1.1";
|
||||
src = ./.;
|
||||
|
||||
propagatedBuildInputs = [ coreutils netpbm python3Packages.colorama python3Packages.ptpython qemu_pkg socat vde2 ]
|
||||
@@ -26,7 +26,7 @@ python3Packages.buildPythonApplication rec {
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${src}/test_driver
|
||||
pylint --errors-only ${src}/test_driver
|
||||
pylint --errors-only --enable=unused-import ${src}/test_driver
|
||||
black --check --diff ${src}/test_driver
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="nixos-test-driver",
|
||||
version='1.0',
|
||||
version='1.1',
|
||||
packages=find_packages(),
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterator, List
|
||||
from typing import Any, Dict, Iterator, List, Union, Optional, Callable, ContextManager
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from test_driver.logger import rootlog
|
||||
from test_driver.machine import Machine, NixStartScript, retry
|
||||
from test_driver.vlan import VLan
|
||||
from test_driver.polling_condition import PollingCondition
|
||||
|
||||
|
||||
class Driver:
|
||||
@@ -16,6 +17,7 @@ class Driver:
|
||||
tests: str
|
||||
vlans: List[VLan]
|
||||
machines: List[Machine]
|
||||
polling_conditions: List[PollingCondition]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -36,12 +38,15 @@ class Driver:
|
||||
for s in scripts:
|
||||
yield NixStartScript(s)
|
||||
|
||||
self.polling_conditions = []
|
||||
|
||||
self.machines = [
|
||||
Machine(
|
||||
start_command=cmd,
|
||||
keep_vm_state=keep_vm_state,
|
||||
name=cmd.machine_name,
|
||||
tmp_dir=tmp_dir,
|
||||
callbacks=[self.check_polling_conditions],
|
||||
)
|
||||
for cmd in cmd(start_scripts)
|
||||
]
|
||||
@@ -84,6 +89,7 @@ class Driver:
|
||||
retry=retry,
|
||||
serial_stdout_off=self.serial_stdout_off,
|
||||
serial_stdout_on=self.serial_stdout_on,
|
||||
polling_condition=self.polling_condition,
|
||||
Machine=Machine, # for typing
|
||||
)
|
||||
machine_symbols = {m.name: m for m in self.machines}
|
||||
@@ -159,3 +165,36 @@ class Driver:
|
||||
|
||||
def serial_stdout_off(self) -> None:
|
||||
rootlog._print_serial_logs = False
|
||||
|
||||
def check_polling_conditions(self) -> None:
|
||||
for condition in self.polling_conditions:
|
||||
condition.maybe_raise()
|
||||
|
||||
def polling_condition(
|
||||
self,
|
||||
fun_: Optional[Callable] = None,
|
||||
*,
|
||||
seconds_interval: float = 2.0,
|
||||
description: Optional[str] = None,
|
||||
) -> Union[Callable[[Callable], ContextManager], ContextManager]:
|
||||
driver = self
|
||||
|
||||
class Poll:
|
||||
def __init__(self, fun: Callable):
|
||||
self.condition = PollingCondition(
|
||||
fun,
|
||||
seconds_interval,
|
||||
description,
|
||||
)
|
||||
|
||||
def __enter__(self) -> None:
|
||||
driver.polling_conditions.append(self.condition)
|
||||
|
||||
def __exit__(self, a, b, c) -> None: # type: ignore
|
||||
res = driver.polling_conditions.pop()
|
||||
assert res is self.condition
|
||||
|
||||
if fun_ is None:
|
||||
return Poll
|
||||
else:
|
||||
return Poll(fun_)
|
||||
|
||||
@@ -318,6 +318,7 @@ class Machine:
|
||||
# Store last serial console lines for use
|
||||
# of wait_for_console_text
|
||||
last_lines: Queue = Queue()
|
||||
callbacks: List[Callable]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Machine '{self.name}'>"
|
||||
@@ -329,12 +330,14 @@ class Machine:
|
||||
name: str = "machine",
|
||||
keep_vm_state: bool = False,
|
||||
allow_reboot: bool = False,
|
||||
callbacks: Optional[List[Callable]] = None,
|
||||
) -> None:
|
||||
self.tmp_dir = tmp_dir
|
||||
self.keep_vm_state = keep_vm_state
|
||||
self.allow_reboot = allow_reboot
|
||||
self.name = name
|
||||
self.start_command = start_command
|
||||
self.callbacks = callbacks if callbacks is not None else []
|
||||
|
||||
# set up directories
|
||||
self.shared_dir = self.tmp_dir / "shared-xchg"
|
||||
@@ -406,6 +409,7 @@ class Machine:
|
||||
return answer
|
||||
|
||||
def send_monitor_command(self, command: str) -> str:
|
||||
self.run_callbacks()
|
||||
with self.nested("sending monitor command: {}".format(command)):
|
||||
message = ("{}\n".format(command)).encode()
|
||||
assert self.monitor is not None
|
||||
@@ -509,6 +513,7 @@ class Machine:
|
||||
def execute(
|
||||
self, command: str, check_return: bool = True, timeout: Optional[int] = 900
|
||||
) -> Tuple[int, str]:
|
||||
self.run_callbacks()
|
||||
self.connect()
|
||||
|
||||
if timeout is not None:
|
||||
@@ -969,3 +974,7 @@ class Machine:
|
||||
self.shell.close()
|
||||
self.monitor.close()
|
||||
self.serial_thread.join()
|
||||
|
||||
def run_callbacks(self) -> None:
|
||||
for callback in self.callbacks:
|
||||
callback()
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
from typing import Callable, Optional
|
||||
import time
|
||||
|
||||
from .logger import rootlog
|
||||
|
||||
|
||||
class PollingConditionFailed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class PollingCondition:
|
||||
condition: Callable[[], bool]
|
||||
seconds_interval: float
|
||||
description: Optional[str]
|
||||
|
||||
last_called: float
|
||||
entered: bool
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
condition: Callable[[], Optional[bool]],
|
||||
seconds_interval: float = 2.0,
|
||||
description: Optional[str] = None,
|
||||
):
|
||||
self.condition = condition # type: ignore
|
||||
self.seconds_interval = seconds_interval
|
||||
|
||||
if description is None:
|
||||
if condition.__doc__:
|
||||
self.description = condition.__doc__
|
||||
else:
|
||||
self.description = condition.__name__
|
||||
else:
|
||||
self.description = str(description)
|
||||
|
||||
self.last_called = float("-inf")
|
||||
self.entered = False
|
||||
|
||||
def check(self) -> bool:
|
||||
if self.entered or not self.overdue:
|
||||
return True
|
||||
|
||||
with self, rootlog.nested(self.nested_message):
|
||||
rootlog.info(f"Time since last: {time.monotonic() - self.last_called:.2f}s")
|
||||
try:
|
||||
res = self.condition() # type: ignore
|
||||
except Exception:
|
||||
res = False
|
||||
res = res is None or res
|
||||
rootlog.info(self.status_message(res))
|
||||
return res
|
||||
|
||||
def maybe_raise(self) -> None:
|
||||
if not self.check():
|
||||
raise PollingConditionFailed(self.status_message(False))
|
||||
|
||||
def status_message(self, status: bool) -> str:
|
||||
return f"Polling condition {'succeeded' if status else 'failed'}: {self.description}"
|
||||
|
||||
@property
|
||||
def nested_message(self) -> str:
|
||||
nested_message = ["Checking polling condition"]
|
||||
if self.description is not None:
|
||||
nested_message.append(repr(self.description))
|
||||
|
||||
return " ".join(nested_message)
|
||||
|
||||
@property
|
||||
def overdue(self) -> bool:
|
||||
return self.last_called + self.seconds_interval < time.monotonic()
|
||||
|
||||
def __enter__(self) -> None:
|
||||
self.entered = True
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback) -> None: # type: ignore
|
||||
self.entered = False
|
||||
self.last_called = time.monotonic()
|
||||
@@ -22,8 +22,15 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
scudo = {
|
||||
libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so";
|
||||
scudo = let
|
||||
platformMap = {
|
||||
aarch64-linux = "aarch64";
|
||||
x86_64-linux = "x86_64";
|
||||
};
|
||||
|
||||
systemPlatform = platformMap.${pkgs.stdenv.hostPlatform.system} or (throw "scudo not supported on ${pkgs.stdenv.hostPlatform.system}");
|
||||
in {
|
||||
libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-${systemPlatform}.so";
|
||||
description = ''
|
||||
A user-mode allocator based on LLVM Sanitizer’s CombinedAllocator,
|
||||
which aims at providing additional mitigations against heap based
|
||||
|
||||
@@ -196,9 +196,7 @@ in
|
||||
protocols.source = pkgs.iana-etc + "/etc/protocols";
|
||||
|
||||
# /etc/hosts: Hostname-to-IP mappings.
|
||||
hosts.source = pkgs.runCommand "hosts" {} ''
|
||||
cat ${escapeShellArgs cfg.hostFiles} > $out
|
||||
'';
|
||||
hosts.source = pkgs.concatText "hosts" cfg.hostFiles;
|
||||
|
||||
# /etc/netgroup: Network-wide groups.
|
||||
netgroup.text = mkDefault "";
|
||||
|
||||
@@ -351,7 +351,7 @@ foreach my $u (values %usersOut) {
|
||||
push @subGids, $value;
|
||||
}
|
||||
|
||||
if($u->{isNormalUser}) {
|
||||
if($u->{autoSubUidGidRange}) {
|
||||
my $subordinate = allocSubUid($name);
|
||||
$subUidMap->{$name} = $subordinate;
|
||||
my $value = join(":", ($name, $subordinate, 65536));
|
||||
|
||||
@@ -204,6 +204,16 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
autoSubUidGidRange = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Automatically allocate subordinate user and group ids for this user.
|
||||
Allocated range is currently always of size 65536.
|
||||
'';
|
||||
};
|
||||
|
||||
createHome = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -320,6 +330,9 @@ let
|
||||
(mkIf (!cfg.mutableUsers && config.initialHashedPassword != null) {
|
||||
hashedPassword = mkDefault config.initialHashedPassword;
|
||||
})
|
||||
(mkIf (config.isNormalUser && config.subUidRanges == [] && config.subGidRanges == []) {
|
||||
autoSubUidGidRange = mkDefault true;
|
||||
})
|
||||
];
|
||||
|
||||
};
|
||||
@@ -419,7 +432,7 @@ let
|
||||
{ inherit (u)
|
||||
name uid group description home createHome isSystemUser
|
||||
password passwordFile hashedPassword
|
||||
isNormalUser subUidRanges subGidRanges
|
||||
autoSubUidGidRange subUidRanges subGidRanges
|
||||
initialPassword initialHashedPassword;
|
||||
shell = utils.toShellPath u.shell;
|
||||
}) cfg.users;
|
||||
|
||||
@@ -31,7 +31,6 @@ in {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Turn on this option if you want to enable all the firmware with a license allowing redistribution.
|
||||
(i.e. free firmware and <literal>firmware-linux-nonfree</literal>)
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -51,7 +50,7 @@ in {
|
||||
config = mkMerge [
|
||||
(mkIf (cfg.enableAllFirmware || cfg.enableRedistributableFirmware) {
|
||||
hardware.firmware = with pkgs; [
|
||||
firmwareLinuxNonfree
|
||||
linux-firmware
|
||||
intel2200BGFirmware
|
||||
rtl8192su-firmware
|
||||
rt5677-firmware
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
{ config, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.hardware.cpu.intel.sgx.provision;
|
||||
defaultGroup = "sgx_prv";
|
||||
cfg = config.hardware.cpu.intel.sgx;
|
||||
defaultPrvGroup = "sgx_prv";
|
||||
in
|
||||
{
|
||||
options.hardware.cpu.intel.sgx.enableDcapCompat = mkOption {
|
||||
description = ''
|
||||
Whether to enable backward compatibility for SGX software build for the
|
||||
out-of-tree Intel SGX DCAP driver.
|
||||
|
||||
Creates symbolic links for the SGX devices <literal>/dev/sgx_enclave</literal>
|
||||
and <literal>/dev/sgx_provision</literal> to make them available as
|
||||
<literal>/dev/sgx/enclave</literal> and <literal>/dev/sgx/provision</literal>,
|
||||
respectively.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
options.hardware.cpu.intel.sgx.provision = {
|
||||
enable = mkEnableOption "access to the Intel SGX provisioning device";
|
||||
user = mkOption {
|
||||
@@ -15,7 +29,7 @@ in
|
||||
group = mkOption {
|
||||
description = "Group to assign to the SGX provisioning device.";
|
||||
type = types.str;
|
||||
default = defaultGroup;
|
||||
default = defaultPrvGroup;
|
||||
};
|
||||
mode = mkOption {
|
||||
description = "Mode to set for the SGX provisioning device.";
|
||||
@@ -24,24 +38,32 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
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";
|
||||
}
|
||||
];
|
||||
config = mkMerge [
|
||||
(mkIf cfg.provision.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = hasAttr cfg.provision.user config.users.users;
|
||||
message = "Given user does not exist";
|
||||
}
|
||||
{
|
||||
assertion = (cfg.provision.group == defaultPrvGroup) || (hasAttr cfg.provision.group config.users.groups);
|
||||
message = "Given group does not exist";
|
||||
}
|
||||
];
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == defaultGroup) {
|
||||
"${cfg.group}" = { };
|
||||
};
|
||||
users.groups = optionalAttrs (cfg.provision.group == defaultPrvGroup) {
|
||||
"${cfg.provision.group}" = { };
|
||||
};
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${cfg.user}", GROUP="${cfg.group}", MODE="${cfg.mode}"
|
||||
'';
|
||||
};
|
||||
services.udev.extraRules = with cfg.provision; ''
|
||||
SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${user}", GROUP="${group}", MODE="${mode}"
|
||||
'';
|
||||
})
|
||||
(mkIf cfg.enableDcapCompat {
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="misc", KERNEL=="sgx_enclave", SYMLINK+="sgx/enclave"
|
||||
SUBSYSTEM=="misc", KERNEL=="sgx_provision", SYMLINK+="sgx/provision"
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.hardware.hackrf;
|
||||
|
||||
in
|
||||
{
|
||||
options.hardware.hackrf = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enables hackrf udev rules and ensures 'plugdev' group exists.
|
||||
This is a prerequisite to using HackRF devices without being root, since HackRF USB descriptors will be owned by plugdev through udev.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.udev.packages = [ pkgs.hackrf ];
|
||||
users.groups.plugdev = { };
|
||||
};
|
||||
}
|
||||
@@ -5,10 +5,14 @@ let
|
||||
|
||||
in {
|
||||
options.hardware.rtl-sdr = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Enables rtl-sdr udev rules, ensures 'plugdev' group exists, and blacklists DVB kernel modules.
|
||||
This is a prerequisite to using devices supported by rtl-sdr without being root, since rtl-sdr USB descriptors will be owned by plugdev through udev.
|
||||
'';
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enables rtl-sdr udev rules, ensures 'plugdev' group exists, and blacklists DVB kernel modules.
|
||||
This is a prerequisite to using devices supported by rtl-sdr without being root, since rtl-sdr USB descriptors will be owned by plugdev through udev.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
@@ -11,23 +11,17 @@ let
|
||||
enabled = elem "amdgpu-pro" drivers;
|
||||
|
||||
package = config.boot.kernelPackages.amdgpu-pro;
|
||||
package32 = pkgs.pkgsi686Linux.linuxPackages.amdgpu-pro.override { libsOnly = true; kernel = null; };
|
||||
package32 = pkgs.pkgsi686Linux.linuxPackages.amdgpu-pro.override { kernel = null; };
|
||||
|
||||
opengl = config.hardware.opengl;
|
||||
|
||||
kernel = pkgs.linux_4_9.override {
|
||||
extraConfig = ''
|
||||
KALLSYMS_ALL y
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
config = mkIf enabled {
|
||||
|
||||
nixpkgs.config.xorg.abiCompat = "1.19";
|
||||
nixpkgs.config.xorg.abiCompat = "1.20";
|
||||
|
||||
services.xserver.drivers = singleton
|
||||
{ name = "amdgpu"; modules = [ package ]; display = true; };
|
||||
@@ -36,31 +30,39 @@ in
|
||||
hardware.opengl.package32 = package32;
|
||||
hardware.opengl.setLdLibraryPath = true;
|
||||
|
||||
boot.extraModulePackages = [ package ];
|
||||
boot.extraModulePackages = [ package.kmod ];
|
||||
|
||||
boot.kernelPackages =
|
||||
pkgs.recurseIntoAttrs (pkgs.linuxPackagesFor kernel);
|
||||
boot.kernelPackages = pkgs.linuxKernel.packagesFor
|
||||
(pkgs.linuxKernel.kernels.linux_5_10.override {
|
||||
structuredExtraConfig = {
|
||||
DEVICE_PRIVATE = kernel.yes;
|
||||
KALLSYMS_ALL = kernel.yes;
|
||||
};
|
||||
});
|
||||
|
||||
boot.blacklistedKernelModules = [ "radeon" ];
|
||||
|
||||
hardware.firmware = [ package ];
|
||||
hardware.firmware = [ package.fw ];
|
||||
|
||||
system.activationScripts.setup-amdgpu-pro = ''
|
||||
mkdir -p /run/lib
|
||||
ln -sfn ${package}/lib ${package.libCompatDir}
|
||||
ln -sfn ${package} /run/amdgpu-pro
|
||||
'' + optionalString opengl.driSupport32Bit ''
|
||||
ln -sfn ${package32}/lib ${package32.libCompatDir}
|
||||
ln -sfn ${package}/opt/amdgpu{,-pro} /run
|
||||
'';
|
||||
|
||||
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
||||
(isYes "DEVICE_PRIVATE")
|
||||
(isYes "KALLSYMS_ALL")
|
||||
];
|
||||
|
||||
boot.initrd.extraUdevRulesCommands = ''
|
||||
cp -v ${package}/etc/udev/rules.d/*.rules $out/
|
||||
'';
|
||||
|
||||
environment.systemPackages =
|
||||
[ package.vulkan ] ++
|
||||
# this isn't really DRI, but we'll reuse this option for now
|
||||
optional config.hardware.opengl.driSupport32Bit package32.vulkan;
|
||||
|
||||
environment.etc = {
|
||||
"amd/amdrc".source = package + "/etc/amd/amdrc";
|
||||
"amd/amdapfxx.blb".source = package + "/etc/amd/amdapfxx.blb";
|
||||
"gbm/gbm.conf".source = package + "/etc/gbm/gbm.conf";
|
||||
"modprobe.d/blacklist-radeon.conf".source = package + "/etc/modprobe.d/blacklist-radeon.conf";
|
||||
amd.source = package + "/etc/amd";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -94,7 +94,9 @@ with lib;
|
||||
|
||||
system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
|
||||
#!ipxe
|
||||
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams}
|
||||
# Use the cmdline variable to allow the user to specify custom kernel params
|
||||
# when chainloading this script from other iPXE scripts like netboot.xyz
|
||||
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
|
||||
initrd initrd
|
||||
boot
|
||||
'';
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
imports = [
|
||||
../../profiles/installation-device.nix
|
||||
./sd-image-riscv64-qemu.nix
|
||||
];
|
||||
|
||||
# the installation media is also the installation target,
|
||||
# so we don't want to provide the installation configuration.nix.
|
||||
installer.cloneConfig = false;
|
||||
}
|
||||
@@ -104,4 +104,6 @@ chroot_add_resolv_conf "$mountPoint" || print "ERROR: failed to set up resolv.co
|
||||
chroot "$mountPoint" systemd-tmpfiles --create --remove --exclude-prefix=/dev 1>&2 || true
|
||||
)
|
||||
|
||||
unset TMPDIR
|
||||
|
||||
exec chroot "$mountPoint" "${command[@]}"
|
||||
|
||||
@@ -61,22 +61,90 @@ let
|
||||
in scrubbedEval.options;
|
||||
baseOptionsJSON =
|
||||
let
|
||||
filter =
|
||||
filterIntoStore =
|
||||
builtins.filterSource
|
||||
(n: t:
|
||||
(t == "directory" -> baseNameOf n != "tests")
|
||||
&& (t == "file" -> hasSuffix ".nix" n)
|
||||
);
|
||||
|
||||
# Figure out if Nix runs in pure evaluation mode. May return true in
|
||||
# impure mode, but this is highly unlikely.
|
||||
# We need to know because of https://github.com/NixOS/nix/issues/1888
|
||||
# and https://github.com/NixOS/nix/issues/5868
|
||||
isPureEval = builtins.getEnv "PATH" == "" && builtins.getEnv "_" == "";
|
||||
|
||||
# Return a nixpkgs subpath with minimal copying.
|
||||
#
|
||||
# The sources for the base options json derivation can come in one of
|
||||
# two forms:
|
||||
# - single source: a store path with all of nixpkgs, postfix with
|
||||
# subpaths to access various directories. This has the benefit of
|
||||
# not creating copies of these subtrees in the Nix store, but
|
||||
# can cause unnecessary rebuilds if you update the Nixpkgs `pkgs`
|
||||
# tree often.
|
||||
# - split sources: multiple store paths with subdirectories of
|
||||
# nixpkgs that exclude the bulk of the pkgs directory.
|
||||
# This requires more copying and hashing during evaluation but
|
||||
# requires fewer files to be copied. This method produces fewer
|
||||
# unnecessary rebuilds of the base options json.
|
||||
#
|
||||
# Flake
|
||||
#
|
||||
# Flakes always put a copy of the full nixpkgs sources in the store,
|
||||
# so we can use the "single source" method. This method is ideal
|
||||
# for using nixpkgs as a dependency, as the base options json will be
|
||||
# substitutable from cache.nixos.org.
|
||||
#
|
||||
# This requires that the `self.outPath` is wired into `pkgs` correctly,
|
||||
# which is done for you if `pkgs` comes from the `lib.nixosSystem` or
|
||||
# `legacyPackages` flake attributes.
|
||||
#
|
||||
# Other Nixpkgs invocation
|
||||
#
|
||||
# If you do not use the known-correct flake attributes, but rather
|
||||
# invoke Nixpkgs yourself, set `config.path` to the correct path value,
|
||||
# e.g. `import nixpkgs { config.path = nixpkgs; }`.
|
||||
#
|
||||
# Choosing between single or split source paths
|
||||
#
|
||||
# We make assumptions based on the type and contents of `pkgs.path`.
|
||||
# By passing a different `config.path` to Nixpkgs, you can influence
|
||||
# how your documentation cache is evaluated and rebuilt.
|
||||
#
|
||||
# Single source
|
||||
# - If pkgs.path is a string containing a store path, the code has no
|
||||
# choice but to create this store path, if it hasn't already been.
|
||||
# We assume that the "single source" method is most efficient.
|
||||
# - If pkgs.path is a path value containing that is a store path,
|
||||
# we try to convert it to a string with context without copying.
|
||||
# This occurs for example when nixpkgs was fetched and using its
|
||||
# default `config.path`, which is `./.`.
|
||||
# Nix currently does not allow this conversion when evaluating in
|
||||
# pure mode. If the conversion is not possible, we use the
|
||||
# "split source" method.
|
||||
#
|
||||
# Split source
|
||||
# - If pkgs.path is a path value that is not a store path, we assume
|
||||
# that it's unlikely for all of nixpkgs to end up in the store for
|
||||
# other reasons and try to keep both the copying and rebuilds low.
|
||||
pull =
|
||||
if builtins.typeOf pkgs.path == "string" && isStorePath pkgs.path then
|
||||
dir: "${pkgs.path}/${dir}"
|
||||
else if !isPureEval && isStorePath pkgs.path then
|
||||
dir: "${builtins.storePath pkgs.path}/${dir}"
|
||||
else
|
||||
dir: filterIntoStore "${toString pkgs.path}/${dir}";
|
||||
in
|
||||
pkgs.runCommand "lazy-options.json" {
|
||||
libPath = filter "${toString pkgs.path}/lib";
|
||||
pkgsLibPath = filter "${toString pkgs.path}/pkgs/pkgs-lib";
|
||||
nixosPath = filter "${toString pkgs.path}/nixos";
|
||||
libPath = pull "lib";
|
||||
pkgsLibPath = pull "pkgs/pkgs-lib";
|
||||
nixosPath = pull "nixos";
|
||||
modules = map (p: ''"${removePrefix "${modulesPath}/" (toString p)}"'') docModules.lazy;
|
||||
} ''
|
||||
export NIX_STORE_DIR=$TMPDIR/store
|
||||
export NIX_STATE_DIR=$TMPDIR/state
|
||||
${pkgs.nix}/bin/nix-instantiate \
|
||||
${pkgs.buildPackages.nix}/bin/nix-instantiate \
|
||||
--show-trace \
|
||||
--eval --json --strict \
|
||||
--argstr libPath "$libPath" \
|
||||
|
||||
@@ -182,7 +182,7 @@ in
|
||||
yandexdisk = 143;
|
||||
mxisd = 144; # was once collectd
|
||||
#consul = 145;# dynamically allocated as of 2021-09-03
|
||||
mailpile = 146;
|
||||
#mailpile = 146; # removed 2022-01-12
|
||||
redmine = 147;
|
||||
#seeks = 148; # removed 2020-06-21
|
||||
prosody = 149;
|
||||
@@ -353,6 +353,7 @@ in
|
||||
distcc = 321;
|
||||
webdav = 322;
|
||||
pipewire = 323;
|
||||
rstudio-server = 324;
|
||||
|
||||
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
|
||||
|
||||
@@ -502,7 +503,7 @@ in
|
||||
#yandexdisk = 143; # unused
|
||||
mxisd = 144; # was once collectd
|
||||
#consul = 145; # unused
|
||||
mailpile = 146;
|
||||
#mailpile = 146; # removed 2022-01-12
|
||||
redmine = 147;
|
||||
#seeks = 148; # removed 2020-06-21
|
||||
prosody = 149;
|
||||
@@ -660,6 +661,7 @@ in
|
||||
distcc = 321;
|
||||
webdav = 322;
|
||||
pipewire = 323;
|
||||
rstudio-server = 324;
|
||||
|
||||
# When adding a gid, make sure it doesn't match an existing
|
||||
# uid. Users and groups with the same name should have equal
|
||||
|
||||
@@ -5,11 +5,14 @@ with lib;
|
||||
let
|
||||
cfg = config.services.locate;
|
||||
isMLocate = hasPrefix "mlocate" cfg.locate.name;
|
||||
isPLocate = hasPrefix "plocate" cfg.locate.name;
|
||||
isMorPLocate = (isMLocate || isPLocate);
|
||||
isFindutils = hasPrefix "findutils" cfg.locate.name;
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ])
|
||||
(mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths" )
|
||||
(mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths")
|
||||
];
|
||||
|
||||
options.services.locate = with types; {
|
||||
@@ -163,7 +166,16 @@ in {
|
||||
|
||||
prunePaths = mkOption {
|
||||
type = listOf path;
|
||||
default = [ "/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store" "/nix/var/log/nix" ];
|
||||
default = [
|
||||
"/tmp"
|
||||
"/var/tmp"
|
||||
"/var/cache"
|
||||
"/var/lock"
|
||||
"/var/run"
|
||||
"/var/spool"
|
||||
"/nix/store"
|
||||
"/nix/var/log/nix"
|
||||
];
|
||||
description = ''
|
||||
Which paths to exclude from indexing
|
||||
'';
|
||||
@@ -188,26 +200,38 @@ in {
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.groups = mkIf isMLocate { mlocate = {}; };
|
||||
users.groups = mkMerge [
|
||||
(mkIf isMLocate { mlocate = { }; })
|
||||
(mkIf isPLocate { plocate = { }; })
|
||||
];
|
||||
|
||||
security.wrappers = mkIf isMLocate {
|
||||
locate = {
|
||||
group = "mlocate";
|
||||
owner = "root";
|
||||
permissions = "u+rx,g+x,o+x";
|
||||
setgid = true;
|
||||
setuid = false;
|
||||
source = "${cfg.locate}/bin/locate";
|
||||
security.wrappers =
|
||||
let
|
||||
common = {
|
||||
owner = "root";
|
||||
permissions = "u+rx,g+x,o+x";
|
||||
setgid = true;
|
||||
setuid = false;
|
||||
};
|
||||
mlocate = (mkIf isMLocate {
|
||||
group = "mlocate";
|
||||
source = "${cfg.locate}/bin/locate";
|
||||
});
|
||||
plocate = (mkIf isPLocate {
|
||||
group = "plocate";
|
||||
source = "${cfg.locate}/bin/plocate";
|
||||
});
|
||||
in
|
||||
mkIf isMorPLocate {
|
||||
locate = mkMerge [ common mlocate plocate ];
|
||||
plocate = (mkIf isPLocate (mkMerge [ common plocate ]));
|
||||
};
|
||||
};
|
||||
|
||||
nixpkgs.config = { locate.dbfile = cfg.output; };
|
||||
|
||||
environment.systemPackages = [ cfg.locate ];
|
||||
|
||||
environment.variables = mkIf (!isMLocate)
|
||||
{ LOCATE_PATH = cfg.output;
|
||||
};
|
||||
environment.variables = mkIf (!isMorPLocate) { LOCATE_PATH = cfg.output; };
|
||||
|
||||
environment.etc = {
|
||||
# write /etc/updatedb.conf for manual calls to `updatedb`
|
||||
@@ -221,57 +245,65 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
warnings = optional (isMLocate && cfg.localuser != null) "mlocate does not support the services.locate.localuser option; updatedb will run as root. (Silence with services.locate.localuser = null.)"
|
||||
++ optional (isFindutils && cfg.pruneNames != []) "findutils locate does not support pruning by directory component"
|
||||
++ optional (isFindutils && cfg.pruneBindMounts) "findutils locate does not support skipping bind mounts";
|
||||
warnings = optional (isMorPLocate && cfg.localuser != null)
|
||||
"mlocate does not support the services.locate.localuser option; updatedb will run as root. (Silence with services.locate.localuser = null.)"
|
||||
++ optional (isFindutils && cfg.pruneNames != [ ])
|
||||
"findutils locate does not support pruning by directory component"
|
||||
++ optional (isFindutils && cfg.pruneBindMounts)
|
||||
"findutils locate does not support skipping bind mounts";
|
||||
|
||||
systemd.services.update-locatedb =
|
||||
{ description = "Update Locate Database";
|
||||
path = mkIf (!isMLocate) [ pkgs.su ];
|
||||
systemd.services.update-locatedb = {
|
||||
description = "Update Locate Database";
|
||||
path = mkIf (!isMorPLocate) [ pkgs.su ];
|
||||
|
||||
# mlocate's updatedb takes flags via a configuration file or
|
||||
# on the command line, but not by environment variable.
|
||||
script =
|
||||
if isMLocate
|
||||
then let toFlags = x: optional (cfg.${x} != [])
|
||||
"--${lib.toLower x} '${concatStringsSep " " cfg.${x}}'";
|
||||
args = concatLists (map toFlags ["pruneFS" "pruneNames" "prunePaths"]);
|
||||
in ''
|
||||
# mlocate's updatedb takes flags via a configuration file or
|
||||
# on the command line, but not by environment variable.
|
||||
script =
|
||||
if isMorPLocate then
|
||||
let
|
||||
toFlags = x:
|
||||
optional (cfg.${x} != [ ])
|
||||
"--${lib.toLower x} '${concatStringsSep " " cfg.${x}}'";
|
||||
args = concatLists (map toFlags [ "pruneFS" "pruneNames" "prunePaths" ]);
|
||||
in
|
||||
''
|
||||
exec ${cfg.locate}/bin/updatedb \
|
||||
--output ${toString cfg.output} ${concatStringsSep " " args} \
|
||||
--prune-bind-mounts ${if cfg.pruneBindMounts then "yes" else "no"} \
|
||||
${concatStringsSep " " cfg.extraFlags}
|
||||
''
|
||||
else ''
|
||||
exec ${cfg.locate}/bin/updatedb \
|
||||
${optionalString (cfg.localuser != null && ! isMLocate) "--localuser=${cfg.localuser}"} \
|
||||
--output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
|
||||
'';
|
||||
environment = optionalAttrs (!isMLocate) {
|
||||
PRUNEFS = concatStringsSep " " cfg.pruneFS;
|
||||
PRUNEPATHS = concatStringsSep " " cfg.prunePaths;
|
||||
PRUNENAMES = concatStringsSep " " cfg.pruneNames;
|
||||
PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no";
|
||||
};
|
||||
serviceConfig.Nice = 19;
|
||||
serviceConfig.IOSchedulingClass = "idle";
|
||||
serviceConfig.PrivateTmp = "yes";
|
||||
serviceConfig.PrivateNetwork = "yes";
|
||||
serviceConfig.NoNewPrivileges = "yes";
|
||||
serviceConfig.ReadOnlyPaths = "/";
|
||||
# Use dirOf cfg.output because mlocate creates temporary files next to
|
||||
# the actual database. We could specify and create them as well,
|
||||
# but that would make this quite brittle when they change something.
|
||||
# NOTE: If /var/cache does not exist, this leads to the misleading error message:
|
||||
# update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory
|
||||
serviceConfig.ReadWritePaths = dirOf cfg.output;
|
||||
else ''
|
||||
exec ${cfg.locate}/bin/updatedb \
|
||||
${optionalString (cfg.localuser != null && !isMorPLocate) "--localuser=${cfg.localuser}"} \
|
||||
--output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
|
||||
'';
|
||||
environment = optionalAttrs (!isMorPLocate) {
|
||||
PRUNEFS = concatStringsSep " " cfg.pruneFS;
|
||||
PRUNEPATHS = concatStringsSep " " cfg.prunePaths;
|
||||
PRUNENAMES = concatStringsSep " " cfg.pruneNames;
|
||||
PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no";
|
||||
};
|
||||
serviceConfig.Nice = 19;
|
||||
serviceConfig.IOSchedulingClass = "idle";
|
||||
serviceConfig.PrivateTmp = "yes";
|
||||
serviceConfig.PrivateNetwork = "yes";
|
||||
serviceConfig.NoNewPrivileges = "yes";
|
||||
serviceConfig.ReadOnlyPaths = "/";
|
||||
# Use dirOf cfg.output because mlocate creates temporary files next to
|
||||
# the actual database. We could specify and create them as well,
|
||||
# but that would make this quite brittle when they change something.
|
||||
# NOTE: If /var/cache does not exist, this leads to the misleading error message:
|
||||
# update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory
|
||||
serviceConfig.ReadWritePaths = dirOf cfg.output;
|
||||
};
|
||||
|
||||
systemd.timers.update-locatedb = mkIf (cfg.interval != "never")
|
||||
{ description = "Update timer for locate database";
|
||||
partOf = [ "update-locatedb.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = cfg.interval;
|
||||
};
|
||||
systemd.timers.update-locatedb = mkIf (cfg.interval != "never") {
|
||||
description = "Update timer for locate database";
|
||||
partOf = [ "update-locatedb.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig.OnCalendar = cfg.interval;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ SuperSandro2000 ];
|
||||
}
|
||||
|
||||
@@ -59,11 +59,18 @@ let
|
||||
inherit (cfg) config overlays localSystem crossSystem;
|
||||
};
|
||||
|
||||
# NOTE: flake.nix assumes that nixpkgs.config is only used with ../../..
|
||||
# as nixpkgs.config.path should be equivalent to ../../..
|
||||
finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
imports = [
|
||||
./assertions.nix
|
||||
./meta.nix
|
||||
];
|
||||
|
||||
options.nixpkgs = {
|
||||
|
||||
pkgs = mkOption {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{ evalMinimalConfig, pkgs, lib, stdenv }:
|
||||
lib.recurseIntoAttrs {
|
||||
invokeNixpkgsSimple =
|
||||
(evalMinimalConfig ({ config, modulesPath, ... }: {
|
||||
imports = [ (modulesPath + "/misc/nixpkgs.nix") ];
|
||||
nixpkgs.system = stdenv.hostPlatform.system;
|
||||
}))._module.args.pkgs.hello;
|
||||
}
|
||||
@@ -53,6 +53,7 @@
|
||||
./hardware/flirc.nix
|
||||
./hardware/gpgsmartcards.nix
|
||||
./hardware/i2c.nix
|
||||
./hardware/hackrf.nix
|
||||
./hardware/sensor/hddtemp.nix
|
||||
./hardware/sensor/iio.nix
|
||||
./hardware/keyboard/teck.nix
|
||||
@@ -197,6 +198,7 @@
|
||||
./programs/ssmtp.nix
|
||||
./programs/sysdig.nix
|
||||
./programs/systemtap.nix
|
||||
./programs/starship.nix
|
||||
./programs/steam.nix
|
||||
./programs/sway.nix
|
||||
./programs/system-config-printer.nix
|
||||
@@ -226,7 +228,7 @@
|
||||
./programs/zsh/zsh-autosuggestions.nix
|
||||
./programs/zsh/zsh-syntax-highlighting.nix
|
||||
./rename.nix
|
||||
./security/acme.nix
|
||||
./security/acme
|
||||
./security/apparmor.nix
|
||||
./security/audit.nix
|
||||
./security/auditd.nix
|
||||
@@ -364,6 +366,7 @@
|
||||
./services/desktops/malcontent.nix
|
||||
./services/desktops/pipewire/pipewire.nix
|
||||
./services/desktops/pipewire/pipewire-media-session.nix
|
||||
./services/desktops/pipewire/wireplumber.nix
|
||||
./services/desktops/gnome/at-spi2-core.nix
|
||||
./services/desktops/gnome/chrome-gnome-shell.nix
|
||||
./services/desktops/gnome/evolution-data-server.nix
|
||||
@@ -391,11 +394,13 @@
|
||||
./services/development/hoogle.nix
|
||||
./services/development/jupyter/default.nix
|
||||
./services/development/jupyterhub/default.nix
|
||||
./services/development/rstudio-server/default.nix
|
||||
./services/development/lorri.nix
|
||||
./services/display-managers/greetd.nix
|
||||
./services/editors/emacs.nix
|
||||
./services/editors/infinoted.nix
|
||||
./services/finance/odoo.nix
|
||||
./services/games/asf.nix
|
||||
./services/games/crossfire-server.nix
|
||||
./services/games/deliantra-server.nix
|
||||
./services/games/factorio.nix
|
||||
@@ -540,6 +545,7 @@
|
||||
./services/misc/gollum.nix
|
||||
./services/misc/gpsd.nix
|
||||
./services/misc/headphones.nix
|
||||
./services/misc/heisenbridge.nix
|
||||
./services/misc/greenclip.nix
|
||||
./services/misc/home-assistant.nix
|
||||
./services/misc/ihaskell.nix
|
||||
@@ -735,6 +741,7 @@
|
||||
./services/networking/ejabberd.nix
|
||||
./services/networking/epmd.nix
|
||||
./services/networking/ergo.nix
|
||||
./services/networking/ergochat.nix
|
||||
./services/networking/eternal-terminal.nix
|
||||
./services/networking/fakeroute.nix
|
||||
./services/networking/ferm.nix
|
||||
@@ -743,6 +750,7 @@
|
||||
./services/networking/flannel.nix
|
||||
./services/networking/freenet.nix
|
||||
./services/networking/freeradius.nix
|
||||
./services/networking/frr.nix
|
||||
./services/networking/gateone.nix
|
||||
./services/networking/gdomap.nix
|
||||
./services/networking/ghostunnel.nix
|
||||
@@ -784,7 +792,6 @@
|
||||
./services/networking/lldpd.nix
|
||||
./services/networking/logmein-hamachi.nix
|
||||
./services/networking/lxd-image-server.nix
|
||||
./services/networking/mailpile.nix
|
||||
./services/networking/magic-wormhole-mailbox-server.nix
|
||||
./services/networking/matterbridge.nix
|
||||
./services/networking/mjpg-streamer.nix
|
||||
@@ -796,6 +803,7 @@
|
||||
./services/networking/miredo.nix
|
||||
./services/networking/mstpd.nix
|
||||
./services/networking/mtprotoproxy.nix
|
||||
./services/networking/mtr-exporter.nix
|
||||
./services/networking/mullvad-vpn.nix
|
||||
./services/networking/multipath.nix
|
||||
./services/networking/murmur.nix
|
||||
@@ -888,6 +896,7 @@
|
||||
./services/networking/tcpcrypt.nix
|
||||
./services/networking/teamspeak3.nix
|
||||
./services/networking/tedicross.nix
|
||||
./services/networking/teleport.nix
|
||||
./services/networking/thelounge.nix
|
||||
./services/networking/tinc.nix
|
||||
./services/networking/tinydns.nix
|
||||
@@ -959,6 +968,7 @@
|
||||
./services/security/vault.nix
|
||||
./services/security/vaultwarden/default.nix
|
||||
./services/security/yubikey-agent.nix
|
||||
./services/system/cachix-agent/default.nix
|
||||
./services/system/cloud-init.nix
|
||||
./services/system/dbus.nix
|
||||
./services/system/earlyoom.nix
|
||||
@@ -988,6 +998,7 @@
|
||||
./services/web-apps/bookstack.nix
|
||||
./services/web-apps/calibre-web.nix
|
||||
./services/web-apps/code-server.nix
|
||||
./services/web-apps/baget.nix
|
||||
./services/web-apps/convos.nix
|
||||
./services/web-apps/cryptpad.nix
|
||||
./services/web-apps/dex.nix
|
||||
@@ -1011,6 +1022,7 @@
|
||||
./services/web-apps/keycloak.nix
|
||||
./services/web-apps/lemmy.nix
|
||||
./services/web-apps/invidious.nix
|
||||
./services/web-apps/invoiceplane.nix
|
||||
./services/web-apps/limesurvey.nix
|
||||
./services/web-apps/mastodon.nix
|
||||
./services/web-apps/mattermost.nix
|
||||
@@ -1026,6 +1038,7 @@
|
||||
./services/web-apps/plausible.nix
|
||||
./services/web-apps/pgpkeyserver-lite.nix
|
||||
./services/web-apps/powerdns-admin.nix
|
||||
./services/web-apps/prosody-filer.nix
|
||||
./services/web-apps/matomo.nix
|
||||
./services/web-apps/openwebrx.nix
|
||||
./services/web-apps/restya-board.nix
|
||||
@@ -1177,6 +1190,7 @@
|
||||
./tasks/powertop.nix
|
||||
./testing/service-runner.nix
|
||||
./virtualisation/anbox.nix
|
||||
./virtualisation/build-vm.nix
|
||||
./virtualisation/container-config.nix
|
||||
./virtualisation/containerd.nix
|
||||
./virtualisation/containers.nix
|
||||
|
||||
@@ -7,6 +7,7 @@ let
|
||||
|
||||
defaultProfile = filterAttrs (k: v: v != null) {
|
||||
HomepageLocation = cfg.homepageLocation;
|
||||
DefaultSearchProviderEnabled = cfg.defaultSearchProviderEnabled;
|
||||
DefaultSearchProviderSearchURL = cfg.defaultSearchProviderSearchURL;
|
||||
DefaultSearchProviderSuggestURL = cfg.defaultSearchProviderSuggestURL;
|
||||
ExtensionInstallForcelist = cfg.extensions;
|
||||
@@ -50,6 +51,13 @@ in
|
||||
example = "https://nixos.org";
|
||||
};
|
||||
|
||||
defaultSearchProviderEnabled = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
description = "Enable the default search provider.";
|
||||
default = null;
|
||||
example = true;
|
||||
};
|
||||
|
||||
defaultSearchProviderSearchURL = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "Chromium default search provider url.";
|
||||
|
||||
@@ -17,7 +17,7 @@ let
|
||||
exec ${askPassword} "$@"
|
||||
'';
|
||||
|
||||
knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
|
||||
knownHosts = attrValues cfg.knownHosts;
|
||||
|
||||
knownHostsText = (flip (concatMapStringsSep "\n") knownHosts
|
||||
(h: assert h.hostNames != [];
|
||||
@@ -25,6 +25,9 @@ let
|
||||
+ (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
|
||||
)) + "\n";
|
||||
|
||||
knownHostsFiles = [ "/etc/ssh/ssh_known_hosts" "/etc/ssh/ssh_known_hosts2" ]
|
||||
++ map pkgs.copyPathToStore cfg.knownHostsFiles;
|
||||
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
@@ -139,7 +142,7 @@ in
|
||||
|
||||
knownHosts = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
type = types.attrsOf (types.submodule ({ name, config, options, ... }: {
|
||||
options = {
|
||||
certAuthority = mkOption {
|
||||
type = types.bool;
|
||||
@@ -151,12 +154,22 @@ in
|
||||
};
|
||||
hostNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ name ] ++ config.extraHostNames;
|
||||
defaultText = literalExpression "[ ${name} ] ++ config.${options.extraHostNames}";
|
||||
description = ''
|
||||
DEPRECATED, please use <literal>extraHostNames</literal>.
|
||||
A list of host names and/or IP numbers used for accessing
|
||||
the host's ssh service.
|
||||
'';
|
||||
};
|
||||
extraHostNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
A list of additional host names and/or IP numbers used for
|
||||
accessing the host's ssh service.
|
||||
'';
|
||||
};
|
||||
publicKey = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
@@ -177,13 +190,12 @@ in
|
||||
You can fetch a public key file from a running SSH server
|
||||
with the <command>ssh-keyscan</command> command. The content
|
||||
of the file should follow the same format as described for
|
||||
the <literal>publicKey</literal> option.
|
||||
the <literal>publicKey</literal> option. Only a single key
|
||||
is supported. If a host has multiple keys, use
|
||||
<option>programs.ssh.knownHostsFiles</option> instead.
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = {
|
||||
hostNames = mkDefault [ name ];
|
||||
};
|
||||
}));
|
||||
description = ''
|
||||
The set of system-wide known SSH hosts.
|
||||
@@ -191,17 +203,36 @@ in
|
||||
example = literalExpression ''
|
||||
{
|
||||
myhost = {
|
||||
hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
|
||||
extraHostNames = [ "myhost.mydomain.com" "10.10.1.4" ];
|
||||
publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub;
|
||||
};
|
||||
myhost2 = {
|
||||
hostNames = [ "myhost2" ];
|
||||
publicKeyFile = ./pubkeys/myhost2_ssh_host_dsa_key.pub;
|
||||
};
|
||||
"myhost2.net".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILIRuJ8p1Fi+m6WkHV0KWnRfpM1WxoW8XAS+XvsSKsTK";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
knownHostsFiles = mkOption {
|
||||
default = [];
|
||||
type = with types; listOf path;
|
||||
description = ''
|
||||
Files containing SSH host keys to set as global known hosts.
|
||||
<literal>/etc/ssh/ssh_known_hosts</literal> (which is
|
||||
generated by <option>programs.ssh.knownHosts</option>) and
|
||||
<literal>/etc/ssh/ssh_known_hosts2</literal> are always
|
||||
included.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
./known_hosts
|
||||
(writeText "github.keys" '''
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
''')
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
kexAlgorithms = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
@@ -248,6 +279,9 @@ in
|
||||
message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
|
||||
});
|
||||
|
||||
warnings = mapAttrsToList (name: _: ''programs.ssh.knownHosts.${name}.hostNames is deprecated, use programs.ssh.knownHosts.${name}.extraHostNames'')
|
||||
(filterAttrs (name: {hostNames, extraHostNames, ...}: hostNames != [ name ] ++ extraHostNames) cfg.knownHosts);
|
||||
|
||||
# SSH configuration. Slight duplication of the sshd_config
|
||||
# generation in the sshd service.
|
||||
environment.etc."ssh/ssh_config".text =
|
||||
@@ -258,6 +292,7 @@ in
|
||||
# Generated options from other settings
|
||||
Host *
|
||||
AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
|
||||
GlobalKnownHostsFile ${concatStringsSep " " knownHostsFiles}
|
||||
|
||||
${optionalString cfg.setXAuthLocation ''
|
||||
XAuthLocation ${pkgs.xorg.xauth}/bin/xauth
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.starship;
|
||||
|
||||
settingsFormat = pkgs.formats.toml { };
|
||||
|
||||
settingsFile = settingsFormat.generate "starship.toml" cfg.settings;
|
||||
|
||||
in {
|
||||
options.programs.starship = {
|
||||
enable = mkEnableOption "the Starship shell prompt";
|
||||
|
||||
settings = mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration included in <literal>starship.toml</literal>.
|
||||
|
||||
See https://starship.rs/config/#prompt for documentation.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.bash.promptInit = ''
|
||||
if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then
|
||||
export STARSHIP_CONFIG=${settingsFile}
|
||||
eval "$(${pkgs.starship}/bin/starship init bash)"
|
||||
fi
|
||||
'';
|
||||
|
||||
programs.fish.promptInit = ''
|
||||
if test "$TERM" != "dumb" -a \( -z "$INSIDE_EMACS" -o "$INSIDE_EMACS" = "vterm" \)
|
||||
set -x STARSHIP_CONFIG ${settingsFile}
|
||||
eval (${pkgs.starship}/bin/starship init fish)
|
||||
end
|
||||
'';
|
||||
|
||||
programs.zsh.promptInit = ''
|
||||
if [[ $TERM != "dumb" && (-z $INSIDE_EMACS || $INSIDE_EMACS == "vterm") ]]; then
|
||||
export STARSHIP_CONFIG=${settingsFile}
|
||||
eval "$(${pkgs.starship}/bin/starship init zsh)"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
meta.maintainers = pkgs.starship.meta.maintainers;
|
||||
}
|
||||
@@ -90,10 +90,10 @@ in {
|
||||
extraPackages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = with pkgs; [
|
||||
swaylock swayidle alacritty dmenu
|
||||
swaylock swayidle foot dmenu
|
||||
];
|
||||
defaultText = literalExpression ''
|
||||
with pkgs; [ swaylock swayidle alacritty dmenu ];
|
||||
with pkgs; [ swaylock swayidle foot dmenu ];
|
||||
'';
|
||||
example = literalExpression ''
|
||||
with pkgs; [
|
||||
|
||||
@@ -7,7 +7,7 @@ let
|
||||
inherit (lib.modules) mkDefault mkIf;
|
||||
inherit (lib.options) literalExpression mkEnableOption mkOption;
|
||||
inherit (lib.strings) concatStringsSep optionalString toLower;
|
||||
inherit (lib.types) addCheck attrsOf lines nullOr package path port str strMatching submodule;
|
||||
inherit (lib.types) addCheck attrsOf lines nonEmptyStr nullOr package path port str strMatching submodule;
|
||||
|
||||
# Checks if given list of strings contains unique
|
||||
# elements when compared without considering case.
|
||||
@@ -35,7 +35,7 @@ let
|
||||
'';
|
||||
};
|
||||
options.server = mkOption {
|
||||
type = strMatching ".+";
|
||||
type = nonEmptyStr;
|
||||
example = "tsmserver.company.com";
|
||||
description = ''
|
||||
Host/domain name or IP address of the IBM TSM server.
|
||||
@@ -56,7 +56,7 @@ let
|
||||
'';
|
||||
};
|
||||
options.node = mkOption {
|
||||
type = strMatching ".+";
|
||||
type = nonEmptyStr;
|
||||
example = "MY-TSM-NODE";
|
||||
description = ''
|
||||
Target node name on the IBM TSM server.
|
||||
@@ -144,7 +144,7 @@ let
|
||||
};
|
||||
config.name = mkDefault name;
|
||||
# Client system-options file directives are explained here:
|
||||
# https://www.ibm.com/support/knowledgecenter/SSEQVQ_8.1.8/client/c_opt_usingopts.html
|
||||
# https://www.ibm.com/docs/en/spectrum-protect/8.1.13?topic=commands-processing-options
|
||||
config.extraConfig =
|
||||
mapAttrs (lib.trivial.const mkDefault) (
|
||||
{
|
||||
|
||||
+44
-48
@@ -17,35 +17,56 @@ with lib;
|
||||
(mkAliasOptionModule [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ])
|
||||
|
||||
# Completely removed modules
|
||||
(mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
|
||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "penultimate" ] "The corresponding package has removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "quagga" ] "the corresponding package has been removed from nixpkgs")
|
||||
(mkRemovedOptionModule [ "hardware" "brightnessctl" ] ''
|
||||
The brightnessctl module was removed because newer versions of
|
||||
brightnessctl don't require the udev rules anymore (they can use the
|
||||
systemd-logind API). Instead of using the module you can now
|
||||
simply add the brightnessctl package to environment.systemPackages.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "hardware" "u2f" ] ''
|
||||
The U2F modules module was removed, as all it did was adding the
|
||||
udev rules from libu2f-host to the system. Udev gained native support
|
||||
to handle FIDO security tokens, so this isn't necessary anymore.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||
(mkRemovedOptionModule [ "networking" "wicd" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
|
||||
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
|
||||
(mkRemovedOptionModule [ "security" "hideProcessInformation" ] ''
|
||||
The hidepid module was removed, since the underlying machinery
|
||||
is broken when using cgroups-v2.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "beegfsEnable" ] "The BeeGFS module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "cgmanager" "enable"] "cgmanager was deprecated by lxc and therefore removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "chronos" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "couchpotato" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "deepin" ] "The corresponding packages were removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "dnscrypt-proxy" ] "Use services.dnscrypt-proxy2 instead")
|
||||
(mkRemovedOptionModule [ "services" "firefox" "syncserver" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "marathon" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "moinmoin" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "mesos" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||
(mkRemovedOptionModule [ "networking" "wicd" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "beegfsEnable" ] "The BeeGFS module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
|
||||
(mkRemovedOptionModule ["services" "cgmanager" "enable"] "cgmanager was deprecated by lxc and therefore removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "osquery" ] "The osquery module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "flashpolicyd" ] "The flashpolicyd module has been removed. Adobe Flash Player is deprecated.")
|
||||
(mkRemovedOptionModule [ "services" "fourStore" ] "The fourStore module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "frab" ] "The frab module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "frab" ] "The frab module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "kippo" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "mailpile" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "marathon" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "mathics" ] "The Mathics module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "meguca" ] "Use meguca has been removed from nixpkgs")
|
||||
(mkRemovedOptionModule [ "services" "mesos" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "moinmoin" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "mwlib" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
|
||||
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
|
||||
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
|
||||
services.xserver.multitouch (which uses xf86_input_mtrack) has been removed
|
||||
as the underlying package isn't being maintained. Working alternatives are
|
||||
libinput and synaptics.
|
||||
(mkRemovedOptionModule [ "services" "osquery" ] "The osquery module has been removed")
|
||||
(mkRemovedOptionModule [ "services" "prey" ] ''
|
||||
prey-bash-client is deprecated upstream
|
||||
'')
|
||||
(mkRemovedOptionModule [ "services" "quagga" ] "the corresponding package has been removed from nixpkgs")
|
||||
(mkRemovedOptionModule [ "services" "seeks" ] "")
|
||||
(mkRemovedOptionModule [ "services" "venus" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "wakeonlan"] "This module was removed in favor of enabling it with networking.interfaces.<name>.wakeOnLan")
|
||||
(mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "xserver" "displayManager" "auto" ] ''
|
||||
The services.xserver.displayManager.auto module has been removed
|
||||
because it was only intended for use in internal NixOS tests, and gave the
|
||||
@@ -53,38 +74,13 @@ with lib;
|
||||
LightDM. Please use the services.xserver.displayManager.autoLogin options
|
||||
instead, or any other display manager in NixOS as they all support auto-login.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "services" "dnscrypt-proxy" ] "Use services.dnscrypt-proxy2 instead")
|
||||
(mkRemovedOptionModule [ "services" "meguca" ] "Use meguca has been removed from nixpkgs")
|
||||
(mkRemovedOptionModule ["hardware" "brightnessctl" ] ''
|
||||
The brightnessctl module was removed because newer versions of
|
||||
brightnessctl don't require the udev rules anymore (they can use the
|
||||
systemd-logind API). Instead of using the module you can now
|
||||
simply add the brightnessctl package to environment.systemPackages.
|
||||
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
|
||||
services.xserver.multitouch (which uses xf86_input_mtrack) has been removed
|
||||
as the underlying package isn't being maintained. Working alternatives are
|
||||
libinput and synaptics.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "virtualisation" "rkt" ] "The rkt module has been removed, it was archived by upstream")
|
||||
|
||||
(mkRemovedOptionModule ["services" "prey" ] ''
|
||||
prey-bash-client is deprecated upstream
|
||||
'')
|
||||
|
||||
(mkRemovedOptionModule ["hardware" "u2f" ] ''
|
||||
The U2F modules module was removed, as all it did was adding the
|
||||
udev rules from libu2f-host to the system. Udev gained native support
|
||||
to handle FIDO security tokens, so this isn't necessary anymore.
|
||||
'')
|
||||
|
||||
(mkRemovedOptionModule [ "services" "seeks" ] "")
|
||||
(mkRemovedOptionModule [ "services" "venus" ] "The corresponding package was removed from nixpkgs.")
|
||||
(mkRemovedOptionModule [ "services" "flashpolicyd" ] "The flashpolicyd module has been removed. Adobe Flash Player is deprecated.")
|
||||
|
||||
(mkRemovedOptionModule [ "security" "hideProcessInformation" ] ''
|
||||
The hidepid module was removed, since the underlying machinery
|
||||
is broken when using cgroups-v2.
|
||||
'')
|
||||
(mkRemovedOptionModule ["services" "wakeonlan"] "This module was removed in favor of enabling it with networking.interfaces.<name>.wakeOnLan")
|
||||
|
||||
(mkRemovedOptionModule [ "services" "kippo" ] "The corresponding package was removed from nixpkgs.")
|
||||
|
||||
# Do NOT add any option renames here, see top of the file
|
||||
];
|
||||
}
|
||||
|
||||
@@ -916,6 +916,6 @@ in {
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.acme.members;
|
||||
doc = ./acme.xml;
|
||||
doc = ./doc.xml;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{ cert, group, groups, user }: {
|
||||
assertion = cert.group == group || builtins.any (u: u == user) groups.${cert.group}.members;
|
||||
message = "Group for certificate ${cert.domain} must be ${group}, or user ${user} must be a member of group ${cert.group}";
|
||||
}
|
||||
@@ -1072,8 +1072,8 @@ in
|
||||
security.apparmor.includes."abstractions/pam" = let
|
||||
isEnabled = test: fold or false (map test (attrValues config.security.pam.services));
|
||||
in
|
||||
lib.concatMapStringsSep "\n"
|
||||
(name: "r ${config.environment.etc."pam.d/${name}".source},")
|
||||
lib.concatMapStrings
|
||||
(name: "r ${config.environment.etc."pam.d/${name}".source},\n")
|
||||
(attrNames config.security.pam.services) +
|
||||
''
|
||||
mr ${getLib pkgs.pam}/lib/security/pam_filter/*,
|
||||
|
||||
@@ -209,62 +209,42 @@ in {
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# install mpd units
|
||||
systemd.packages = [ pkgs.mpd ];
|
||||
|
||||
systemd.sockets.mpd = mkIf cfg.startWhenNeeded {
|
||||
description = "Music Player Daemon Socket";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
listenStreams = [
|
||||
(if pkgs.lib.hasPrefix "/" cfg.network.listenAddress
|
||||
then cfg.network.listenAddress
|
||||
else "${optionalString (cfg.network.listenAddress != "any") "${cfg.network.listenAddress}:"}${toString cfg.network.port}")
|
||||
];
|
||||
socketConfig = {
|
||||
Backlog = 5;
|
||||
KeepAlive = true;
|
||||
PassCredentials = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mpd = {
|
||||
after = [ "network.target" "sound.target" ];
|
||||
description = "Music Player Daemon";
|
||||
wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
|
||||
|
||||
serviceConfig = mkMerge [
|
||||
preStart =
|
||||
''
|
||||
set -euo pipefail
|
||||
install -m 600 ${mpdConf} /run/mpd/mpd.conf
|
||||
'' + optionalString (cfg.credentials != [])
|
||||
(concatStringsSep "\n"
|
||||
(imap0
|
||||
(i: c: ''${pkgs.replace-secret}/bin/replace-secret '{{password-${toString i}}}' '${c.passwordFile}' /run/mpd/mpd.conf'')
|
||||
cfg.credentials));
|
||||
|
||||
serviceConfig =
|
||||
{
|
||||
User = "${cfg.user}";
|
||||
ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /run/mpd/mpd.conf";
|
||||
ExecStartPre = pkgs.writeShellScript "mpd-start-pre" (''
|
||||
set -euo pipefail
|
||||
install -m 600 ${mpdConf} /run/mpd/mpd.conf
|
||||
'' + optionalString (cfg.credentials != [])
|
||||
(concatStringsSep "\n"
|
||||
(imap0
|
||||
(i: c: ''${pkgs.replace-secret}/bin/replace-secret '{{password-${toString i}}}' '${c.passwordFile}' /run/mpd/mpd.conf'')
|
||||
cfg.credentials))
|
||||
);
|
||||
# Note: the first "" overrides the ExecStart from the upstream unit
|
||||
ExecStart = [ "" "${pkgs.mpd}/bin/mpd --systemd /run/mpd/mpd.conf" ];
|
||||
RuntimeDirectory = "mpd";
|
||||
Type = "notify";
|
||||
LimitRTPRIO = 50;
|
||||
LimitRTTIME = "infinity";
|
||||
ProtectSystem = true;
|
||||
NoNewPrivileges = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelModules = true;
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK";
|
||||
RestrictNamespaces = true;
|
||||
Restart = "always";
|
||||
}
|
||||
(mkIf (cfg.dataDir == "/var/lib/${name}") {
|
||||
StateDirectory = [ name ];
|
||||
})
|
||||
(mkIf (cfg.playlistDirectory == "/var/lib/${name}/playlists") {
|
||||
StateDirectory = [ name "${name}/playlists" ];
|
||||
})
|
||||
(mkIf (cfg.musicDirectory == "/var/lib/${name}/music") {
|
||||
StateDirectory = [ name "${name}/music" ];
|
||||
})
|
||||
];
|
||||
StateDirectory = []
|
||||
++ optionals (cfg.dataDir == "/var/lib/${name}") [ name ]
|
||||
++ optionals (cfg.playlistDirectory == "/var/lib/${name}/playlists") [ name "${name}/playlists" ]
|
||||
++ optionals (cfg.musicDirectory == "/var/lib/${name}/music") [ name "${name}/music" ];
|
||||
};
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (cfg.user == name) {
|
||||
|
||||
@@ -30,7 +30,7 @@ let
|
||||
}
|
||||
trap 'on_exit' INT TERM QUIT EXIT
|
||||
|
||||
archiveName="${cfg.archiveBaseName}-$(date ${cfg.dateFormat})"
|
||||
archiveName="${if cfg.archiveBaseName == null then "" else cfg.archiveBaseName + "-"}$(date ${cfg.dateFormat})"
|
||||
archiveSuffix="${optionalString cfg.appendFailedSuffix ".failed"}"
|
||||
${cfg.preHook}
|
||||
'' + optionalString cfg.doInit ''
|
||||
@@ -60,7 +60,7 @@ let
|
||||
'' + optionalString (cfg.prune.keep != { }) ''
|
||||
borg prune $extraArgs \
|
||||
${mkKeepArgs cfg} \
|
||||
--prefix ${escapeShellArg cfg.prune.prefix} \
|
||||
${optionalString (cfg.prune.prefix != null) "--prefix ${escapeShellArg cfg.prune.prefix} \\"}
|
||||
$extraPruneArgs
|
||||
${cfg.postPrune}
|
||||
'';
|
||||
@@ -99,7 +99,18 @@ let
|
||||
BORG_REPO = cfg.repo;
|
||||
inherit (cfg) extraArgs extraInitArgs extraCreateArgs extraPruneArgs;
|
||||
} // (mkPassEnv cfg) // cfg.environment;
|
||||
inherit (cfg) startAt;
|
||||
};
|
||||
|
||||
mkBackupTimers = name: cfg:
|
||||
nameValuePair "borgbackup-job-${name}" {
|
||||
description = "BorgBackup job ${name} timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
Persistent = cfg.persistentTimer;
|
||||
OnCalendar = cfg.startAt;
|
||||
};
|
||||
# if remote-backup wait for network
|
||||
after = optional (cfg.persistentTimer && !isLocalPath cfg.repo) "network-online.target";
|
||||
};
|
||||
|
||||
# utility function around makeWrapper
|
||||
@@ -284,7 +295,7 @@ in {
|
||||
};
|
||||
|
||||
archiveBaseName = mkOption {
|
||||
type = types.strMatching "[^/{}]+";
|
||||
type = types.nullOr (types.strMatching "[^/{}]+");
|
||||
default = "${globalConfig.networking.hostName}-${name}";
|
||||
defaultText = literalExpression ''"''${config.networking.hostName}-<name>"'';
|
||||
description = ''
|
||||
@@ -292,6 +303,7 @@ in {
|
||||
determined by <option>dateFormat</option>, will be appended. The full
|
||||
name can be modified at runtime (<literal>$archiveName</literal>).
|
||||
Placeholders like <literal>{hostname}</literal> must not be used.
|
||||
Use <literal>null</literal> for no base name.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -320,6 +332,19 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
persistentTimer = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Set the <literal>persistentTimer</literal> option for the
|
||||
<citerefentry><refentrytitle>systemd.timer</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry>
|
||||
which triggers the backup immediately if the last trigger
|
||||
was missed (e.g. if the system was powered down).
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
@@ -471,11 +496,11 @@ in {
|
||||
};
|
||||
|
||||
prune.prefix = mkOption {
|
||||
type = types.str;
|
||||
type = types.nullOr (types.str);
|
||||
description = ''
|
||||
Only consider archive names starting with this prefix for pruning.
|
||||
By default, only archives created by this job are considered.
|
||||
Use <literal>""</literal> to consider all archives.
|
||||
Use <literal>""</literal> or <literal>null</literal> to consider all archives.
|
||||
'';
|
||||
default = config.archiveBaseName;
|
||||
defaultText = literalExpression "archiveBaseName";
|
||||
@@ -694,6 +719,10 @@ in {
|
||||
# A repo named "foo" is mapped to systemd.services.borgbackup-repo-foo
|
||||
// mapAttrs' mkRepoService repos;
|
||||
|
||||
# A job named "foo" is mapped to systemd.timers.borgbackup-job-foo
|
||||
# only generate the timer if interval (startAt) is set
|
||||
systemd.timers = mapAttrs' mkBackupTimers (filterAttrs (_: cfg: cfg.startAt != []) jobs);
|
||||
|
||||
users = mkMerge (mapAttrsToList mkUsersConfig repos);
|
||||
|
||||
environment.systemPackages = with pkgs; [ borgbackup ] ++ (mapAttrsToList mkBorgWrapper jobs);
|
||||
|
||||
@@ -5,7 +5,7 @@ let
|
||||
inherit (lib.attrsets) hasAttr;
|
||||
inherit (lib.modules) mkDefault mkIf;
|
||||
inherit (lib.options) mkEnableOption mkOption;
|
||||
inherit (lib.types) nullOr strMatching;
|
||||
inherit (lib.types) nonEmptyStr nullOr;
|
||||
|
||||
options.services.tsmBackup = {
|
||||
enable = mkEnableOption ''
|
||||
@@ -15,7 +15,7 @@ let
|
||||
<option>programs.tsmClient.enable</option>
|
||||
'';
|
||||
command = mkOption {
|
||||
type = strMatching ".+";
|
||||
type = nonEmptyStr;
|
||||
default = "backup";
|
||||
example = "incr";
|
||||
description = ''
|
||||
@@ -24,7 +24,7 @@ let
|
||||
'';
|
||||
};
|
||||
servername = mkOption {
|
||||
type = strMatching ".+";
|
||||
type = nonEmptyStr;
|
||||
example = "mainTsmServer";
|
||||
description = ''
|
||||
Create a systemd system service
|
||||
@@ -41,7 +41,7 @@ let
|
||||
'';
|
||||
};
|
||||
autoTime = mkOption {
|
||||
type = nullOr (strMatching ".+");
|
||||
type = nullOr nonEmptyStr;
|
||||
default = null;
|
||||
example = "12:00";
|
||||
description = ''
|
||||
@@ -87,16 +87,35 @@ in
|
||||
environment.DSM_LOG = "/var/log/tsm-backup/";
|
||||
# TSM needs a HOME dir to store certificates.
|
||||
environment.HOME = "/var/lib/tsm-backup";
|
||||
# for exit status description see
|
||||
# https://www.ibm.com/support/knowledgecenter/en/SSEQVQ_8.1.8/client/c_sched_rtncode.html
|
||||
serviceConfig.SuccessExitStatus = "4 8";
|
||||
# The `-se` option must come after the command.
|
||||
# The `-optfile` option suppresses a `dsm.opt`-not-found warning.
|
||||
serviceConfig.ExecStart =
|
||||
"${cfgPrg.wrappedPackage}/bin/dsmc ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null";
|
||||
serviceConfig.LogsDirectory = "tsm-backup";
|
||||
serviceConfig.StateDirectory = "tsm-backup";
|
||||
serviceConfig.StateDirectoryMode = "0750";
|
||||
serviceConfig = {
|
||||
# for exit status description see
|
||||
# https://www.ibm.com/docs/en/spectrum-protect/8.1.13?topic=clients-client-return-codes
|
||||
SuccessExitStatus = "4 8";
|
||||
# The `-se` option must come after the command.
|
||||
# The `-optfile` option suppresses a `dsm.opt`-not-found warning.
|
||||
ExecStart =
|
||||
"${cfgPrg.wrappedPackage}/bin/dsmc ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null";
|
||||
LogsDirectory = "tsm-backup";
|
||||
StateDirectory = "tsm-backup";
|
||||
StateDirectoryMode = "0750";
|
||||
# systemd sandboxing
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
#PrivateTmp = true; # would break backup of {/var,}/tmp
|
||||
#PrivateUsers = true; # would block backup of /home/*
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = "read-only";
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "noaccess";
|
||||
ProtectSystem = "strict";
|
||||
RestrictNamespaces = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
startAt = mkIf (cfg.autoTime!=null) cfg.autoTime;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -167,4 +167,5 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -363,4 +363,6 @@ in {
|
||||
|
||||
services.kubernetes.kubelet.clusterDns = mkDefault cfg.clusterIp;
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -496,4 +496,5 @@ in
|
||||
|
||||
];
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.controllerManager;
|
||||
klib = options.services.kubernetes.lib.default;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@@ -57,7 +56,7 @@ in
|
||||
type = int;
|
||||
};
|
||||
|
||||
kubeconfig = klib.mkKubeConfigOptions "Kubernetes controller manager";
|
||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes controller manager";
|
||||
|
||||
leaderElect = mkOption {
|
||||
description = "Whether to start leader election before executing main loop.";
|
||||
@@ -130,7 +129,7 @@ in
|
||||
"--cluster-cidr=${cfg.clusterCidr}"} \
|
||||
${optionalString (cfg.featureGates != [])
|
||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||
--kubeconfig=${klib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig} \
|
||||
--kubeconfig=${top.lib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig} \
|
||||
--leader-elect=${boolToString cfg.leaderElect} \
|
||||
${optionalString (cfg.rootCaFile!=null)
|
||||
"--root-ca-file=${cfg.rootCaFile}"} \
|
||||
@@ -157,7 +156,7 @@ in
|
||||
path = top.path;
|
||||
};
|
||||
|
||||
services.kubernetes.pki.certs = with klib; {
|
||||
services.kubernetes.pki.certs = with top.lib; {
|
||||
controllerManager = mkCert {
|
||||
name = "kube-controller-manager";
|
||||
CN = "kube-controller-manager";
|
||||
@@ -172,4 +171,6 @@ in
|
||||
|
||||
services.kubernetes.controllerManager.kubeconfig.server = mkDefault top.apiserverAddress;
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,7 @@ let
|
||||
|
||||
containerd.runtimes.runc = {
|
||||
runtime_type = "io.containerd.runc.v2";
|
||||
};
|
||||
|
||||
containerd.runtimes."io.containerd.runc.v2".options = {
|
||||
SystemdCgroup = true;
|
||||
options.SystemdCgroup = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -193,8 +190,6 @@ in {
|
||||
inherit mkKubeConfigOptions;
|
||||
};
|
||||
type = types.attrs;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
secretsPath = mkOption {
|
||||
@@ -315,4 +310,6 @@ in {
|
||||
else "${cfg.masterAddress}:${toString cfg.apiserver.securePort}"}");
|
||||
})
|
||||
];
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -95,4 +95,6 @@ in
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.kubelet;
|
||||
klib = options.services.kubernetes.lib.default;
|
||||
|
||||
cniConfig =
|
||||
if cfg.cni.config != [] && cfg.cni.configDir != null then
|
||||
@@ -28,7 +27,7 @@ let
|
||||
config.Cmd = ["/bin/pause"];
|
||||
};
|
||||
|
||||
kubeconfig = klib.mkKubeConfig "kubelet" cfg.kubeconfig;
|
||||
kubeconfig = top.lib.mkKubeConfig "kubelet" cfg.kubeconfig;
|
||||
|
||||
manifestPath = "kubernetes/manifests";
|
||||
|
||||
@@ -178,7 +177,7 @@ in
|
||||
type = str;
|
||||
};
|
||||
|
||||
kubeconfig = klib.mkKubeConfigOptions "Kubelet";
|
||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubelet";
|
||||
|
||||
manifests = mkOption {
|
||||
description = "List of manifests to bootstrap with kubelet (only pods can be created as manifest entry)";
|
||||
@@ -265,8 +264,6 @@ in
|
||||
"net.bridge.bridge-nf-call-ip6tables" = 1;
|
||||
};
|
||||
|
||||
systemd.enableUnifiedCgroupHierarchy = false; # true breaks node memory metrics
|
||||
|
||||
systemd.services.kubelet = {
|
||||
description = "Kubernetes Kubelet Service";
|
||||
wantedBy = [ "kubernetes.target" ];
|
||||
@@ -359,7 +356,7 @@ in
|
||||
services.kubernetes.kubelet.hostname = with config.networking;
|
||||
mkDefault (hostName + optionalString (domain != null) ".${domain}");
|
||||
|
||||
services.kubernetes.pki.certs = with klib; {
|
||||
services.kubernetes.pki.certs = with top.lib; {
|
||||
kubelet = mkCert {
|
||||
name = "kubelet";
|
||||
CN = top.kubelet.hostname;
|
||||
@@ -396,4 +393,6 @@ in
|
||||
})
|
||||
|
||||
];
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
cfg = top.pki;
|
||||
klib = options.services.kubernetes.lib;
|
||||
|
||||
csrCA = pkgs.writeText "kube-pki-cacert-csr.json" (builtins.toJSON {
|
||||
key = {
|
||||
@@ -30,7 +29,7 @@ let
|
||||
cfsslAPITokenLength = 32;
|
||||
|
||||
clusterAdminKubeconfig = with cfg.certs.clusterAdmin;
|
||||
klib.mkKubeConfig "cluster-admin" {
|
||||
top.lib.mkKubeConfig "cluster-admin" {
|
||||
server = top.apiserverAddress;
|
||||
certFile = cert;
|
||||
keyFile = key;
|
||||
@@ -251,7 +250,7 @@ in
|
||||
# - it would be better with a more Nix-oriented way of managing addons
|
||||
systemd.services.kube-addon-manager = mkIf top.addonManager.enable (mkMerge [{
|
||||
environment.KUBECONFIG = with cfg.certs.addonManager;
|
||||
klib.mkKubeConfig "addon-manager" {
|
||||
top.lib.mkKubeConfig "addon-manager" {
|
||||
server = top.apiserverAddress;
|
||||
certFile = cert;
|
||||
keyFile = key;
|
||||
@@ -344,7 +343,7 @@ in
|
||||
'';
|
||||
|
||||
services.flannel = with cfg.certs.flannelClient; {
|
||||
kubeconfig = klib.mkKubeConfig "flannel" {
|
||||
kubeconfig = top.lib.mkKubeConfig "flannel" {
|
||||
server = top.apiserverAddress;
|
||||
certFile = cert;
|
||||
keyFile = key;
|
||||
@@ -402,4 +401,6 @@ in
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.proxy;
|
||||
klib = options.services.kubernetes.lib.default;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@@ -44,7 +43,7 @@ in
|
||||
type = str;
|
||||
};
|
||||
|
||||
kubeconfig = klib.mkKubeConfigOptions "Kubernetes proxy";
|
||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes proxy";
|
||||
|
||||
verbosity = mkOption {
|
||||
description = ''
|
||||
@@ -73,7 +72,7 @@ in
|
||||
${optionalString (cfg.featureGates != [])
|
||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||
--hostname-override=${cfg.hostname} \
|
||||
--kubeconfig=${klib.mkKubeConfig "kube-proxy" cfg.kubeconfig} \
|
||||
--kubeconfig=${top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig} \
|
||||
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
||||
${cfg.extraOpts}
|
||||
'';
|
||||
@@ -89,7 +88,7 @@ in
|
||||
services.kubernetes.proxy.hostname = with config.networking; mkDefault hostName;
|
||||
|
||||
services.kubernetes.pki.certs = {
|
||||
kubeProxyClient = klib.mkCert {
|
||||
kubeProxyClient = top.lib.mkCert {
|
||||
name = "kube-proxy-client";
|
||||
CN = "system:kube-proxy";
|
||||
action = "systemctl restart kube-proxy.service";
|
||||
@@ -98,4 +97,6 @@ in
|
||||
|
||||
services.kubernetes.proxy.kubeconfig.server = mkDefault top.apiserverAddress;
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.scheduler;
|
||||
klib = options.services.kubernetes.lib.default;
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
@@ -33,7 +32,7 @@ in
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
kubeconfig = klib.mkKubeConfigOptions "Kubernetes scheduler";
|
||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes scheduler";
|
||||
|
||||
leaderElect = mkOption {
|
||||
description = "Whether to start leader election before executing main loop.";
|
||||
@@ -70,7 +69,7 @@ in
|
||||
--address=${cfg.address} \
|
||||
${optionalString (cfg.featureGates != [])
|
||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||
--kubeconfig=${klib.mkKubeConfig "kube-scheduler" cfg.kubeconfig} \
|
||||
--kubeconfig=${top.lib.mkKubeConfig "kube-scheduler" cfg.kubeconfig} \
|
||||
--leader-elect=${boolToString cfg.leaderElect} \
|
||||
--port=${toString cfg.port} \
|
||||
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
||||
@@ -88,7 +87,7 @@ in
|
||||
};
|
||||
|
||||
services.kubernetes.pki.certs = {
|
||||
schedulerClient = klib.mkCert {
|
||||
schedulerClient = top.lib.mkCert {
|
||||
name = "kube-scheduler-client";
|
||||
CN = "system:kube-scheduler";
|
||||
action = "systemctl restart kube-scheduler.service";
|
||||
@@ -97,4 +96,6 @@ in
|
||||
|
||||
services.kubernetes.scheduler.kubeconfig.server = mkDefault top.apiserverAddress;
|
||||
};
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,12 @@ in {
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 6379;
|
||||
description = "The port for Redis to listen to.";
|
||||
default = if name == "" then 6379 else 0;
|
||||
defaultText = literalExpression ''if name == "" then 6379 else 0'';
|
||||
description = ''
|
||||
The TCP port to accept connections.
|
||||
If port 0 is specified Redis will not listen on a TCP socket.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
@@ -102,7 +106,7 @@ in {
|
||||
bind = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = if name == "" then "127.0.0.1" else null;
|
||||
defaultText = "127.0.0.1 or null if name != \"\"";
|
||||
defaultText = literalExpression ''if name == "" then "127.0.0.1" else null'';
|
||||
description = ''
|
||||
The IP interface to bind to.
|
||||
<literal>null</literal> means "all interfaces".
|
||||
@@ -253,7 +257,7 @@ in {
|
||||
};
|
||||
config.settings = mkMerge [
|
||||
{
|
||||
port = if config.bind == null then 0 else config.port;
|
||||
port = config.port;
|
||||
daemonize = false;
|
||||
supervised = "systemd";
|
||||
loglevel = config.logLevel;
|
||||
|
||||
@@ -57,26 +57,12 @@ in
|
||||
pkgs.gnome.gnome-settings-daemon
|
||||
];
|
||||
|
||||
systemd.user.targets."gnome-session-initialized".wants = [
|
||||
"gsd-color.target"
|
||||
"gsd-datetime.target"
|
||||
"gsd-keyboard.target"
|
||||
"gsd-media-keys.target"
|
||||
"gsd-print-notifications.target"
|
||||
"gsd-rfkill.target"
|
||||
"gsd-screensaver-proxy.target"
|
||||
"gsd-sharing.target"
|
||||
"gsd-smartcard.target"
|
||||
"gsd-sound.target"
|
||||
"gsd-wacom.target"
|
||||
"gsd-wwan.target"
|
||||
"gsd-a11y-settings.target"
|
||||
"gsd-housekeeping.target"
|
||||
"gsd-power.target"
|
||||
systemd.user.targets."gnome-session-x11-services".wants = [
|
||||
"org.gnome.SettingsDaemon.XSettings.service"
|
||||
];
|
||||
|
||||
systemd.user.targets."gnome-session-x11-services".wants = [
|
||||
"gsd-xsettings.target"
|
||||
systemd.user.targets."gnome-session-x11-services-ready".wants = [
|
||||
"org.gnome.SettingsDaemon.XSettings.service"
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
@@ -47,6 +47,8 @@ with lib;
|
||||
|
||||
systemd.packages = [ pkgs.tracker-miners ];
|
||||
|
||||
services.gnome.tracker.subcommandPackages = [ pkgs.tracker-miners ];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.gnome.tracker;
|
||||
in
|
||||
{
|
||||
|
||||
meta = {
|
||||
@@ -33,6 +36,15 @@ with lib;
|
||||
'';
|
||||
};
|
||||
|
||||
subcommandPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
description = ''
|
||||
List of packages containing tracker3 subcommands.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
@@ -40,7 +52,7 @@ with lib;
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.gnome.tracker.enable {
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.tracker ];
|
||||
|
||||
@@ -48,6 +60,17 @@ with lib;
|
||||
|
||||
systemd.packages = [ pkgs.tracker ];
|
||||
|
||||
environment.variables = {
|
||||
TRACKER_CLI_SUBCOMMANDS_DIR =
|
||||
let
|
||||
subcommandPackagesTree = pkgs.symlinkJoin {
|
||||
name = "tracker-with-subcommands-${pkgs.tracker.version}";
|
||||
paths = [ pkgs.tracker ] ++ cfg.subcommandPackages;
|
||||
};
|
||||
in
|
||||
"${subcommandPackagesTree}/libexec/tracker3";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.pipewire.wireplumber;
|
||||
in
|
||||
{
|
||||
meta.maintainers = [ lib.maintainers.k900 ];
|
||||
|
||||
options = {
|
||||
services.pipewire.wireplumber = {
|
||||
enable = lib.mkEnableOption "A modular session / policy manager for PipeWire";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.wireplumber;
|
||||
defaultText = lib.literalExpression "pkgs.wireplumber";
|
||||
description = ''
|
||||
The wireplumber derivation to use.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !config.services.pipewire.media-session.enable;
|
||||
message = "WirePlumber and pipewire-media-session can't be enabled at the same time.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
systemd.packages = [ cfg.package ];
|
||||
|
||||
systemd.services.wireplumber.enable = config.services.pipewire.systemWide;
|
||||
systemd.user.services.wireplumber.enable = !config.services.pipewire.systemWide;
|
||||
|
||||
systemd.services.wireplumber.wantedBy = [ "pipewire.service" ];
|
||||
systemd.user.services.wireplumber.wantedBy = [ "pipewire.service" ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.rstudio-server;
|
||||
|
||||
rserver-conf = builtins.toFile "rserver.conf" ''
|
||||
server-working-dir=${cfg.serverWorkingDir}
|
||||
www-address=${cfg.listenAddr}
|
||||
${cfg.rserverExtraConfig}
|
||||
'';
|
||||
|
||||
rsession-conf = builtins.toFile "rsession.conf" ''
|
||||
${cfg.rsessionExtraConfig}
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
meta.maintainers = with maintainers; [ jbedo cfhammill ];
|
||||
|
||||
options.services.rstudio-server = {
|
||||
enable = mkEnableOption "RStudio server";
|
||||
|
||||
serverWorkingDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/rstudio-server";
|
||||
description = ''
|
||||
Default working directory for server (server-working-dir in rserver.conf).
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddr = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = ''
|
||||
Address to listen on (www-address in rserver.conf).
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.rstudio-server;
|
||||
defaultText = literalExpression "pkgs.rstudio-server";
|
||||
example = literalExpression "pkgs.rstudioServerWrapper.override { packages = [ pkgs.rPackages.ggplot2 ]; }";
|
||||
description = ''
|
||||
Rstudio server package to use. Can be set to rstudioServerWrapper to provide packages.
|
||||
'';
|
||||
};
|
||||
|
||||
rserverExtraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra contents for rserver.conf.
|
||||
'';
|
||||
};
|
||||
|
||||
rsessionExtraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra contents for resssion.conf.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable
|
||||
{
|
||||
systemd.services.rstudio-server = {
|
||||
description = "Rstudio server";
|
||||
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = [ rserver-conf rsession-conf ];
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
Type = "forking";
|
||||
ExecStart = "${cfg.package}/bin/rserver";
|
||||
StateDirectory = "rstudio-server";
|
||||
RuntimeDirectory = "rstudio-server";
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
"rstudio/rserver.conf".source = rserver-conf;
|
||||
"rstudio/rsession.conf".source = rsession-conf;
|
||||
"pam.d/rstudio".source = "/etc/pam.d/login";
|
||||
};
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users = {
|
||||
users.rstudio-server = {
|
||||
uid = config.ids.uids.rstudio-server;
|
||||
description = "rstudio-server";
|
||||
group = "rstudio-server";
|
||||
};
|
||||
groups.rstudio-server = {
|
||||
gid = config.ids.gids.rstudio-server;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.archisteamfarm;
|
||||
|
||||
format = pkgs.formats.json { };
|
||||
|
||||
asf-config = format.generate "ASF.json" (cfg.settings // {
|
||||
# we disable it because ASF cannot update itself anyways
|
||||
# and nixos takes care of restarting the service
|
||||
# is in theory not needed as this is already the default for default builds
|
||||
UpdateChannel = 0;
|
||||
Headless = true;
|
||||
});
|
||||
|
||||
ipc-config = format.generate "IPC.config" cfg.ipcSettings;
|
||||
|
||||
mkBot = n: c:
|
||||
format.generate "${n}.json" (c.settings // {
|
||||
SteamLogin = if c.username == "" then n else c.username;
|
||||
SteamPassword = c.passwordFile;
|
||||
# sets the password format to file (https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Security#file)
|
||||
PasswordFormat = 4;
|
||||
Enabled = c.enabled;
|
||||
});
|
||||
in
|
||||
{
|
||||
options.services.archisteamfarm = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
If enabled, starts the ArchisSteamFarm service.
|
||||
For configuring the SteamGuard token you will need to use the web-ui, which is enabled by default over on 127.0.0.1:1242.
|
||||
You cannot configure ASF in any way outside of nix, since all the config files get wiped on restart and replaced with the programatically set ones by nix.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
|
||||
web-ui = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enable = mkEnableOption
|
||||
"Wheter to start the web-ui. This is the preferred way of configuring things such as the steam guard token";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.ArchiSteamFarm.ui;
|
||||
description =
|
||||
"Web-UI package to use. Contents must be in lib/dist.";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {
|
||||
enable = true;
|
||||
package = pkgs.ArchiSteamFarm.ui;
|
||||
};
|
||||
example = {
|
||||
enable = false;
|
||||
};
|
||||
description = "The Web-UI hosted on 127.0.0.1:1242.";
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.ArchiSteamFarm;
|
||||
description =
|
||||
"Package to use. Should always be the latest version, for security reasons, since this module uses very new features and to not get out of sync with the Steam API.";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/asf";
|
||||
description = ''
|
||||
The ASF home directory used to store all data.
|
||||
If left as the default value this directory will automatically be created before the ASF server starts, otherwise the sysadmin is responsible for ensuring the directory exists with appropriate ownership and permissions.'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = format.type;
|
||||
description = ''
|
||||
The ASF.json file, all the options are documented <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#global-config">here</link>.
|
||||
Do note that `AutoRestart` and `UpdateChannel` is always to `false`
|
||||
respectively `0` because NixOS takes care of updating everything.
|
||||
`Headless` is also always set to `true` because there is no way to provide inputs via a systemd service.
|
||||
You should try to keep ASF up to date since upstream does not provide support for anything but the latest version and you're exposing yourself to all kinds of issues - as is outlined <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#updateperiod">here</link>.
|
||||
'';
|
||||
example = {
|
||||
Statistics = false;
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
|
||||
ipcSettings = mkOption {
|
||||
type = format.type;
|
||||
description = ''
|
||||
Settings to write to IPC.config.
|
||||
All options can be found <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/IPC#custom-configuration">here</link>.
|
||||
'';
|
||||
example = {
|
||||
Kestrel = {
|
||||
Endpoints = {
|
||||
HTTP = {
|
||||
Url = "http://*:1242";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
|
||||
bots = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
username = mkOption {
|
||||
type = types.str;
|
||||
description =
|
||||
"Name of the user to log in. Default is attribute name.";
|
||||
default = "";
|
||||
};
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description =
|
||||
"Path to a file containig the password. The file must be readable by the <literal>asf</literal> user/group.";
|
||||
};
|
||||
enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to enable the bot on startup.";
|
||||
};
|
||||
settings = mkOption {
|
||||
type = types.attrs;
|
||||
description =
|
||||
"Additional settings that are documented <link xlink:href=\"https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config\">here</link>.";
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
});
|
||||
description = ''
|
||||
Bots name and configuration.
|
||||
'';
|
||||
example = {
|
||||
exampleBot = {
|
||||
username = "alice";
|
||||
passwordFile = "/var/lib/asf/secrets/password";
|
||||
settings = { SteamParentalCode = "1234"; };
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
users = {
|
||||
users.asf = {
|
||||
home = cfg.dataDir;
|
||||
isSystemUser = true;
|
||||
group = "asf";
|
||||
description = "Archis-Steam-Farm service user";
|
||||
};
|
||||
groups.asf = { };
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
asf = {
|
||||
description = "Archis-Steam-Farm Service";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = mkMerge [
|
||||
(mkIf (cfg.dataDir == "/var/lib/asf") { StateDirectory = "asf"; })
|
||||
{
|
||||
User = "asf";
|
||||
Group = "asf";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
Type = "simple";
|
||||
ExecStart =
|
||||
"${cfg.package}/bin/ArchiSteamFarm --path ${cfg.dataDir} --process-required --no-restart --service --no-config-migrate";
|
||||
|
||||
# mostly copied from the default systemd service
|
||||
PrivateTmp = true;
|
||||
LockPersonality = true;
|
||||
PrivateDevices = true;
|
||||
PrivateIPC = true;
|
||||
PrivateMounts = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "full";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
}
|
||||
];
|
||||
|
||||
preStart = ''
|
||||
mkdir -p config
|
||||
rm -f www
|
||||
rm -f config/{*.json,*.config}
|
||||
|
||||
ln -s ${asf-config} config/ASF.json
|
||||
|
||||
${strings.optionalString (cfg.ipcSettings != {}) ''
|
||||
ln -s ${ipc-config} config/IPC.config
|
||||
''}
|
||||
|
||||
ln -s ${pkgs.runCommandLocal "ASF-bots" {} ''
|
||||
mkdir -p $out/lib/asf/bots
|
||||
for i in ${strings.concatStringsSep " " (lists.map (x: "${getName x},${x}") (attrsets.mapAttrsToList mkBot cfg.bots))}; do IFS=",";
|
||||
set -- $i
|
||||
ln -s $2 $out/lib/asf/bots/$1
|
||||
done
|
||||
''}/lib/asf/bots/* config/
|
||||
|
||||
${strings.optionalString cfg.web-ui.enable ''
|
||||
ln -s ${cfg.web-ui.package}/lib/dist www
|
||||
''}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
buildDocsInSandbox = false;
|
||||
maintainers = with maintainers; [ lom ];
|
||||
};
|
||||
}
|
||||
@@ -4,7 +4,8 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.thermald;
|
||||
in {
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
options = {
|
||||
services.thermald = {
|
||||
@@ -41,6 +42,7 @@ in {
|
||||
description = "Thermal Daemon Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
PrivateNetwork = true;
|
||||
ExecStart = ''
|
||||
${cfg.package}/sbin/thermald \
|
||||
--no-daemon \
|
||||
|
||||
@@ -38,7 +38,7 @@ let
|
||||
ssl_cert = <${cfg.sslServerCert}
|
||||
ssl_key = <${cfg.sslServerKey}
|
||||
${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
|
||||
ssl_dh = <${config.security.dhparams.params.dovecot2.path}
|
||||
${optionalString cfg.enableDHE ''ssl_dh = <${config.security.dhparams.params.dovecot2.path}''}
|
||||
disable_plaintext_auth = yes
|
||||
''
|
||||
)
|
||||
@@ -169,25 +169,13 @@ in
|
||||
];
|
||||
|
||||
options.services.dovecot2 = {
|
||||
enable = mkEnableOption "Dovecot 2.x POP3/IMAP server";
|
||||
enable = mkEnableOption "the dovecot 2.x POP3/IMAP server";
|
||||
|
||||
enablePop3 = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Start the POP3 listener (when Dovecot is enabled).";
|
||||
};
|
||||
enablePop3 = mkEnableOption "starting the POP3 listener (when Dovecot is enabled).";
|
||||
|
||||
enableImap = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Start the IMAP listener (when Dovecot is enabled).";
|
||||
};
|
||||
enableImap = mkEnableOption "starting the IMAP listener (when Dovecot is enabled)." // { default = true; };
|
||||
|
||||
enableLmtp = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Start the LMTP listener (when Dovecot is enabled).";
|
||||
};
|
||||
enableLmtp = mkEnableOption "starting the LMTP listener (when Dovecot is enabled).";
|
||||
|
||||
protocols = mkOption {
|
||||
type = types.listOf types.str;
|
||||
@@ -279,13 +267,9 @@ in
|
||||
description = "Default group to store mail for virtual users.";
|
||||
};
|
||||
|
||||
createMailUser = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''Whether to automatically create the user
|
||||
given in <option>services.dovecot.user</option> and the group
|
||||
given in <option>services.dovecot.group</option>.'';
|
||||
};
|
||||
createMailUser = mkEnableOption ''automatically creating the user
|
||||
given in <option>services.dovecot.user</option> and the group
|
||||
given in <option>services.dovecot.group</option>.'' // { default = true; };
|
||||
|
||||
modules = mkOption {
|
||||
type = types.listOf types.package;
|
||||
@@ -316,11 +300,9 @@ in
|
||||
description = "Path to the server's private key.";
|
||||
};
|
||||
|
||||
enablePAM = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to create a own Dovecot PAM service and configure PAM user logins.";
|
||||
};
|
||||
enablePAM = mkEnableOption "creating a own Dovecot PAM service and configure PAM user logins." // { default = true; };
|
||||
|
||||
enableDHE = mkEnableOption "enable ssl_dh and generation of primes for the key exchange." // { default = true; };
|
||||
|
||||
sieveScripts = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
@@ -328,11 +310,7 @@ in
|
||||
description = "Sieve scripts to be executed. Key is a sequence, e.g. 'before2', 'after' etc.";
|
||||
};
|
||||
|
||||
showPAMFailure = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Show the PAM failure message on authentication error (useful for OTPW).";
|
||||
};
|
||||
showPAMFailure = mkEnableOption "showing the PAM failure message on authentication error (useful for OTPW).";
|
||||
|
||||
mailboxes = mkOption {
|
||||
type = with types; coercedTo
|
||||
@@ -348,12 +326,7 @@ in
|
||||
description = "Configure mailboxes and auto create or subscribe them.";
|
||||
};
|
||||
|
||||
enableQuota = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = "Whether to enable the dovecot quota service.";
|
||||
};
|
||||
enableQuota = mkEnableOption "the dovecot quota service.";
|
||||
|
||||
quotaPort = mkOption {
|
||||
type = types.str;
|
||||
@@ -376,7 +349,7 @@ in
|
||||
config = mkIf cfg.enable {
|
||||
security.pam.services.dovecot2 = mkIf cfg.enablePAM {};
|
||||
|
||||
security.dhparams = mkIf (cfg.sslServerCert != null) {
|
||||
security.dhparams = mkIf (cfg.sslServerCert != null && cfg.enableDHE) {
|
||||
enable = true;
|
||||
params.dovecot2 = {};
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ in
|
||||
} // (if ((lib.getName cfg.package) == (lib.getName pkgs.ananicy-cpp)) then {
|
||||
# https://gitlab.com/ananicy-cpp/ananicy-cpp/-/blob/master/src/config.cpp#L12
|
||||
loglevel = mkOD "warn"; # default is info but its spammy
|
||||
cgroup_realtime_workaround = mkOD true;
|
||||
cgroup_realtime_workaround = mkOD config.systemd.enableUnifiedCgroupHierarchy;
|
||||
} else {
|
||||
# https://github.com/Nefelim4ag/Ananicy/blob/master/ananicy.d/ananicy.conf
|
||||
check_disks_schedulers = mkOD true;
|
||||
|
||||
@@ -21,6 +21,8 @@ let
|
||||
<para>
|
||||
This must be in a format usable by findmnt; that could be a key=value
|
||||
pair, or a bare path to a mount point.
|
||||
Using bare paths will allow systemd to start the beesd service only
|
||||
after mounting the associated path.
|
||||
'';
|
||||
example = "LABEL=MyBulkDataDrive";
|
||||
};
|
||||
@@ -122,6 +124,7 @@ in
|
||||
StartupIOWeight = 25;
|
||||
SyslogIdentifier = "beesd"; # would otherwise be "bees-service-wrapper"
|
||||
};
|
||||
unitConfig.RequiresMountsFor = lib.mkIf (lib.hasPrefix "/" fs.spec) fs.spec;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
})
|
||||
cfg.filesystems;
|
||||
|
||||
@@ -177,6 +177,19 @@ in
|
||||
defaultText = literalExpression ''"''${config.${opt.stateDir}}/dump"'';
|
||||
description = "Path to the dump files.";
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "zip" "rar" "tar" "sz" "tar.gz" "tar.xz" "tar.bz2" "tar.br" "tar.lz4" ];
|
||||
default = "zip";
|
||||
description = "Archive format used to store the dump file.";
|
||||
};
|
||||
|
||||
file = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Filename to be used for the dump. If `null` a default name is choosen by gitea.";
|
||||
example = "gitea-dump";
|
||||
};
|
||||
};
|
||||
|
||||
ssh = {
|
||||
@@ -634,7 +647,7 @@ in
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = cfg.user;
|
||||
ExecStart = "${gitea}/bin/gitea dump";
|
||||
ExecStart = "${gitea}/bin/gitea dump --type ${cfg.dump.type}" + optionalString (cfg.dump.file != null) " --file ${cfg.dump.file}";
|
||||
WorkingDirectory = cfg.dump.backupDir;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ let
|
||||
in
|
||||
{
|
||||
options.services.heisenbridge = {
|
||||
enable = mkEnableOption "the Matrix<->IRC bridge";
|
||||
enable = mkEnableOption "the Matrix to IRC bridge";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
@@ -172,25 +172,39 @@ in
|
||||
++ (map (lib.escapeShellArg) cfg.extraArgs)
|
||||
);
|
||||
|
||||
ProtectHome = true;
|
||||
PrivateDevices = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
StateDirectory = "heisenbridge";
|
||||
StateDirectoryMode = "755";
|
||||
# Hardening options
|
||||
|
||||
User = "heisenbridge";
|
||||
Group = "heisenbridge";
|
||||
RuntimeDirectory = "heisenbridge";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
StateDirectory = "heisenbridge";
|
||||
StateDirectoryMode = "0755";
|
||||
|
||||
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024 || cfg.identd.port < 1024) "CAP_NET_BIND_SERVICE";
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictSUIDSGID = true;
|
||||
PrivateMounts = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
RestrictNamespaces = true;
|
||||
RemoveIPC = true;
|
||||
UMask = "0077";
|
||||
|
||||
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024 || (cfg.identd.enable && cfg.identd.port < 1024)) "CAP_NET_BIND_SERVICE";
|
||||
AmbientCapabilities = CapabilityBoundingSet;
|
||||
NoNewPrivileges = true;
|
||||
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
PrivateMounts = true;
|
||||
SystemCallFilter = "~@aio @clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @raw-io @setuid @swap";
|
||||
SystemCallFilter = ["@system-service" "~@priviledged" "@chown"];
|
||||
SystemCallArchitectures = "native";
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6";
|
||||
};
|
||||
|
||||
@@ -5,6 +5,8 @@ with lib;
|
||||
let
|
||||
cfg = config.services.mbpfan;
|
||||
verbose = if cfg.verbose then "v" else "";
|
||||
settingsFormat = pkgs.formats.ini {};
|
||||
settingsFile = settingsFormat.generate "config.conf" cfg.settings;
|
||||
|
||||
in {
|
||||
options.services.mbpfan = {
|
||||
@@ -19,54 +21,6 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
minFanSpeed = mkOption {
|
||||
type = types.int;
|
||||
default = 2000;
|
||||
description = ''
|
||||
The minimum fan speed.
|
||||
'';
|
||||
};
|
||||
|
||||
maxFanSpeed = mkOption {
|
||||
type = types.int;
|
||||
default = 6200;
|
||||
description = ''
|
||||
The maximum fan speed.
|
||||
'';
|
||||
};
|
||||
|
||||
lowTemp = mkOption {
|
||||
type = types.int;
|
||||
default = 63;
|
||||
description = ''
|
||||
The low temperature.
|
||||
'';
|
||||
};
|
||||
|
||||
highTemp = mkOption {
|
||||
type = types.int;
|
||||
default = 66;
|
||||
description = ''
|
||||
The high temperature.
|
||||
'';
|
||||
};
|
||||
|
||||
maxTemp = mkOption {
|
||||
type = types.int;
|
||||
default = 86;
|
||||
description = ''
|
||||
The maximum temperature.
|
||||
'';
|
||||
};
|
||||
|
||||
pollingInterval = mkOption {
|
||||
type = types.int;
|
||||
default = 7;
|
||||
description = ''
|
||||
The polling interval.
|
||||
'';
|
||||
};
|
||||
|
||||
verbose = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -74,23 +28,61 @@ in {
|
||||
If true, sets the log level to verbose.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
default = {};
|
||||
description = "The INI configuration for Mbpfan.";
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.general.min_fan1_speed = mkOption {
|
||||
type = types.int;
|
||||
default = 2000;
|
||||
description = "The minimum fan speed.";
|
||||
};
|
||||
options.general.max_fan1_speed = mkOption {
|
||||
type = types.int;
|
||||
default = 6199;
|
||||
description = "The maximum fan speed.";
|
||||
};
|
||||
options.general.low_temp = mkOption {
|
||||
type = types.int;
|
||||
default = 55;
|
||||
description = "The low temperature.";
|
||||
};
|
||||
options.general.high_temp = mkOption {
|
||||
type = types.int;
|
||||
default = 58;
|
||||
description = "The high temperature.";
|
||||
};
|
||||
options.general.max_temp = mkOption {
|
||||
type = types.int;
|
||||
default = 86;
|
||||
description = "The maximum temperature.";
|
||||
};
|
||||
options.general.polling_interval = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = "The polling interval.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "pollingInterval" ] [ "services" "mbpfan" "settings" "general" "polling_interval" ])
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "maxTemp" ] [ "services" "mbpfan" "settings" "general" "max_temp" ])
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "lowTemp" ] [ "services" "mbpfan" "settings" "general" "low_temp" ])
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "highTemp" ] [ "services" "mbpfan" "settings" "general" "high_temp" ])
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "minFanSpeed" ] [ "services" "mbpfan" "settings" "general" "min_fan1_speed" ])
|
||||
(mkRenamedOptionModule [ "services" "mbpfan" "maxFanSpeed" ] [ "services" "mbpfan" "settings" "general" "max_fan1_speed" ])
|
||||
];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
boot.kernelModules = [ "coretemp" "applesmc" ];
|
||||
|
||||
environment = {
|
||||
etc."mbpfan.conf".text = ''
|
||||
[general]
|
||||
min_fan_speed = ${toString cfg.minFanSpeed}
|
||||
max_fan_speed = ${toString cfg.maxFanSpeed}
|
||||
low_temp = ${toString cfg.lowTemp}
|
||||
high_temp = ${toString cfg.highTemp}
|
||||
max_temp = ${toString cfg.maxTemp}
|
||||
polling_interval = ${toString cfg.pollingInterval}
|
||||
'';
|
||||
systemPackages = [ cfg.package ];
|
||||
};
|
||||
environment.etc."mbpfan.conf".source = settingsFile;
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
systemd.services.mbpfan = {
|
||||
description = "A fan manager daemon for MacBook Pro";
|
||||
|
||||
@@ -43,6 +43,7 @@ in
|
||||
# This folder must be writeable as the application is storing
|
||||
# its data in it, so the StateDirectory is a good choice
|
||||
N8N_USER_FOLDER = "/var/lib/n8n";
|
||||
HOME = "/var/lib/n8n";
|
||||
N8N_CONFIG_FILES = "${configFile}";
|
||||
};
|
||||
serviceConfig = {
|
||||
|
||||
@@ -19,8 +19,17 @@ let
|
||||
"${wrappedPlugins}/libexec/netdata/plugins.d"
|
||||
] ++ cfg.extraPluginPaths;
|
||||
|
||||
configDirectory = pkgs.runCommand "netdata-config-d" { } ''
|
||||
mkdir $out
|
||||
${concatStringsSep "\n" (mapAttrsToList (path: file: ''
|
||||
mkdir -p "$out/$(dirname ${path})"
|
||||
ln -s "${file}" "$out/${path}"
|
||||
'') cfg.configDir)}
|
||||
'';
|
||||
|
||||
localConfig = {
|
||||
global = {
|
||||
"config directory" = "/etc/netdata/conf.d";
|
||||
"plugins directory" = concatStringsSep " " plugins;
|
||||
};
|
||||
web = {
|
||||
@@ -130,6 +139,26 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
configDir = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
default = {};
|
||||
description = ''
|
||||
Complete netdata config directory except netdata.conf.
|
||||
The default configuration is merged with changes
|
||||
defined in this option.
|
||||
Each top-level attribute denotes a path in the configuration
|
||||
directory as in environment.etc.
|
||||
Its value is the absolute path and must be readable by netdata.
|
||||
Cannot be combined with configText.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
"health_alarm_notify.conf" = pkgs.writeText "health_alarm_notify.conf" '''
|
||||
sendmail="/path/to/sendmail"
|
||||
''';
|
||||
"health.d" = "/run/secrets/netdata/health.d";
|
||||
'';
|
||||
};
|
||||
|
||||
enableAnalyticsReporting = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -150,11 +179,14 @@ in {
|
||||
}
|
||||
];
|
||||
|
||||
environment.etc."netdata/netdata.conf".source = configFile;
|
||||
environment.etc."netdata/conf.d".source = configDirectory;
|
||||
|
||||
systemd.services.netdata = {
|
||||
description = "Real time performance monitoring";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = (with pkgs; [ curl gawk iproute2 which ])
|
||||
path = (with pkgs; [ curl gawk iproute2 which procps ])
|
||||
++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages)
|
||||
++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package);
|
||||
environment = {
|
||||
@@ -162,8 +194,12 @@ in {
|
||||
} // lib.optionalAttrs (!cfg.enableAnalyticsReporting) {
|
||||
DO_NOT_TRACK = "1";
|
||||
};
|
||||
restartTriggers = [
|
||||
config.environment.etc."netdata/netdata.conf".source
|
||||
config.environment.etc."netdata/conf.d".source
|
||||
];
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}";
|
||||
ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c /etc/netdata/netdata.conf";
|
||||
ExecReload = "${pkgs.util-linux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID";
|
||||
TimeoutStopSec = 60;
|
||||
Restart = "on-failure";
|
||||
|
||||
@@ -252,8 +252,8 @@ let
|
||||
promTypes.scrape_config = types.submodule {
|
||||
options = {
|
||||
authorization = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
type = types.nullOr types.attrs;
|
||||
default = null;
|
||||
description = ''
|
||||
Sets the `Authorization` header on every scrape request with the configured credentials.
|
||||
'';
|
||||
|
||||
@@ -87,6 +87,22 @@ in {
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.settings != { }
|
||||
-> (hasAttrByPath [ "dns" "bind_host" ] cfg.settings)
|
||||
|| (hasAttrByPath [ "dns" "bind_hosts" ] cfg.settings);
|
||||
message =
|
||||
"AdGuard setting dns.bind_host or dns.bind_hosts needs to be configured for a minimal working configuration";
|
||||
}
|
||||
{
|
||||
assertion = cfg.settings != { }
|
||||
-> hasAttrByPath [ "dns" "bootstrap_dns" ] cfg.settings;
|
||||
message =
|
||||
"AdGuard setting dns.bootstrap_dns needs to be configured for a minimal working configuration";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.adguardhome = {
|
||||
description = "AdGuard Home: Network-level blocker";
|
||||
after = [ "network.target" ];
|
||||
@@ -96,7 +112,7 @@ in {
|
||||
StartLimitBurst = 10;
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
preStart = optionalString (cfg.settings != { }) ''
|
||||
if [ -e "$STATE_DIRECTORY/AdGuardHome.yaml" ] \
|
||||
&& [ "${toString cfg.mutableSettings}" = "1" ]; then
|
||||
# Writing directly to AdGuardHome.yaml results in empty file
|
||||
|
||||
@@ -59,7 +59,7 @@ let
|
||||
listen-on-v6 { ${concatMapStrings (entry: " ${entry}; ") cfg.listenOnIpv6} };
|
||||
allow-query { cachenetworks; };
|
||||
blackhole { badnetworks; };
|
||||
forward first;
|
||||
forward ${cfg.forward};
|
||||
forwarders { ${concatMapStrings (entry: " ${entry}; ") cfg.forwarders} };
|
||||
directory "${cfg.directory}";
|
||||
pid-file "/run/named/named.pid";
|
||||
@@ -151,6 +151,14 @@ in
|
||||
";
|
||||
};
|
||||
|
||||
forward = mkOption {
|
||||
default = "first";
|
||||
type = types.enum ["first" "only"];
|
||||
description = "
|
||||
Whether to forward 'first' (try forwarding but lookup directly if forwarding fails) or 'only'.
|
||||
";
|
||||
};
|
||||
|
||||
listenOn = mkOption {
|
||||
default = [ "any" ];
|
||||
type = types.listOf types.str;
|
||||
|
||||
@@ -13,7 +13,7 @@ let
|
||||
foreground=YES
|
||||
use=${cfg.use}
|
||||
login=${cfg.username}
|
||||
password=
|
||||
password=${lib.optionalString (cfg.protocol == "nsupdate") "/run/${RuntimeDirectory}/ddclient.key"}
|
||||
protocol=${cfg.protocol}
|
||||
${lib.optionalString (cfg.script != "") "script=${cfg.script}"}
|
||||
${lib.optionalString (cfg.server != "") "server=${cfg.server}"}
|
||||
@@ -30,7 +30,9 @@ let
|
||||
|
||||
preStart = ''
|
||||
install ${configFile} /run/${RuntimeDirectory}/ddclient.conf
|
||||
${lib.optionalString (cfg.configFile == null) (if (cfg.passwordFile != null) then ''
|
||||
${lib.optionalString (cfg.configFile == null) (if (cfg.protocol == "nsupdate") then ''
|
||||
install ${cfg.passwordFile} /run/${RuntimeDirectory}/ddclient.key
|
||||
'' else if (cfg.passwordFile != null) then ''
|
||||
password=$(printf "%q" "$(head -n 1 "${cfg.passwordFile}")")
|
||||
sed -i "s|^password=$|password=$password|" /run/${RuntimeDirectory}/ddclient.conf
|
||||
'' else ''
|
||||
@@ -85,7 +87,9 @@ with lib;
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
default = "";
|
||||
# For `nsupdate` username contains the path to the nsupdate executable
|
||||
default = lib.optionalString (config.services.ddclient.protocol == "nsupdate") "${pkgs.bind.dnsutils}/bin/nsupdate";
|
||||
defaultText = "";
|
||||
type = str;
|
||||
description = ''
|
||||
User name.
|
||||
@@ -96,7 +100,7 @@ with lib;
|
||||
default = null;
|
||||
type = nullOr str;
|
||||
description = ''
|
||||
A file containing the password.
|
||||
A file containing the password or a TSIG key in named format when using the nsupdate protocol.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
{ config, lib, options, pkgs, ... }: let
|
||||
cfg = config.services.ergochat;
|
||||
in {
|
||||
options = {
|
||||
services.ergochat = {
|
||||
|
||||
enable = lib.mkEnableOption "Ergo IRC daemon";
|
||||
|
||||
openFilesLimit = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 1024;
|
||||
description = ''
|
||||
Maximum number of open files. Limits the clients and server connections.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = (pkgs.formats.yaml {}).generate "ergo.conf" cfg.settings;
|
||||
defaultText = "generated config file from <literal>.settings</literal>";
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
Setting this will skip any configuration done via <literal>.settings</literal>
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = (pkgs.formats.yaml {}).type;
|
||||
description = ''
|
||||
Ergo IRC daemon configuration file.
|
||||
https://raw.githubusercontent.com/ergochat/ergo/master/default.yaml
|
||||
'';
|
||||
default = {
|
||||
network = {
|
||||
name = "testnetwork";
|
||||
};
|
||||
server = {
|
||||
name = "example.com";
|
||||
listeners = {
|
||||
":6667" = {};
|
||||
};
|
||||
casemapping = "permissive";
|
||||
enforce-utf = true;
|
||||
lookup-hostnames = false;
|
||||
ip-cloaking = {
|
||||
enabled = false;
|
||||
};
|
||||
forward-confirm-hostnames = false;
|
||||
check-ident = false;
|
||||
relaymsg = {
|
||||
enabled = false;
|
||||
};
|
||||
max-sendq = "1M";
|
||||
ip-limits = {
|
||||
count = false;
|
||||
throttle = false;
|
||||
};
|
||||
};
|
||||
datastore = {
|
||||
autoupgrade = true;
|
||||
# this points to the StateDirectory of the systemd service
|
||||
path = "/var/lib/ergo/ircd.db";
|
||||
};
|
||||
accounts = {
|
||||
authentication-enabled = true;
|
||||
registration = {
|
||||
enabled = true;
|
||||
allow-before-connect = true;
|
||||
throttling = {
|
||||
enabled = true;
|
||||
duration = "10m";
|
||||
max-attempts = 30;
|
||||
};
|
||||
bcrypt-cost = 4;
|
||||
email-verification.enabled = false;
|
||||
};
|
||||
multiclient = {
|
||||
enabled = true;
|
||||
allowed-by-default = true;
|
||||
always-on = "opt-out";
|
||||
auto-away = "opt-out";
|
||||
};
|
||||
};
|
||||
channels = {
|
||||
default-modes = "+ntC";
|
||||
registration = {
|
||||
enabled = true;
|
||||
};
|
||||
};
|
||||
limits = {
|
||||
nicklen = 32;
|
||||
identlen = 20;
|
||||
channellen = 64;
|
||||
awaylen = 390;
|
||||
kicklen = 390;
|
||||
topiclen = 390;
|
||||
};
|
||||
history = {
|
||||
enabled = true;
|
||||
channel-length = 2048;
|
||||
client-length = 256;
|
||||
autoresize-window = "3d";
|
||||
autoreplay-on-join = 0;
|
||||
chathistory-maxmessages = 100;
|
||||
znc-maxmessages = 2048;
|
||||
restrictions = {
|
||||
expire-time = "1w";
|
||||
query-cutoff = "none";
|
||||
grace-period = "1h";
|
||||
};
|
||||
retention = {
|
||||
allow-individual-delete = false;
|
||||
enable-account-indexing = false;
|
||||
};
|
||||
tagmsg-storage = {
|
||||
default = false;
|
||||
whitelist = [
|
||||
"+draft/react"
|
||||
"+react"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.etc."ergo.yaml".source = cfg.configFile;
|
||||
|
||||
# merge configured values with default values
|
||||
services.ergochat.settings =
|
||||
lib.mapAttrsRecursive (_: lib.mkDefault) options.services.ergochat.settings.default;
|
||||
|
||||
systemd.services.ergochat = {
|
||||
description = "Ergo IRC daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# reload is not applying the changed config. further investigation is needed
|
||||
# at some point this should be enabled, since we don't want to restart for
|
||||
# every config change
|
||||
# reloadIfChanged = true;
|
||||
restartTriggers = [ cfg.configFile ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.ergochat}/bin/ergo run --conf /etc/ergo.yaml";
|
||||
ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "ergo";
|
||||
LimitNOFILE = toString cfg.openFilesLimit;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
meta.maintainers = with lib.maintainers; [ lassulus tv ];
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.frr;
|
||||
|
||||
services = [
|
||||
"static"
|
||||
"bgp"
|
||||
"ospf"
|
||||
"ospf6"
|
||||
"rip"
|
||||
"ripng"
|
||||
"isis"
|
||||
"pim"
|
||||
"ldp"
|
||||
"nhrp"
|
||||
"eigrp"
|
||||
"babel"
|
||||
"sharp"
|
||||
"pbr"
|
||||
"bfd"
|
||||
"fabric"
|
||||
];
|
||||
|
||||
allServices = services ++ [ "zebra" ];
|
||||
|
||||
isEnabled = service: cfg.${service}.enable;
|
||||
|
||||
daemonName = service: if service == "zebra" then service else "${service}d";
|
||||
|
||||
configFile = service:
|
||||
let
|
||||
scfg = cfg.${service};
|
||||
in
|
||||
if scfg.configFile != null then scfg.configFile
|
||||
else pkgs.writeText "${daemonName service}.conf"
|
||||
''
|
||||
! FRR ${daemonName service} configuration
|
||||
!
|
||||
hostname ${config.networking.hostName}
|
||||
log syslog
|
||||
service password-encryption
|
||||
!
|
||||
${scfg.config}
|
||||
!
|
||||
end
|
||||
'';
|
||||
|
||||
serviceOptions = service:
|
||||
{
|
||||
enable = mkEnableOption "the FRR ${toUpper service} routing protocol";
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/etc/frr/${daemonName service}.conf";
|
||||
description = ''
|
||||
Configuration file to use for FRR ${daemonName service}.
|
||||
By default the NixOS generated files are used.
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example =
|
||||
let
|
||||
examples = {
|
||||
rip = ''
|
||||
router rip
|
||||
network 10.0.0.0/8
|
||||
'';
|
||||
|
||||
ospf = ''
|
||||
router ospf
|
||||
network 10.0.0.0/8 area 0
|
||||
'';
|
||||
|
||||
bgp = ''
|
||||
router bgp 65001
|
||||
neighbor 10.0.0.1 remote-as 65001
|
||||
'';
|
||||
};
|
||||
in
|
||||
examples.${service} or "";
|
||||
description = ''
|
||||
${daemonName service} configuration statements.
|
||||
'';
|
||||
};
|
||||
|
||||
vtyListenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
description = ''
|
||||
Address to bind to for the VTY interface.
|
||||
'';
|
||||
};
|
||||
|
||||
vtyListenPort = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
TCP Port to bind to for the VTY interface.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
imports = [
|
||||
{
|
||||
options.services.frr = {
|
||||
zebra = (serviceOptions "zebra") // {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = any isEnabled services;
|
||||
description = ''
|
||||
Whether to enable the Zebra routing manager.
|
||||
|
||||
The Zebra routing manager is automatically enabled
|
||||
if any routing protocols are configured.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
{ options.services.frr = (genAttrs services serviceOptions); }
|
||||
];
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf (any isEnabled allServices) {
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.frr # for the vtysh tool
|
||||
];
|
||||
|
||||
users.users.frr = {
|
||||
description = "FRR daemon user";
|
||||
isSystemUser = true;
|
||||
group = "frr";
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
frr = {};
|
||||
# Members of the frrvty group can use vtysh to inspect the FRR daemons
|
||||
frrvty = { members = [ "frr" ]; };
|
||||
};
|
||||
|
||||
environment.etc = let
|
||||
mkEtcLink = service: {
|
||||
name = "frr/${service}.conf";
|
||||
value.source = configFile service;
|
||||
};
|
||||
in
|
||||
(builtins.listToAttrs
|
||||
(map mkEtcLink (filter isEnabled allServices))) // {
|
||||
"frr/vtysh.conf".text = "";
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /run/frr 0750 frr frr -"
|
||||
];
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
frrService = service:
|
||||
let
|
||||
scfg = cfg.${service};
|
||||
daemon = daemonName service;
|
||||
in
|
||||
nameValuePair daemon ({
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-pre.target" "systemd-sysctl.service" ] ++ lib.optionals (service != "zebra") [ "zebra.service" ];
|
||||
bindsTo = lib.optionals (service != "zebra") [ "zebra.service" ];
|
||||
wants = [ "network.target" ];
|
||||
|
||||
description = if service == "zebra" then "FRR Zebra routing manager"
|
||||
else "FRR ${toUpper service} routing daemon";
|
||||
|
||||
unitConfig.Documentation = if service == "zebra" then "man:zebra(8)"
|
||||
else "man:${daemon}(8) man:zebra(8)";
|
||||
|
||||
restartTriggers = [
|
||||
(configFile service)
|
||||
];
|
||||
reloadIfChanged = true;
|
||||
|
||||
serviceConfig = {
|
||||
PIDFile = "frr/${daemon}.pid";
|
||||
ExecStart = "${pkgs.frr}/libexec/frr/${daemon} -f /etc/frr/${service}.conf"
|
||||
+ optionalString (scfg.vtyListenAddress != "") " -A ${scfg.vtyListenAddress}"
|
||||
+ optionalString (scfg.vtyListenPort != null) " -P ${toString scfg.vtyListenPort}";
|
||||
ExecReload = "${pkgs.python3.interpreter} ${pkgs.frr}/libexec/frr/frr-reload.py --reload --daemon ${daemonName service} --bindir ${pkgs.frr}/bin --rundir /run/frr /etc/frr/${service}.conf";
|
||||
Restart = "on-abnormal";
|
||||
};
|
||||
});
|
||||
in
|
||||
listToAttrs (map frrService (filter isEnabled allServices));
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ woffs ];
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user