Merge branch 'master' into add/hashdeep-package
This commit is contained in:
commit
a28e401fd5
@ -235,5 +235,5 @@ package manager uses. To update the expressions run the `generate.sh` script
|
|||||||
that is stored in the `pkgs/development/mobile/androidenv/` sub directory:
|
that is stored in the `pkgs/development/mobile/androidenv/` sub directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sh ./generate.sh
|
./generate.sh
|
||||||
```
|
```
|
||||||
|
@ -233,7 +233,7 @@ mkDerivation {
|
|||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
You can rely on applications depending on the library set the necessary environment variables but that it often easy to miss. Instead we recommend to patch the paths in the source code whenever possible. Here are some examples:
|
You can rely on applications depending on the library setting the necessary environment variables but that is often easy to miss. Instead we recommend to patch the paths in the source code whenever possible. Here are some examples:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem xml:id="ssec-gnome-common-issues-unwrappable-package-gnome-shell-ext">
|
<listitem xml:id="ssec-gnome-common-issues-unwrappable-package-gnome-shell-ext">
|
||||||
<para>
|
<para>
|
||||||
|
@ -53,14 +53,16 @@ all crate sources of this package. Currently it is obtained by inserting a
|
|||||||
fake checksum into the expression and building the package once. The correct
|
fake checksum into the expression and building the package once. The correct
|
||||||
checksum can be then take from the failed build.
|
checksum can be then take from the failed build.
|
||||||
|
|
||||||
When the `Cargo.lock`, provided by upstream, is not in sync with the
|
Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
|
||||||
`Cargo.toml`, it is possible to use `cargoPatches` to update it. All patches
|
best practices guide, Rust applications should always commit the `Cargo.lock`
|
||||||
added in `cargoPatches` will also be prepended to the patches in `patches` at
|
file in git to ensure a reproducible build. However, a few packages do not, and
|
||||||
build-time.
|
Nix depends on this file, so if it missing you can use `cargoPatches` to apply
|
||||||
|
it in the `patchPhase`. Consider sending a PR upstream with a note to the
|
||||||
|
maintainer describing why it's important to include in the application.
|
||||||
|
|
||||||
Unless `legacyCargoFetcher` is set to `true`, the fetcher will also verify that
|
The fetcher will verify that the `Cargo.lock` file is in sync with the `src`
|
||||||
the `Cargo.lock` file is in sync with the `src` attribute, and will compress the
|
attribute, and fail the build if not. It will also will compress the vendor
|
||||||
vendor directory into a tar.gz archive.
|
directory into a tar.gz archive.
|
||||||
|
|
||||||
### Building a crate for a different target
|
### Building a crate for a different target
|
||||||
|
|
||||||
|
@ -131,7 +131,12 @@ rec {
|
|||||||
origArgs = auto // args;
|
origArgs = auto // args;
|
||||||
pkgs = f origArgs;
|
pkgs = f origArgs;
|
||||||
mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
|
mkAttrOverridable = name: _: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
|
||||||
in lib.mapAttrs mkAttrOverridable pkgs;
|
in
|
||||||
|
if lib.isDerivation pkgs then throw
|
||||||
|
("function `callPackages` was called on a *single* derivation "
|
||||||
|
+ ''"${pkgs.name or "<unknown-name>"}";''
|
||||||
|
+ " did you mean to use `callPackage` instead?")
|
||||||
|
else lib.mapAttrs mkAttrOverridable pkgs;
|
||||||
|
|
||||||
|
|
||||||
/* Add attributes to each output of a derivation without changing
|
/* Add attributes to each output of a derivation without changing
|
||||||
|
@ -24,6 +24,7 @@ let
|
|||||||
# packaging
|
# packaging
|
||||||
customisation = callLibs ./customisation.nix;
|
customisation = callLibs ./customisation.nix;
|
||||||
maintainers = import ../maintainers/maintainer-list.nix;
|
maintainers = import ../maintainers/maintainer-list.nix;
|
||||||
|
teams = callLibs ../maintainers/team-list.nix;
|
||||||
meta = callLibs ./meta.nix;
|
meta = callLibs ./meta.nix;
|
||||||
sources = callLibs ./sources.nix;
|
sources = callLibs ./sources.nix;
|
||||||
versions = callLibs ./versions.nix;
|
versions = callLibs ./versions.nix;
|
||||||
@ -55,6 +56,9 @@ let
|
|||||||
# back-compat aliases
|
# back-compat aliases
|
||||||
platforms = systems.doubles;
|
platforms = systems.doubles;
|
||||||
|
|
||||||
|
# linux kernel configuration
|
||||||
|
kernel = callLibs ./kernel.nix;
|
||||||
|
|
||||||
inherit (builtins) add addErrorContext attrNames concatLists
|
inherit (builtins) add addErrorContext attrNames concatLists
|
||||||
deepSeq elem elemAt filter genericClosure genList getAttr
|
deepSeq elem elemAt filter genericClosure genList getAttr
|
||||||
hasAttr head isAttrs isBool isInt isList isString length
|
hasAttr head isAttrs isBool isInt isList isString length
|
||||||
|
@ -76,10 +76,14 @@ rec {
|
|||||||
* mkKeyValue is the same as in toINI.
|
* mkKeyValue is the same as in toINI.
|
||||||
*/
|
*/
|
||||||
toKeyValue = {
|
toKeyValue = {
|
||||||
mkKeyValue ? mkKeyValueDefault {} "="
|
mkKeyValue ? mkKeyValueDefault {} "=",
|
||||||
}: attrs:
|
listsAsDuplicateKeys ? false
|
||||||
let mkLine = k: v: mkKeyValue k v + "\n";
|
}:
|
||||||
in libStr.concatStrings (libAttr.mapAttrsToList mkLine attrs);
|
let mkLine = k: v: mkKeyValue k v + "\n";
|
||||||
|
mkLines = if listsAsDuplicateKeys
|
||||||
|
then k: v: map (mkLine k) (if lib.isList v then v else [v])
|
||||||
|
else k: v: [ (mkLine k v) ];
|
||||||
|
in attrs: libStr.concatStrings (lib.concatLists (libAttr.mapAttrsToList mkLines attrs));
|
||||||
|
|
||||||
|
|
||||||
/* Generate an INI-style config file from an
|
/* Generate an INI-style config file from an
|
||||||
@ -106,7 +110,9 @@ rec {
|
|||||||
# apply transformations (e.g. escapes) to section names
|
# apply transformations (e.g. escapes) to section names
|
||||||
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
|
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
|
||||||
# format a setting line from key and value
|
# format a setting line from key and value
|
||||||
mkKeyValue ? mkKeyValueDefault {} "="
|
mkKeyValue ? mkKeyValueDefault {} "=",
|
||||||
|
# allow lists as values for duplicate keys
|
||||||
|
listsAsDuplicateKeys ? false
|
||||||
}: attrsOfAttrs:
|
}: attrsOfAttrs:
|
||||||
let
|
let
|
||||||
# map function to string for each key val
|
# map function to string for each key val
|
||||||
@ -115,7 +121,7 @@ rec {
|
|||||||
(libAttr.mapAttrsToList mapFn attrs);
|
(libAttr.mapAttrsToList mapFn attrs);
|
||||||
mkSection = sectName: sectValues: ''
|
mkSection = sectName: sectValues: ''
|
||||||
[${mkSectionName sectName}]
|
[${mkSectionName sectName}]
|
||||||
'' + toKeyValue { inherit mkKeyValue; } sectValues;
|
'' + toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } sectValues;
|
||||||
in
|
in
|
||||||
# map input to ini sections
|
# map input to ini sections
|
||||||
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
|
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
{ lib, version }:
|
{ lib }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
# Common patterns/legacy
|
|
||||||
whenAtLeast = ver: mkIf (versionAtLeast version ver);
|
|
||||||
whenOlder = ver: mkIf (versionOlder version ver);
|
|
||||||
# range is (inclusive, exclusive)
|
|
||||||
whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh);
|
|
||||||
|
|
||||||
|
|
||||||
# Keeping these around in case we decide to change this horrible implementation :)
|
# Keeping these around in case we decide to change this horrible implementation :)
|
||||||
@ -18,4 +13,14 @@ with lib;
|
|||||||
module = { tristate = "m"; };
|
module = { tristate = "m"; };
|
||||||
freeform = x: { freeform = x; };
|
freeform = x: { freeform = x; };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Common patterns/legacy used in common-config/hardened-config.nix
|
||||||
|
*/
|
||||||
|
whenHelpers = version: {
|
||||||
|
whenAtLeast = ver: mkIf (versionAtLeast version ver);
|
||||||
|
whenOlder = ver: mkIf (versionOlder version ver);
|
||||||
|
# range is (inclusive, exclusive)
|
||||||
|
whenBetween = verLow: verHigh: mkIf (versionAtLeast version verLow && versionOlder version verHigh);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,11 @@ rec {
|
|||||||
res set._definedNames
|
res set._definedNames
|
||||||
else
|
else
|
||||||
res;
|
res;
|
||||||
result = { inherit options config; };
|
result = {
|
||||||
|
inherit options;
|
||||||
|
config = removeAttrs config [ "_module" ];
|
||||||
|
inherit (config) _module;
|
||||||
|
};
|
||||||
in result;
|
in result;
|
||||||
|
|
||||||
# collectModules :: (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> [ Module ]
|
# collectModules :: (modulesPath: String) -> (modules: [ Module ]) -> (args: Attrs) -> [ Module ]
|
||||||
@ -389,7 +393,7 @@ rec {
|
|||||||
let
|
let
|
||||||
# Process mkMerge and mkIf properties.
|
# Process mkMerge and mkIf properties.
|
||||||
defs' = concatMap (m:
|
defs' = concatMap (m:
|
||||||
map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value)
|
map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
|
||||||
) defs;
|
) defs;
|
||||||
|
|
||||||
# Process mkOverride properties.
|
# Process mkOverride properties.
|
||||||
@ -410,10 +414,9 @@ rec {
|
|||||||
# Type-check the remaining definitions, and merge them. Or throw if no definitions.
|
# Type-check the remaining definitions, and merge them. Or throw if no definitions.
|
||||||
mergedValue =
|
mergedValue =
|
||||||
if isDefined then
|
if isDefined then
|
||||||
foldl' (res: def:
|
if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
|
||||||
if type.check def.value then res
|
else let firstInvalid = findFirst (def: ! type.check def.value) null defsFinal;
|
||||||
else throw "The option value `${showOption loc}' in `${def.file}' is not of type `${type.description}'."
|
in throw "The option value `${showOption loc}' in `${firstInvalid.file}' is not of type `${type.description}'."
|
||||||
) (type.merge loc defsFinal) defsFinal
|
|
||||||
else
|
else
|
||||||
# (nixos-option detects this specific error message and gives it special
|
# (nixos-option detects this specific error message and gives it special
|
||||||
# handling. If changed here, please change it there too.)
|
# handling. If changed here, please change it there too.)
|
||||||
|
@ -159,7 +159,7 @@ rec {
|
|||||||
let ss = opt.type.getSubOptions opt.loc;
|
let ss = opt.type.getSubOptions opt.loc;
|
||||||
in if ss != {} then optionAttrSetToDocList' opt.loc ss else [];
|
in if ss != {} then optionAttrSetToDocList' opt.loc ss else [];
|
||||||
in
|
in
|
||||||
[ docOption ] ++ subOptions) (collect isOption options);
|
[ docOption ] ++ optionals docOption.visible subOptions) (collect isOption options);
|
||||||
|
|
||||||
|
|
||||||
/* This function recursively removes all derivation attributes from
|
/* This function recursively removes all derivation attributes from
|
||||||
|
@ -26,7 +26,13 @@ let
|
|||||||
|
|
||||||
"riscv32-linux" "riscv64-linux"
|
"riscv32-linux" "riscv64-linux"
|
||||||
|
|
||||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none" "vc4-none"
|
"arm-none" "armv6l-none" "aarch64-none"
|
||||||
|
"avr-none"
|
||||||
|
"i686-none" "x86_64-none"
|
||||||
|
"powerpc-none"
|
||||||
|
"msp430-none"
|
||||||
|
"riscv64-none" "riscv32-none"
|
||||||
|
"vc4-none"
|
||||||
|
|
||||||
"js-ghcjs"
|
"js-ghcjs"
|
||||||
];
|
];
|
||||||
|
@ -348,6 +348,18 @@ runTests {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
testToINIDuplicateKeys = {
|
||||||
|
expr = generators.toINI { listsAsDuplicateKeys = true; } { foo.bar = true; baz.qux = [ 1 false ]; };
|
||||||
|
expected = ''
|
||||||
|
[baz]
|
||||||
|
qux=1
|
||||||
|
qux=false
|
||||||
|
|
||||||
|
[foo]
|
||||||
|
bar=true
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
testToINIDefaultEscapes = {
|
testToINIDefaultEscapes = {
|
||||||
expr = generators.toINI {} {
|
expr = generators.toINI {} {
|
||||||
"no [ and ] allowed unescaped" = {
|
"no [ and ] allowed unescaped" = {
|
||||||
|
@ -185,6 +185,14 @@ checkConfigError 'The option .* defined in .* does not exist' config.enable ./di
|
|||||||
# Check that imports can depend on derivations
|
# Check that imports can depend on derivations
|
||||||
checkConfigOutput "true" config.enable ./import-from-store.nix
|
checkConfigOutput "true" config.enable ./import-from-store.nix
|
||||||
|
|
||||||
|
# Check that configs can be conditional on option existence
|
||||||
|
checkConfigOutput true config.enable ./define-option-dependently.nix ./declare-enable.nix ./declare-int-positive-value.nix
|
||||||
|
checkConfigOutput 360 config.value ./define-option-dependently.nix ./declare-enable.nix ./declare-int-positive-value.nix
|
||||||
|
checkConfigOutput 7 config.value ./define-option-dependently.nix ./declare-int-positive-value.nix
|
||||||
|
checkConfigOutput true config.set.enable ./define-option-dependently-nested.nix ./declare-enable-nested.nix ./declare-int-positive-value-nested.nix
|
||||||
|
checkConfigOutput 360 config.set.value ./define-option-dependently-nested.nix ./declare-enable-nested.nix ./declare-int-positive-value-nested.nix
|
||||||
|
checkConfigOutput 7 config.set.value ./define-option-dependently-nested.nix ./declare-int-positive-value-nested.nix
|
||||||
|
|
||||||
# Check attrsOf and lazyAttrsOf. Only lazyAttrsOf should be lazy, and only
|
# Check attrsOf and lazyAttrsOf. Only lazyAttrsOf should be lazy, and only
|
||||||
# attrsOf should work with conditional definitions
|
# attrsOf should work with conditional definitions
|
||||||
# In addition, lazyAttrsOf should honor an options emptyValue
|
# In addition, lazyAttrsOf should honor an options emptyValue
|
||||||
@ -194,6 +202,11 @@ checkConfigOutput "true" config.conditionalWorks ./declare-attrsOf.nix ./attrsOf
|
|||||||
checkConfigOutput "false" config.conditionalWorks ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
checkConfigOutput "false" config.conditionalWorks ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
||||||
checkConfigOutput "empty" config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
checkConfigOutput "empty" config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
||||||
|
|
||||||
|
|
||||||
|
# Even with multiple assignments, a type error should be thrown if any of them aren't valid
|
||||||
|
checkConfigError 'The option value .* in .* is not of type .*' \
|
||||||
|
config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
14
lib/tests/modules/declare-enable-nested.nix
Normal file
14
lib/tests/modules/declare-enable-nested.nix
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options.set = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
default = false;
|
||||||
|
example = true;
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = ''
|
||||||
|
Some descriptive text
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
9
lib/tests/modules/declare-int-positive-value-nested.nix
Normal file
9
lib/tests/modules/declare-int-positive-value-nested.nix
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options.set = {
|
||||||
|
value = lib.mkOption {
|
||||||
|
type = lib.types.ints.positive;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
16
lib/tests/modules/define-option-dependently-nested.nix
Normal file
16
lib/tests/modules/define-option-dependently-nested.nix
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{ lib, options, ... }:
|
||||||
|
|
||||||
|
# Some modules may be distributed separately and need to adapt to other modules
|
||||||
|
# that are distributed and versioned separately.
|
||||||
|
{
|
||||||
|
|
||||||
|
# Always defined, but the value depends on the presence of an option.
|
||||||
|
config.set = {
|
||||||
|
value = if options ? set.enable then 360 else 7;
|
||||||
|
}
|
||||||
|
# Only define if possible.
|
||||||
|
// lib.optionalAttrs (options ? set.enable) {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
16
lib/tests/modules/define-option-dependently.nix
Normal file
16
lib/tests/modules/define-option-dependently.nix
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{ lib, options, ... }:
|
||||||
|
|
||||||
|
# Some modules may be distributed separately and need to adapt to other modules
|
||||||
|
# that are distributed and versioned separately.
|
||||||
|
{
|
||||||
|
|
||||||
|
# Always defined, but the value depends on the presence of an option.
|
||||||
|
config = {
|
||||||
|
value = if options ? enable then 360 else 7;
|
||||||
|
}
|
||||||
|
# Only define if possible.
|
||||||
|
// lib.optionalAttrs (options ? enable) {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -14,7 +14,7 @@ let
|
|||||||
in with lib.systems.doubles; lib.runTests {
|
in with lib.systems.doubles; lib.runTests {
|
||||||
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js);
|
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js);
|
||||||
|
|
||||||
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
|
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-none" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
|
||||||
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
|
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
|
||||||
testmips = mseteq mips [ "mipsel-linux" ];
|
testmips = mseteq mips [ "mipsel-linux" ];
|
||||||
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
|
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* List of NixOS maintainers.
|
/* List of NixOS maintainers.
|
||||||
|
```nix
|
||||||
handle = {
|
handle = {
|
||||||
# Required
|
# Required
|
||||||
name = "Your name";
|
name = "Your name";
|
||||||
@ -13,32 +13,33 @@
|
|||||||
fingerprint = "AAAA BBBB CCCC DDDD EEEE FFFF 0000 1111 2222 3333";
|
fingerprint = "AAAA BBBB CCCC DDDD EEEE FFFF 0000 1111 2222 3333";
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
- `handle` is the handle you are going to use in nixpkgs expressions,
|
- `handle` is the handle you are going to use in nixpkgs expressions,
|
||||||
- `name` is your, preferably real, name,
|
- `name` is your, preferably real, name,
|
||||||
- `email` is your maintainer email address, and
|
- `email` is your maintainer email address, and
|
||||||
- `github` is your GitHub handle (as it appears in the URL of your profile page, `https://github.com/<userhandle>`),
|
- `github` is your GitHub handle (as it appears in the URL of your profile page, `https://github.com/<userhandle>`),
|
||||||
- `githubId` is your GitHub user ID, which can be found at `https://api.github.com/users/<userhandle>`,
|
- `githubId` is your GitHub user ID, which can be found at `https://api.github.com/users/<userhandle>`,
|
||||||
- `keys` is a list of your PGP/GPG key IDs and fingerprints.
|
- `keys` is a list of your PGP/GPG key IDs and fingerprints.
|
||||||
|
|
||||||
`handle == github` is strongly preferred whenever `github` is an acceptable attribute name and is short and convenient.
|
`handle == github` is strongly preferred whenever `github` is an acceptable attribute name and is short and convenient.
|
||||||
|
|
||||||
Add PGP/GPG keys only if you actually use them to sign commits and/or mail.
|
Add PGP/GPG keys only if you actually use them to sign commits and/or mail.
|
||||||
|
|
||||||
To get the required PGP/GPG values for a key run
|
To get the required PGP/GPG values for a key run
|
||||||
```shell
|
```shell
|
||||||
gpg --keyid-format 0xlong --fingerprint <email> | head -n 2
|
gpg --keyid-format 0xlong --fingerprint <email> | head -n 2
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Note that PGP/GPG values stored here are for informational purposes only, don't use this file as a source of truth.
|
!!! Note that PGP/GPG values stored here are for informational purposes only, don't use this file as a source of truth.
|
||||||
|
|
||||||
More fields may be added in the future.
|
More fields may be added in the future.
|
||||||
|
|
||||||
Please keep the list alphabetically sorted.
|
Please keep the list alphabetically sorted.
|
||||||
See `./scripts/check-maintainer-github-handles.sh` for an example on how to work with this data.
|
See `./scripts/check-maintainer-github-handles.sh` for an example on how to work with this data.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
"0x4A6F" = {
|
"0x4A6F" = {
|
||||||
email = "0x4A6F@shackspace.de";
|
email = "0x4A6F@shackspace.de";
|
||||||
@ -710,6 +711,12 @@
|
|||||||
githubId = 55833;
|
githubId = 55833;
|
||||||
name = "Troels Henriksen";
|
name = "Troels Henriksen";
|
||||||
};
|
};
|
||||||
|
atkinschang = {
|
||||||
|
email = "atkinschang+nixpkgs@gmail.com";
|
||||||
|
github = "AtkinsChang";
|
||||||
|
githubId = 5193600;
|
||||||
|
name = "Atkins Chang";
|
||||||
|
};
|
||||||
atnnn = {
|
atnnn = {
|
||||||
email = "etienne@atnnn.com";
|
email = "etienne@atnnn.com";
|
||||||
github = "atnnn";
|
github = "atnnn";
|
||||||
@ -1461,6 +1468,16 @@
|
|||||||
githubId = 5684605;
|
githubId = 5684605;
|
||||||
name = "Cole Scott";
|
name = "Cole Scott";
|
||||||
};
|
};
|
||||||
|
cole-h = {
|
||||||
|
name = "Cole Helbling";
|
||||||
|
email = "cole.e.helbling@outlook.com";
|
||||||
|
github = "cole-h";
|
||||||
|
githubId = 28582702;
|
||||||
|
keys = [{
|
||||||
|
longkeyid = "rsa4096/0xB37E0F2371016A4C";
|
||||||
|
fingerprint = "68B8 0D57 B2E5 4AC3 EC1F 49B0 B37E 0F23 7101 6A4C";
|
||||||
|
}];
|
||||||
|
};
|
||||||
copumpkin = {
|
copumpkin = {
|
||||||
email = "pumpkingod@gmail.com";
|
email = "pumpkingod@gmail.com";
|
||||||
github = "copumpkin";
|
github = "copumpkin";
|
||||||
@ -1562,10 +1579,12 @@
|
|||||||
githubId = 2217136;
|
githubId = 2217136;
|
||||||
name = "Ștefan D. Mihăilă";
|
name = "Ștefan D. Mihăilă";
|
||||||
keys = [
|
keys = [
|
||||||
{ longkeyid = "rsa4096/6E68A39BF16A3ECB";
|
{
|
||||||
|
longkeyid = "rsa4096/6E68A39BF16A3ECB";
|
||||||
fingerprint = "CBC9 C7CC 51F0 4A61 3901 C723 6E68 A39B F16A 3ECB";
|
fingerprint = "CBC9 C7CC 51F0 4A61 3901 C723 6E68 A39B F16A 3ECB";
|
||||||
}
|
}
|
||||||
{ longkeyid = "rsa4096/6220AD7846220A52";
|
{
|
||||||
|
longkeyid = "rsa4096/6220AD7846220A52";
|
||||||
fingerprint = "7EAB 1447 5BBA 7DDE 7092 7276 6220 AD78 4622 0A52";
|
fingerprint = "7EAB 1447 5BBA 7DDE 7092 7276 6220 AD78 4622 0A52";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -1782,7 +1801,7 @@
|
|||||||
name = "Didier J. Devroye";
|
name = "Didier J. Devroye";
|
||||||
};
|
};
|
||||||
devhell = {
|
devhell = {
|
||||||
email = "\"^\"@regexmail.net";
|
email = ''"^"@regexmail.net'';
|
||||||
github = "devhell";
|
github = "devhell";
|
||||||
githubId = 896182;
|
githubId = 896182;
|
||||||
name = "devhell";
|
name = "devhell";
|
||||||
@ -1948,7 +1967,7 @@
|
|||||||
drewrisinger = {
|
drewrisinger = {
|
||||||
email = "drisinger+nixpkgs@gmail.com";
|
email = "drisinger+nixpkgs@gmail.com";
|
||||||
github = "drewrisinger";
|
github = "drewrisinger";
|
||||||
gitHubId = 10198051;
|
githubId = 10198051;
|
||||||
name = "Drew Risinger";
|
name = "Drew Risinger";
|
||||||
};
|
};
|
||||||
dsferruzza = {
|
dsferruzza = {
|
||||||
@ -2121,7 +2140,7 @@
|
|||||||
};
|
};
|
||||||
ehmry = {
|
ehmry = {
|
||||||
email = "ehmry@posteo.net";
|
email = "ehmry@posteo.net";
|
||||||
github= "ehmry";
|
github = "ehmry";
|
||||||
githubId = 537775;
|
githubId = 537775;
|
||||||
name = "Emery Hemingway";
|
name = "Emery Hemingway";
|
||||||
};
|
};
|
||||||
@ -2209,10 +2228,10 @@
|
|||||||
name = "Jack Kelly";
|
name = "Jack Kelly";
|
||||||
};
|
};
|
||||||
enorris = {
|
enorris = {
|
||||||
name = "Eric Norris";
|
name = "Eric Norris";
|
||||||
email = "erictnorris@gmail.com";
|
email = "erictnorris@gmail.com";
|
||||||
github = "ericnorris";
|
github = "ericnorris";
|
||||||
githubId = 1906605;
|
githubId = 1906605;
|
||||||
};
|
};
|
||||||
Enteee = {
|
Enteee = {
|
||||||
email = "nix@duckpond.ch";
|
email = "nix@duckpond.ch";
|
||||||
@ -2735,6 +2754,12 @@
|
|||||||
githubId = 3217744;
|
githubId = 3217744;
|
||||||
name = "Peter Ferenczy";
|
name = "Peter Ferenczy";
|
||||||
};
|
};
|
||||||
|
gila = {
|
||||||
|
email = "jeffry.molanus@gmail.com";
|
||||||
|
github = "gila";
|
||||||
|
githubId = 15957973;
|
||||||
|
name = "Jeffry Molanus";
|
||||||
|
};
|
||||||
gilligan = {
|
gilligan = {
|
||||||
email = "tobias.pflug@gmail.com";
|
email = "tobias.pflug@gmail.com";
|
||||||
github = "gilligan";
|
github = "gilligan";
|
||||||
@ -2881,7 +2906,7 @@
|
|||||||
github = "hansjoergschurr";
|
github = "hansjoergschurr";
|
||||||
githubId = 9850776;
|
githubId = 9850776;
|
||||||
name = "Hans-Jörg Schurr";
|
name = "Hans-Jörg Schurr";
|
||||||
};
|
};
|
||||||
HaoZeke = {
|
HaoZeke = {
|
||||||
email = "r95g10@gmail.com";
|
email = "r95g10@gmail.com";
|
||||||
github = "haozeke";
|
github = "haozeke";
|
||||||
@ -3086,6 +3111,12 @@
|
|||||||
githubId = 4401220;
|
githubId = 4401220;
|
||||||
name = "Michael Eden";
|
name = "Michael Eden";
|
||||||
};
|
};
|
||||||
|
illiusdope = {
|
||||||
|
email = "mat@marini.ca";
|
||||||
|
github = "illiusdope";
|
||||||
|
githubId = 61913481;
|
||||||
|
name = "Mat Marini";
|
||||||
|
};
|
||||||
ilya-fedin = {
|
ilya-fedin = {
|
||||||
email = "fedin-ilja2010@ya.ru";
|
email = "fedin-ilja2010@ya.ru";
|
||||||
github = "ilya-fedin";
|
github = "ilya-fedin";
|
||||||
@ -3580,6 +3611,12 @@
|
|||||||
github = "jorsn";
|
github = "jorsn";
|
||||||
githubId = 4646725;
|
githubId = 4646725;
|
||||||
};
|
};
|
||||||
|
joshuafern = {
|
||||||
|
name = "Joshua Fern";
|
||||||
|
email = "joshuafern@protonmail.com";
|
||||||
|
github = "JoshuaFern";
|
||||||
|
githubId = 4300747;
|
||||||
|
};
|
||||||
jpas = {
|
jpas = {
|
||||||
name = "Jarrod Pas";
|
name = "Jarrod Pas";
|
||||||
email = "jarrod@jarrodpas.com";
|
email = "jarrod@jarrodpas.com";
|
||||||
@ -3688,6 +3725,16 @@
|
|||||||
githubId = 66669;
|
githubId = 66669;
|
||||||
name = "Jeff Zellner";
|
name = "Jeff Zellner";
|
||||||
};
|
};
|
||||||
|
kaction = {
|
||||||
|
name = "Dmitry Bogatov";
|
||||||
|
email = "KAction@disroot.org";
|
||||||
|
github = "kaction";
|
||||||
|
githubId = 44864956;
|
||||||
|
key = [{
|
||||||
|
longkeyid = "ed25519/0x749FD4DFA2E94236";
|
||||||
|
fingerprint = "3F87 0A7C A7B4 3731 2F13 6083 749F D4DF A2E9 4236";
|
||||||
|
}];
|
||||||
|
};
|
||||||
kaiha = {
|
kaiha = {
|
||||||
email = "kai.harries@gmail.com";
|
email = "kai.harries@gmail.com";
|
||||||
github = "kaiha";
|
github = "kaiha";
|
||||||
@ -4113,6 +4160,12 @@
|
|||||||
github = "leonardoce";
|
github = "leonardoce";
|
||||||
name = "Leonardo Cecchi";
|
name = "Leonardo Cecchi";
|
||||||
};
|
};
|
||||||
|
leshainc = {
|
||||||
|
email = "leshainc@fomalhaut.me";
|
||||||
|
github = "LeshaInc";
|
||||||
|
githubId = 42153076;
|
||||||
|
name = "Alexey Nikashkin";
|
||||||
|
};
|
||||||
lethalman = {
|
lethalman = {
|
||||||
email = "lucabru@src.gnome.org";
|
email = "lucabru@src.gnome.org";
|
||||||
github = "lethalman";
|
github = "lethalman";
|
||||||
@ -4125,6 +4178,16 @@
|
|||||||
githubId = 3425311;
|
githubId = 3425311;
|
||||||
name = "Antoine Eiche";
|
name = "Antoine Eiche";
|
||||||
};
|
};
|
||||||
|
lexuge = {
|
||||||
|
name = "Harry Ying";
|
||||||
|
email = "lexugeyky@outlook.com";
|
||||||
|
github = "LEXUGE";
|
||||||
|
githubId = 13804737;
|
||||||
|
keys = [{
|
||||||
|
longkeyid = "rsa4096/0xAE53B4C2E58EDD45";
|
||||||
|
fingerprint = "7FE2 113A A08B 695A C8B8 DDE6 AE53 B4C2 E58E DD45";
|
||||||
|
}];
|
||||||
|
};
|
||||||
lheckemann = {
|
lheckemann = {
|
||||||
email = "git@sphalerite.org";
|
email = "git@sphalerite.org";
|
||||||
github = "lheckemann";
|
github = "lheckemann";
|
||||||
@ -4208,10 +4271,10 @@
|
|||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
luis = {
|
luis = {
|
||||||
email = "luis.nixos@gmail.com";
|
email = "luis.nixos@gmail.com";
|
||||||
github = "Luis-Hebendanz";
|
github = "Luis-Hebendanz";
|
||||||
githubId = 22085373;
|
githubId = 22085373;
|
||||||
name = "Luis Hebendanz";
|
name = "Luis Hebendanz";
|
||||||
};
|
};
|
||||||
lionello = {
|
lionello = {
|
||||||
email = "lio@lunesu.com";
|
email = "lio@lunesu.com";
|
||||||
@ -4454,12 +4517,12 @@
|
|||||||
githubId = 50230945;
|
githubId = 50230945;
|
||||||
name = "Marcus Boyd";
|
name = "Marcus Boyd";
|
||||||
};
|
};
|
||||||
marenz = {
|
marenz = {
|
||||||
email = "marenz@arkom.men";
|
email = "marenz@arkom.men";
|
||||||
github = "marenz2569";
|
github = "marenz2569";
|
||||||
githubId = 12773269;
|
githubId = 12773269;
|
||||||
name = "Markus Schmidl";
|
name = "Markus Schmidl";
|
||||||
};
|
};
|
||||||
markus1189 = {
|
markus1189 = {
|
||||||
email = "markus1189@gmail.com";
|
email = "markus1189@gmail.com";
|
||||||
github = "markus1189";
|
github = "markus1189";
|
||||||
@ -4528,6 +4591,12 @@
|
|||||||
githubId = 1711539;
|
githubId = 1711539;
|
||||||
name = "matklad";
|
name = "matklad";
|
||||||
};
|
};
|
||||||
|
matt-snider = {
|
||||||
|
email = "matt.snider@protonmail.com";
|
||||||
|
github = "matt-snider";
|
||||||
|
githubId = 11810057;
|
||||||
|
name = "Matt Snider";
|
||||||
|
};
|
||||||
matthewbauer = {
|
matthewbauer = {
|
||||||
email = "mjbauer95@gmail.com";
|
email = "mjbauer95@gmail.com";
|
||||||
github = "matthewbauer";
|
github = "matthewbauer";
|
||||||
@ -4562,6 +4631,12 @@
|
|||||||
githubId = 1269099;
|
githubId = 1269099;
|
||||||
name = "Marius Bakke";
|
name = "Marius Bakke";
|
||||||
};
|
};
|
||||||
|
mbaillie = {
|
||||||
|
email = "martin@baillie.email";
|
||||||
|
github = "martinbaillie";
|
||||||
|
githubId = 613740;
|
||||||
|
name = "Martin Baillie";
|
||||||
|
};
|
||||||
mbbx6spp = {
|
mbbx6spp = {
|
||||||
email = "me@susanpotter.net";
|
email = "me@susanpotter.net";
|
||||||
github = "mbbx6spp";
|
github = "mbbx6spp";
|
||||||
@ -4703,7 +4778,7 @@
|
|||||||
githubId = 668926;
|
githubId = 668926;
|
||||||
name = "Maximilian Güntner";
|
name = "Maximilian Güntner";
|
||||||
};
|
};
|
||||||
mhaselsteiner = {
|
mhaselsteiner = {
|
||||||
email = "magdalena.haselsteiner@gmx.at";
|
email = "magdalena.haselsteiner@gmx.at";
|
||||||
github = "mhaselsteiner";
|
github = "mhaselsteiner";
|
||||||
githubId = 20536514;
|
githubId = 20536514;
|
||||||
@ -4868,11 +4943,11 @@
|
|||||||
mmilata = {
|
mmilata = {
|
||||||
email = "martin@martinmilata.cz";
|
email = "martin@martinmilata.cz";
|
||||||
github = "mmilata";
|
github = "mmilata";
|
||||||
gitHubId = 85857;
|
githubId = 85857;
|
||||||
name = "Martin Milata";
|
name = "Martin Milata";
|
||||||
};
|
};
|
||||||
mmlb = {
|
mmlb = {
|
||||||
email = "me.mmlb@mmlb.me";
|
email = "manny@peekaboo.mmlb.icu";
|
||||||
github = "mmlb";
|
github = "mmlb";
|
||||||
name = "Manuel Mendez";
|
name = "Manuel Mendez";
|
||||||
};
|
};
|
||||||
@ -4945,6 +5020,12 @@
|
|||||||
githubId = 118035;
|
githubId = 118035;
|
||||||
name = "Corbin Simpson";
|
name = "Corbin Simpson";
|
||||||
};
|
};
|
||||||
|
mothsart = {
|
||||||
|
email = "jerem.ferry@gmail.com";
|
||||||
|
github = "mothsart";
|
||||||
|
githubId = 10601196;
|
||||||
|
name = "Jérémie Ferry";
|
||||||
|
};
|
||||||
mounium = {
|
mounium = {
|
||||||
email = "muoniurn@gmail.com";
|
email = "muoniurn@gmail.com";
|
||||||
github = "mounium";
|
github = "mounium";
|
||||||
@ -5482,6 +5563,12 @@
|
|||||||
githubId = 11016164;
|
githubId = 11016164;
|
||||||
name = "Fedor Pakhomov";
|
name = "Fedor Pakhomov";
|
||||||
};
|
};
|
||||||
|
paluh = {
|
||||||
|
email = "paluho@gmail.com";
|
||||||
|
github = "paluh";
|
||||||
|
githubId = 190249;
|
||||||
|
name = "Tomasz Rybarczyk";
|
||||||
|
};
|
||||||
pamplemousse = {
|
pamplemousse = {
|
||||||
email = "xav.maso@gmail.com";
|
email = "xav.maso@gmail.com";
|
||||||
github = "Pamplemousse";
|
github = "Pamplemousse";
|
||||||
@ -5755,11 +5842,10 @@
|
|||||||
github = "pradyuman";
|
github = "pradyuman";
|
||||||
githubId = 9904569;
|
githubId = 9904569;
|
||||||
name = "Pradyuman Vig";
|
name = "Pradyuman Vig";
|
||||||
keys = [
|
keys = [{
|
||||||
{ longkeyid = "rsa4096/4F74D5361C4CA31E";
|
longkeyid = "rsa4096/4F74D5361C4CA31E";
|
||||||
fingerprint = "240B 57DE 4271 2480 7CE3 EAC8 4F74 D536 1C4C A31E";
|
fingerprint = "240B 57DE 4271 2480 7CE3 EAC8 4F74 D536 1C4C A31E";
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
};
|
};
|
||||||
prikhi = {
|
prikhi = {
|
||||||
email = "pavan.rikhi@gmail.com";
|
email = "pavan.rikhi@gmail.com";
|
||||||
@ -5773,10 +5859,12 @@
|
|||||||
githubId = 7537109;
|
githubId = 7537109;
|
||||||
name = "Michael Weiss";
|
name = "Michael Weiss";
|
||||||
keys = [
|
keys = [
|
||||||
{ longkeyid = "ed25519/0x130826A6C2A389FD"; # Git only
|
{
|
||||||
|
longkeyid = "ed25519/0x130826A6C2A389FD"; # Git only
|
||||||
fingerprint = "86A7 4A55 07D0 58D1 322E 37FD 1308 26A6 C2A3 89FD";
|
fingerprint = "86A7 4A55 07D0 58D1 322E 37FD 1308 26A6 C2A3 89FD";
|
||||||
}
|
}
|
||||||
{ longkeyid = "rsa3072/0xBCA9943DD1DF4C04"; # Email, etc.
|
{
|
||||||
|
longkeyid = "rsa3072/0xBCA9943DD1DF4C04"; # Email, etc.
|
||||||
fingerprint = "AF85 991C C950 49A2 4205 1933 BCA9 943D D1DF 4C04";
|
fingerprint = "AF85 991C C950 49A2 4205 1933 BCA9 943D D1DF 4C04";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -5871,6 +5959,12 @@
|
|||||||
githubId = 4579165;
|
githubId = 4579165;
|
||||||
name = "Danny Bautista";
|
name = "Danny Bautista";
|
||||||
};
|
};
|
||||||
|
peelz = {
|
||||||
|
email = "peelz.dev+nixpkgs@gmail.com";
|
||||||
|
github = "louistakepillz";
|
||||||
|
githubId = 920910;
|
||||||
|
name = "peelz";
|
||||||
|
};
|
||||||
q3k = {
|
q3k = {
|
||||||
email = "q3k@q3k.org";
|
email = "q3k@q3k.org";
|
||||||
github = "q3k";
|
github = "q3k";
|
||||||
@ -6136,12 +6230,10 @@
|
|||||||
github = "rnhmjoj";
|
github = "rnhmjoj";
|
||||||
githubId = 2817565;
|
githubId = 2817565;
|
||||||
name = "Michele Guerini Rocco";
|
name = "Michele Guerini Rocco";
|
||||||
keys =
|
keys = [{
|
||||||
[
|
longkeyid = "ed25519/0xBFBAF4C975F76450";
|
||||||
{ longkeyid = "ed25519/0xBFBAF4C975F76450";
|
fingerprint = "92B2 904F D293 C94D C4C9 3E6B BFBA F4C9 75F7 6450";
|
||||||
fingerprint = "92B2 904F D293 C94D C4C9 3E6B BFBA F4C9 75F7 6450";
|
}];
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
rob = {
|
rob = {
|
||||||
email = "rob.vermaas@gmail.com";
|
email = "rob.vermaas@gmail.com";
|
||||||
@ -6346,10 +6438,10 @@
|
|||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
samrose = {
|
samrose = {
|
||||||
email = "samuel.rose@gmail.com";
|
email = "samuel.rose@gmail.com";
|
||||||
github = "samrose";
|
github = "samrose";
|
||||||
githubId = 115821;
|
githubId = 115821;
|
||||||
name = "Sam Rose";
|
name = "Sam Rose";
|
||||||
};
|
};
|
||||||
samueldr = {
|
samueldr = {
|
||||||
email = "samuel@dionne-riel.com";
|
email = "samuel@dionne-riel.com";
|
||||||
@ -6661,6 +6753,12 @@
|
|||||||
githubId = 848812;
|
githubId = 848812;
|
||||||
name = "Stephan Jau";
|
name = "Stephan Jau";
|
||||||
};
|
};
|
||||||
|
sjfloat = {
|
||||||
|
email = "steve+nixpkgs@jonescape.com";
|
||||||
|
github = "sjfloat";
|
||||||
|
githubId = 216167;
|
||||||
|
name = "Steve Jones";
|
||||||
|
};
|
||||||
sjmackenzie = {
|
sjmackenzie = {
|
||||||
email = "setori88@gmail.com";
|
email = "setori88@gmail.com";
|
||||||
github = "sjmackenzie";
|
github = "sjmackenzie";
|
||||||
@ -7219,6 +7317,12 @@
|
|||||||
githubId = 844343;
|
githubId = 844343;
|
||||||
name = "Thiago K. Okada";
|
name = "Thiago K. Okada";
|
||||||
};
|
};
|
||||||
|
thmzlt = {
|
||||||
|
email = "git@thomazleite.com";
|
||||||
|
github = "thmzlt";
|
||||||
|
githubId = 7709;
|
||||||
|
name = "Thomaz Leite";
|
||||||
|
};
|
||||||
ThomasMader = {
|
ThomasMader = {
|
||||||
email = "thomas.mader@gmail.com";
|
email = "thomas.mader@gmail.com";
|
||||||
github = "ThomasMader";
|
github = "ThomasMader";
|
||||||
@ -7294,10 +7398,10 @@
|
|||||||
github = "tkerber";
|
github = "tkerber";
|
||||||
githubId = 5722198;
|
githubId = 5722198;
|
||||||
name = "Thomas Kerber";
|
name = "Thomas Kerber";
|
||||||
keys = [ {
|
keys = [{
|
||||||
longkeyid = "rsa4096/0x8489B911F9ED617B";
|
longkeyid = "rsa4096/0x8489B911F9ED617B";
|
||||||
fingerprint = "556A 403F B0A2 D423 F656 3424 8489 B911 F9ED 617B";
|
fingerprint = "556A 403F B0A2 D423 F656 3424 8489 B911 F9ED 617B";
|
||||||
} ];
|
}];
|
||||||
};
|
};
|
||||||
tmplt = {
|
tmplt = {
|
||||||
email = "tmplt@dragons.rocks";
|
email = "tmplt@dragons.rocks";
|
||||||
@ -7577,7 +7681,8 @@
|
|||||||
};
|
};
|
||||||
vcunat = {
|
vcunat = {
|
||||||
name = "Vladimír Čunát";
|
name = "Vladimír Čunát";
|
||||||
email = "v@cunat.cz"; # vcunat@gmail.com predominated in commits before 2019/03
|
# vcunat@gmail.com predominated in commits before 2019/03
|
||||||
|
email = "v@cunat.cz";
|
||||||
github = "vcunat";
|
github = "vcunat";
|
||||||
githubId = 1785925;
|
githubId = 1785925;
|
||||||
keys = [{
|
keys = [{
|
||||||
|
@ -6,6 +6,7 @@ use warnings;
|
|||||||
|
|
||||||
use CPAN::Meta();
|
use CPAN::Meta();
|
||||||
use CPANPLUS::Backend();
|
use CPANPLUS::Backend();
|
||||||
|
use Module::CoreList;
|
||||||
use Getopt::Long::Descriptive qw( describe_options );
|
use Getopt::Long::Descriptive qw( describe_options );
|
||||||
use JSON::PP qw( encode_json );
|
use JSON::PP qw( encode_json );
|
||||||
use Log::Log4perl qw(:easy);
|
use Log::Log4perl qw(:easy);
|
||||||
@ -164,7 +165,7 @@ Readonly::Hash my %LICENSE_MAP => (
|
|||||||
|
|
||||||
# License not provided in metadata.
|
# License not provided in metadata.
|
||||||
unknown => {
|
unknown => {
|
||||||
licenses => [qw( unknown )],
|
licenses => [],
|
||||||
amb => 1
|
amb => 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -278,14 +279,8 @@ sub get_deps {
|
|||||||
foreach my $n ( $deps->required_modules ) {
|
foreach my $n ( $deps->required_modules ) {
|
||||||
next if $n eq "perl";
|
next if $n eq "perl";
|
||||||
|
|
||||||
# Figure out whether the module is a core module by attempting
|
my @core = Module::CoreList->find_modules(qr/^$n$/);
|
||||||
# to `use` the module in a pure Perl interpreter and checking
|
next if (@core);
|
||||||
# whether it succeeded. Note, $^X is a magic variable holding
|
|
||||||
# the path to the running Perl interpreter.
|
|
||||||
if ( system("env -i $^X -M$n -e1 >/dev/null 2>&1") == 0 ) {
|
|
||||||
DEBUG("skipping Perl-builtin module $n");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $pkg = module_to_pkg( $cb, $n );
|
my $pkg = module_to_pkg( $cb, $n );
|
||||||
|
|
||||||
|
33
maintainers/team-list.nix
Normal file
33
maintainers/team-list.nix
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* List of maintainer teams.
|
||||||
|
name = {
|
||||||
|
# Required
|
||||||
|
members = [ maintainer1 maintainer2 ];
|
||||||
|
scope = "Maintain foo packages.";
|
||||||
|
};
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
- `members` is the list of maintainers belonging to the group,
|
||||||
|
- `scope` describes the scope of the group.
|
||||||
|
|
||||||
|
More fields may be added in the future.
|
||||||
|
|
||||||
|
Please keep the list alphabetically sorted.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{ lib }:
|
||||||
|
with lib.maintainers; {
|
||||||
|
freedesktop = {
|
||||||
|
members = [ jtojnar worldofpeace ];
|
||||||
|
scope = "Maintain Freedesktop.org packages for graphical desktop.";
|
||||||
|
};
|
||||||
|
|
||||||
|
gnome = {
|
||||||
|
members = [
|
||||||
|
hedning
|
||||||
|
jtojnar
|
||||||
|
worldofpeace
|
||||||
|
];
|
||||||
|
scope = "Maintain GNOME desktop environment and platform.";
|
||||||
|
};
|
||||||
|
}
|
@ -21,7 +21,6 @@
|
|||||||
<xi:include href="xfce.xml" />
|
<xi:include href="xfce.xml" />
|
||||||
<xi:include href="networking.xml" />
|
<xi:include href="networking.xml" />
|
||||||
<xi:include href="linux-kernel.xml" />
|
<xi:include href="linux-kernel.xml" />
|
||||||
<xi:include href="matrix.xml" />
|
|
||||||
<xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" />
|
<xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" />
|
||||||
<xi:include href="profiles.xml" />
|
<xi:include href="profiles.xml" />
|
||||||
<xi:include href="kubernetes.xml" />
|
<xi:include href="kubernetes.xml" />
|
||||||
|
@ -154,7 +154,7 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
|
|||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The <literal>99-main.network</literal> file was removed. Maching all
|
The <literal>99-main.network</literal> file was removed. Matching all
|
||||||
network interfaces caused many breakages, see
|
network interfaces caused many breakages, see
|
||||||
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/18962">#18962</link>
|
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/18962">#18962</link>
|
||||||
and <link xlink:href="https://github.com/NixOS/nixpkgs/pull/71106">#71106</link>.
|
and <link xlink:href="https://github.com/NixOS/nixpkgs/pull/71106">#71106</link>.
|
||||||
@ -196,10 +196,10 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
|
|||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
There is now only one Xfce package-set and module. This means attributes, <literal>xfce4-14</literal>
|
There is now only one Xfce package-set and module. This means that attributes <literal>xfce4-14</literal>
|
||||||
<literal>xfce4-12</literal>, and <literal>xfceUnstable</literal> all now point to the latest Xfce 4.14
|
and <literal>xfceUnstable</literal> all now point to the latest Xfce 4.14
|
||||||
packages. And in future NixOS releases will be the latest released version of Xfce available at the
|
packages. And in the future NixOS releases will be the latest released version of Xfce available at the
|
||||||
time during the releases development (if viable).
|
time of the release's development (if viable).
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -235,7 +235,7 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
|
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
|
||||||
This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
|
This has led to drastically reduced closure sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
@ -641,6 +641,13 @@ auth required pam_succeed_if.so uid >= 1000 quiet
|
|||||||
The previous behavior can be restored by setting <literal>config.riot-web.conf = { disable_guests = false; piwik = true; }</literal>.
|
The previous behavior can be restored by setting <literal>config.riot-web.conf = { disable_guests = false; piwik = true; }</literal>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Stand-alone usage of <literal>Upower</literal> now requires
|
||||||
|
<option>services.upower.enable</option> instead of just installing into
|
||||||
|
<xref linkend="opt-environment.systemPackages"/>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -703,6 +710,72 @@ auth required pam_succeed_if.so uid >= 1000 quiet
|
|||||||
via <option>boot.initrd.luks.fido2Support</option>.
|
via <option>boot.initrd.luks.fido2Support</option>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Predicatbly named network-interfaces get renamed in stage-1. This means that it's possible
|
||||||
|
to use the proper interface name for e.g. dropbear-setups.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For further reference, please read <link xlink:href="https://github.com/NixOS/nixpkgs/pull/68953">#68953</link> or the corresponding <link xlink:href="https://discourse.nixos.org/t/predictable-network-interface-names-in-initrd/4055">discourse thread</link>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <package>matrix-synapse</package>-package has been updated to
|
||||||
|
<link xlink:href="https://github.com/matrix-org/synapse/releases/tag/v1.11.1">v1.11.1</link>.
|
||||||
|
Due to <link xlink:href="https://github.com/matrix-org/synapse/releases/tag/v1.10.0rc1">stricter requirements</link>
|
||||||
|
for database configuration when using <package>postgresql</package>, the automated database setup
|
||||||
|
of the module has been removed to avoid any further edge-cases.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<package>matrix-synapse</package> expects <literal>postgresql</literal>-databases to have the options
|
||||||
|
<literal>LC_COLLATE</literal> and <literal>LC_CTYPE</literal> set to
|
||||||
|
<link xlink:href="https://www.postgresql.org/docs/12/locale.html"><literal>'C'</literal></link> which basically
|
||||||
|
instructs <literal>postgresql</literal> to ignore any locale-based preferences.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Depending on your setup, you need to incorporate one of the following changes in your setup to
|
||||||
|
upgrade to 20.03:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>If you use <literal>sqlite3</literal> you don't need to do anything.</para></listitem>
|
||||||
|
<listitem><para>If you use <literal>postgresql</literal> on a different server, you don't need
|
||||||
|
to change anything as well since this module was never designed to configure remote databases.
|
||||||
|
</para></listitem>
|
||||||
|
<listitem><para>If you use <literal>postgresql</literal> and configured your synapse initially on
|
||||||
|
<literal>19.09</literal> or older, you simply need to enable <package>postgresql</package>-support
|
||||||
|
explicitly:
|
||||||
|
<programlisting>{ ... }: {
|
||||||
|
services.matrix-synapse = {
|
||||||
|
<link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
|
||||||
|
/* and all the other config you've defined here */
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.postgresql.enable">services.postgresql.enable</link> = true;
|
||||||
|
}</programlisting>
|
||||||
|
</para></listitem>
|
||||||
|
<listitem><para>If you deploy a fresh <package>matrix-synapse</package>, you need to configure
|
||||||
|
the database yourself (e.g. by using the
|
||||||
|
<link linkend="opt-services.postgresql.initialScript">services.postgresql.initialScript</link>
|
||||||
|
option). An example for this can be found in the
|
||||||
|
<link linkend="module-services-matrix">documentation of the Matrix module</link>.
|
||||||
|
</para></listitem>
|
||||||
|
<listitem><para>If you initially deployed your <package>matrix-synapse</package> on
|
||||||
|
<literal>nixos-unstable</literal> <emphasis>after</emphasis> the <literal>19.09</literal>-release,
|
||||||
|
your database is misconfigured due to a regression in NixOS. For now, <package>matrix-synapse</package> will
|
||||||
|
startup with a warning, but it's recommended to reconfigure the database to set the values
|
||||||
|
<literal>LC_COLLATE</literal> and <literal>LC_CTYPE</literal> to
|
||||||
|
<link xlink:href="https://www.postgresql.org/docs/12/locale.html"><literal>'C'</literal></link>.
|
||||||
|
</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <link linkend="opt-systemd.network.links">systemd.network.links</link> option is now respected
|
||||||
|
even when <link linkend="opt-systemd.network.enable">systemd-networkd</link> is disabled.
|
||||||
|
This mirrors the behaviour of systemd - It's udev that parses <literal>.link</literal> files,
|
||||||
|
not <command>systemd-networkd</command>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
@ -23,6 +23,20 @@
|
|||||||
Support is planned until the end of April 2021, handing over to 21.03.
|
Support is planned until the end of April 2021, handing over to 21.03.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
PHP now defaults to PHP 7.4, updated from 7.3.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Two new options, <link linkend="opt-services.openssh.authorizedKeysCommand">authorizedKeysCommand</link>
|
||||||
|
and <link linkend="opt-services.openssh.authorizedKeysCommandUser">authorizedKeysCommandUser</link>, have
|
||||||
|
been added to the <literal>openssh</literal> module. If you have <literal>AuthorizedKeysCommand</literal>
|
||||||
|
in your <link linkend="opt-services.openssh.extraConfig">services.openssh.extraConfig</link> you should
|
||||||
|
make use of these new options instead.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -72,6 +86,16 @@
|
|||||||
}</programlisting>
|
}</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal>
|
||||||
|
as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal>
|
||||||
|
is 20.09 or higher. It also enables number of
|
||||||
|
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link>
|
||||||
|
which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in
|
||||||
|
<option>systemd.services.supybot.serviceConfig</option>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -41,6 +41,12 @@ let
|
|||||||
# default to the argument. That way this new default could propagate all
|
# default to the argument. That way this new default could propagate all
|
||||||
# they way through, but has the last priority behind everything else.
|
# they way through, but has the last priority behind everything else.
|
||||||
nixpkgs.system = lib.mkDefault system;
|
nixpkgs.system = lib.mkDefault system;
|
||||||
|
|
||||||
|
# Stash the value of the `system` argument. When using `nesting.children`
|
||||||
|
# we want to have the same default value behavior (immediately above)
|
||||||
|
# without any interference from the user's configuration.
|
||||||
|
nixpkgs.initialSystem = system;
|
||||||
|
|
||||||
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
|
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -55,7 +61,7 @@ in rec {
|
|||||||
args = extraArgs;
|
args = extraArgs;
|
||||||
specialArgs =
|
specialArgs =
|
||||||
{ modulesPath = builtins.toString ../modules; } // specialArgs;
|
{ modulesPath = builtins.toString ../modules; } // specialArgs;
|
||||||
}) config options;
|
}) config options _module;
|
||||||
|
|
||||||
# These are the extra arguments passed to every module. In
|
# These are the extra arguments passed to every module. In
|
||||||
# particular, Nixpkgs is passed through the "pkgs" argument.
|
# particular, Nixpkgs is passed through the "pkgs" argument.
|
||||||
@ -63,5 +69,5 @@ in rec {
|
|||||||
inherit baseModules extraModules modules;
|
inherit baseModules extraModules modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit (config._module.args) pkgs;
|
inherit (_module.args) pkgs;
|
||||||
}
|
}
|
||||||
|
@ -175,13 +175,13 @@ in rec {
|
|||||||
|
|
||||||
nodeNames = builtins.attrNames nodes;
|
nodeNames = builtins.attrNames nodes;
|
||||||
invalidNodeNames = lib.filter
|
invalidNodeNames = lib.filter
|
||||||
(node: builtins.match "^[A-z_][A-z0-9_]+$" node == null) nodeNames;
|
(node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null) nodeNames;
|
||||||
|
|
||||||
in
|
in
|
||||||
if lib.length invalidNodeNames > 0 then
|
if lib.length invalidNodeNames > 0 then
|
||||||
throw ''
|
throw ''
|
||||||
Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
|
Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
|
||||||
All machines are referenced as perl variables in the testing framework which will break the
|
All machines are referenced as python variables in the testing framework which will break the
|
||||||
script when special characters are used.
|
script when special characters are used.
|
||||||
|
|
||||||
Please stick to alphanumeric chars and underscores as separation.
|
Please stick to alphanumeric chars and underscores as separation.
|
||||||
|
@ -14,7 +14,7 @@ rec {
|
|||||||
# becomes dev-xyzzy. FIXME: slow.
|
# becomes dev-xyzzy. FIXME: slow.
|
||||||
escapeSystemdPath = s:
|
escapeSystemdPath = s:
|
||||||
replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
|
replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
|
||||||
(if hasPrefix "/" s then substring 1 (stringLength s) s else s);
|
(removePrefix "/" s);
|
||||||
|
|
||||||
# Returns a system path for a given shell package
|
# Returns a system path for a given shell package
|
||||||
toShellPath = shell:
|
toShellPath = shell:
|
||||||
|
@ -18,7 +18,7 @@ state_dir=$HOME/amis/ec2-images
|
|||||||
home_region=eu-west-1
|
home_region=eu-west-1
|
||||||
bucket=nixos-amis
|
bucket=nixos-amis
|
||||||
|
|
||||||
regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1
|
regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1
|
||||||
us-east-1 us-east-2 us-west-1 us-west-2
|
us-east-1 us-east-2 us-west-1 us-west-2
|
||||||
ca-central-1
|
ca-central-1
|
||||||
ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2
|
ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2
|
||||||
|
@ -35,12 +35,22 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.hostFiles = lib.mkOption {
|
||||||
|
type = types.listOf types.path;
|
||||||
|
defaultText = lib.literalExample "Hosts from `networking.hosts` and `networking.extraHosts`";
|
||||||
|
example = lib.literalExample ''[ "''${pkgs.my-blocklist-package}/share/my-blocklist/hosts" ]'';
|
||||||
|
description = ''
|
||||||
|
Files that should be concatenated together to form <filename>/etc/hosts</filename>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
networking.extraHosts = lib.mkOption {
|
networking.extraHosts = lib.mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
example = "192.168.0.1 lanlocalhost";
|
example = "192.168.0.1 lanlocalhost";
|
||||||
description = ''
|
description = ''
|
||||||
Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
|
Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
|
||||||
|
For adding hosts from derivation results, use <option>networking.hostFiles</option> instead.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,6 +169,15 @@ in
|
|||||||
"::1" = [ "localhost" ];
|
"::1" = [ "localhost" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
networking.hostFiles = let
|
||||||
|
stringHosts =
|
||||||
|
let
|
||||||
|
oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip} + "\n";
|
||||||
|
allToString = set: concatMapStrings (oneToString set) (attrNames set);
|
||||||
|
in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) cfg.hosts));
|
||||||
|
extraHosts = pkgs.writeText "extra-hosts" cfg.extraHosts;
|
||||||
|
in mkBefore [ stringHosts extraHosts ];
|
||||||
|
|
||||||
environment.etc =
|
environment.etc =
|
||||||
{ # /etc/services: TCP/UDP port assignments.
|
{ # /etc/services: TCP/UDP port assignments.
|
||||||
services.source = pkgs.iana-etc + "/etc/services";
|
services.source = pkgs.iana-etc + "/etc/services";
|
||||||
@ -167,12 +186,8 @@ in
|
|||||||
protocols.source = pkgs.iana-etc + "/etc/protocols";
|
protocols.source = pkgs.iana-etc + "/etc/protocols";
|
||||||
|
|
||||||
# /etc/hosts: Hostname-to-IP mappings.
|
# /etc/hosts: Hostname-to-IP mappings.
|
||||||
hosts.text = let
|
hosts.source = pkgs.runCommandNoCC "hosts" {} ''
|
||||||
oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip};
|
cat ${escapeShellArgs cfg.hostFiles} > $out
|
||||||
allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set);
|
|
||||||
in ''
|
|
||||||
${allToString (filterAttrs (_: v: v != []) cfg.hosts)}
|
|
||||||
${cfg.extraHosts}
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# /etc/host.conf: resolver configuration file
|
# /etc/host.conf: resolver configuration file
|
||||||
|
@ -133,7 +133,7 @@ in
|
|||||||
tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
|
tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
|
||||||
firebird = 95;
|
firebird = 95;
|
||||||
#keys = 96; # unused
|
#keys = 96; # unused
|
||||||
#haproxy = 97; # DynamicUser as of 2019-11-08
|
#haproxy = 97; # dynamically allocated as of 2020-03-11
|
||||||
mongodb = 98;
|
mongodb = 98;
|
||||||
openldap = 99;
|
openldap = 99;
|
||||||
#users = 100; # unused
|
#users = 100; # unused
|
||||||
@ -448,7 +448,7 @@ in
|
|||||||
#tcpcryptd = 93; # unused
|
#tcpcryptd = 93; # unused
|
||||||
firebird = 95;
|
firebird = 95;
|
||||||
keys = 96;
|
keys = 96;
|
||||||
#haproxy = 97; # DynamicUser as of 2019-11-08
|
#haproxy = 97; # dynamically allocated as of 2020-03-11
|
||||||
#mongodb = 98; # unused
|
#mongodb = 98; # unused
|
||||||
openldap = 99;
|
openldap = 99;
|
||||||
munin = 102;
|
munin = 102;
|
||||||
|
@ -216,6 +216,14 @@ in
|
|||||||
Ignored when <code>nixpkgs.pkgs</code> is set.
|
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
initialSystem = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
internal = true;
|
||||||
|
description = ''
|
||||||
|
Preserved value of <literal>system</literal> passed to <literal>eval-config.nix</literal>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
@ -200,6 +200,7 @@
|
|||||||
./security/wrappers/default.nix
|
./security/wrappers/default.nix
|
||||||
./security/sudo.nix
|
./security/sudo.nix
|
||||||
./security/systemd-confinement.nix
|
./security/systemd-confinement.nix
|
||||||
|
./security/tpm2.nix
|
||||||
./services/admin/oxidized.nix
|
./services/admin/oxidized.nix
|
||||||
./services/admin/salt/master.nix
|
./services/admin/salt/master.nix
|
||||||
./services/admin/salt/minion.nix
|
./services/admin/salt/minion.nix
|
||||||
@ -247,9 +248,10 @@
|
|||||||
./services/cluster/kubernetes/proxy.nix
|
./services/cluster/kubernetes/proxy.nix
|
||||||
./services/cluster/kubernetes/scheduler.nix
|
./services/cluster/kubernetes/scheduler.nix
|
||||||
./services/computing/boinc/client.nix
|
./services/computing/boinc/client.nix
|
||||||
./services/computing/torque/server.nix
|
./services/computing/foldingathome/client.nix
|
||||||
./services/computing/torque/mom.nix
|
|
||||||
./services/computing/slurm/slurm.nix
|
./services/computing/slurm/slurm.nix
|
||||||
|
./services/computing/torque/mom.nix
|
||||||
|
./services/computing/torque/server.nix
|
||||||
./services/continuous-integration/buildbot/master.nix
|
./services/continuous-integration/buildbot/master.nix
|
||||||
./services/continuous-integration/buildbot/worker.nix
|
./services/continuous-integration/buildbot/worker.nix
|
||||||
./services/continuous-integration/buildkite-agents.nix
|
./services/continuous-integration/buildkite-agents.nix
|
||||||
@ -297,6 +299,7 @@
|
|||||||
./services/desktops/geoclue2.nix
|
./services/desktops/geoclue2.nix
|
||||||
./services/desktops/gsignond.nix
|
./services/desktops/gsignond.nix
|
||||||
./services/desktops/gvfs.nix
|
./services/desktops/gvfs.nix
|
||||||
|
./services/desktops/malcontent.nix
|
||||||
./services/desktops/pipewire.nix
|
./services/desktops/pipewire.nix
|
||||||
./services/desktops/gnome3/at-spi2-core.nix
|
./services/desktops/gnome3/at-spi2-core.nix
|
||||||
./services/desktops/gnome3/chrome-gnome-shell.nix
|
./services/desktops/gnome3/chrome-gnome-shell.nix
|
||||||
@ -405,6 +408,7 @@
|
|||||||
./services/mail/sympa.nix
|
./services/mail/sympa.nix
|
||||||
./services/mail/nullmailer.nix
|
./services/mail/nullmailer.nix
|
||||||
./services/misc/airsonic.nix
|
./services/misc/airsonic.nix
|
||||||
|
./services/misc/ankisyncd.nix
|
||||||
./services/misc/apache-kafka.nix
|
./services/misc/apache-kafka.nix
|
||||||
./services/misc/autofs.nix
|
./services/misc/autofs.nix
|
||||||
./services/misc/autorandr.nix
|
./services/misc/autorandr.nix
|
||||||
@ -430,7 +434,6 @@
|
|||||||
./services/misc/ethminer.nix
|
./services/misc/ethminer.nix
|
||||||
./services/misc/exhibitor.nix
|
./services/misc/exhibitor.nix
|
||||||
./services/misc/felix.nix
|
./services/misc/felix.nix
|
||||||
./services/misc/folding-at-home.nix
|
|
||||||
./services/misc/freeswitch.nix
|
./services/misc/freeswitch.nix
|
||||||
./services/misc/fstrim.nix
|
./services/misc/fstrim.nix
|
||||||
./services/misc/gammu-smsd.nix
|
./services/misc/gammu-smsd.nix
|
||||||
@ -660,6 +663,7 @@
|
|||||||
./services/networking/ngircd.nix
|
./services/networking/ngircd.nix
|
||||||
./services/networking/nghttpx/default.nix
|
./services/networking/nghttpx/default.nix
|
||||||
./services/networking/nix-serve.nix
|
./services/networking/nix-serve.nix
|
||||||
|
./services/networking/nix-store-gcs-proxy.nix
|
||||||
./services/networking/nixops-dns.nix
|
./services/networking/nixops-dns.nix
|
||||||
./services/networking/nntp-proxy.nix
|
./services/networking/nntp-proxy.nix
|
||||||
./services/networking/nsd.nix
|
./services/networking/nsd.nix
|
||||||
@ -706,6 +710,7 @@
|
|||||||
./services/networking/shorewall6.nix
|
./services/networking/shorewall6.nix
|
||||||
./services/networking/shout.nix
|
./services/networking/shout.nix
|
||||||
./services/networking/sniproxy.nix
|
./services/networking/sniproxy.nix
|
||||||
|
./services/networking/smartdns.nix
|
||||||
./services/networking/smokeping.nix
|
./services/networking/smokeping.nix
|
||||||
./services/networking/softether.nix
|
./services/networking/softether.nix
|
||||||
./services/networking/spacecookie.nix
|
./services/networking/spacecookie.nix
|
||||||
@ -723,6 +728,7 @@
|
|||||||
./services/networking/syncthing.nix
|
./services/networking/syncthing.nix
|
||||||
./services/networking/syncthing-relay.nix
|
./services/networking/syncthing-relay.nix
|
||||||
./services/networking/syncplay.nix
|
./services/networking/syncplay.nix
|
||||||
|
./services/networking/tailscale.nix
|
||||||
./services/networking/tcpcrypt.nix
|
./services/networking/tcpcrypt.nix
|
||||||
./services/networking/teamspeak3.nix
|
./services/networking/teamspeak3.nix
|
||||||
./services/networking/tedicross.nix
|
./services/networking/tedicross.nix
|
||||||
@ -807,6 +813,7 @@
|
|||||||
./services/ttys/agetty.nix
|
./services/ttys/agetty.nix
|
||||||
./services/ttys/gpm.nix
|
./services/ttys/gpm.nix
|
||||||
./services/ttys/kmscon.nix
|
./services/ttys/kmscon.nix
|
||||||
|
./services/wayland/cage.nix
|
||||||
./services/web-apps/atlassian/confluence.nix
|
./services/web-apps/atlassian/confluence.nix
|
||||||
./services/web-apps/atlassian/crowd.nix
|
./services/web-apps/atlassian/crowd.nix
|
||||||
./services/web-apps/atlassian/jira.nix
|
./services/web-apps/atlassian/jira.nix
|
||||||
|
@ -5,28 +5,34 @@ with lib;
|
|||||||
let
|
let
|
||||||
cfg = config.programs.firejail;
|
cfg = config.programs.firejail;
|
||||||
|
|
||||||
wrappedBins = pkgs.stdenv.mkDerivation {
|
wrappedBins = pkgs.runCommand "firejail-wrapped-binaries"
|
||||||
name = "firejail-wrapped-binaries";
|
{ preferLocalBuild = true;
|
||||||
nativeBuildInputs = with pkgs; [ makeWrapper ];
|
allowSubstitutes = false;
|
||||||
buildCommand = ''
|
}
|
||||||
|
''
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: binary: ''
|
${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: binary: ''
|
||||||
cat <<_EOF >$out/bin/${command}
|
cat <<_EOF >$out/bin/${command}
|
||||||
#!${pkgs.stdenv.shell} -e
|
#! ${pkgs.runtimeShell} -e
|
||||||
/run/wrappers/bin/firejail ${binary} "\$@"
|
exec /run/wrappers/bin/firejail ${binary} "\$@"
|
||||||
_EOF
|
_EOF
|
||||||
chmod 0755 $out/bin/${command}
|
chmod 0755 $out/bin/${command}
|
||||||
'') cfg.wrappedBinaries)}
|
'') cfg.wrappedBinaries)}
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
|
|
||||||
in {
|
in {
|
||||||
options.programs.firejail = {
|
options.programs.firejail = {
|
||||||
enable = mkEnableOption "firejail";
|
enable = mkEnableOption "firejail";
|
||||||
|
|
||||||
wrappedBinaries = mkOption {
|
wrappedBinaries = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrsOf types.path;
|
||||||
default = {};
|
default = {};
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
firefox = "''${lib.getBin pkgs.firefox}/bin/firefox";
|
||||||
|
mpv = "''${lib.getBin pkgs.mpv}/bin/mpv";
|
||||||
|
}
|
||||||
|
'';
|
||||||
description = ''
|
description = ''
|
||||||
Wrap the binaries in firejail and place them in the global path.
|
Wrap the binaries in firejail and place them in the global path.
|
||||||
</para>
|
</para>
|
||||||
@ -41,7 +47,7 @@ in {
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
|
security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
|
||||||
|
|
||||||
environment.systemPackages = [ wrappedBins ];
|
environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with maintainers; [ peterhoeg ];
|
meta.maintainers = with maintainers; [ peterhoeg ];
|
||||||
|
@ -21,12 +21,12 @@ with lib;
|
|||||||
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "group" ] "")
|
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "group" ] "")
|
||||||
(mkRemovedOptionModule [ "services" "winstone" ] "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" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||||
(mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
|
(mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
|
||||||
(mkRemovedOptionModule [ "services.beegfsEnable" ] "The BeeGFS module has been removed")
|
(mkRemovedOptionModule [ "services" "beegfsEnable" ] "The BeeGFS module has been removed")
|
||||||
(mkRemovedOptionModule [ "services.beegfs" ] "The BeeGFS module has been removed")
|
(mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
|
||||||
(mkRemovedOptionModule [ "services.osquery" ] "The osquery module has been removed")
|
(mkRemovedOptionModule [ "services" "osquery" ] "The osquery module has been removed")
|
||||||
(mkRemovedOptionModule [ "services.fourStore" ] "The fourStore module has been removed")
|
(mkRemovedOptionModule [ "services" "fourStore" ] "The fourStore module has been removed")
|
||||||
(mkRemovedOptionModule [ "services.fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
|
(mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
|
||||||
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
|
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
|
||||||
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
|
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
|
||||||
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
|
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
|
||||||
|
@ -136,6 +136,27 @@ let
|
|||||||
challenge to ensure the DNS entries required are available.
|
challenge to ensure the DNS entries required are available.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ocspMustStaple = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Turns on the OCSP Must-Staple TLS extension.
|
||||||
|
Make sure you know what you're doing! See:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><link xlink:href="https://blog.apnic.net/2019/01/15/is-the-web-ready-for-ocsp-must-staple/" /></para></listitem>
|
||||||
|
<listitem><para><link xlink:href="https://blog.hboeck.de/archives/886-The-Problem-with-OCSP-Stapling-and-Must-Staple-and-why-Certificate-Revocation-is-still-broken.html" /></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraLegoRenewFlags = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Additional flags to pass to lego renew.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,7 +195,7 @@ in
|
|||||||
|
|
||||||
renewInterval = mkOption {
|
renewInterval = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "weekly";
|
default = "daily";
|
||||||
description = ''
|
description = ''
|
||||||
Systemd calendar expression when to check for renewal. See
|
Systemd calendar expression when to check for renewal. See
|
||||||
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||||
@ -281,15 +302,18 @@ in
|
|||||||
lpath = "acme/${cert}";
|
lpath = "acme/${cert}";
|
||||||
apath = "/var/lib/${lpath}";
|
apath = "/var/lib/${lpath}";
|
||||||
spath = "/var/lib/acme/.lego";
|
spath = "/var/lib/acme/.lego";
|
||||||
rights = if data.allowKeysForGroup then "750" else "700";
|
fileMode = if data.allowKeysForGroup then "640" else "600";
|
||||||
globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
|
globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
|
||||||
++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
|
++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
|
||||||
++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
|
++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
|
||||||
++ concatLists (mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
|
++ concatLists (mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
|
||||||
++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" data.webroot ])
|
++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" data.webroot ])
|
||||||
++ optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
|
++ optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
|
||||||
runOpts = escapeShellArgs (globalOpts ++ [ "run" ]);
|
certOpts = optionals data.ocspMustStaple [ "--must-staple" ];
|
||||||
renewOpts = escapeShellArgs (globalOpts ++ [ "renew" "--days" (toString cfg.validMinDays) ]);
|
runOpts = escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts);
|
||||||
|
renewOpts = escapeShellArgs (globalOpts ++
|
||||||
|
[ "renew" "--days" (toString cfg.validMinDays) ] ++
|
||||||
|
certOpts ++ data.extraLegoRenewFlags);
|
||||||
acmeService = {
|
acmeService = {
|
||||||
description = "Renew ACME Certificate for ${cert}";
|
description = "Renew ACME Certificate for ${cert}";
|
||||||
after = [ "network.target" "network-online.target" ];
|
after = [ "network.target" "network-online.target" ];
|
||||||
@ -307,7 +331,7 @@ in
|
|||||||
Group = data.group;
|
Group = data.group;
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
StateDirectory = "acme/.lego ${lpath}";
|
StateDirectory = "acme/.lego ${lpath}";
|
||||||
StateDirectoryMode = rights;
|
StateDirectoryMode = if data.allowKeysForGroup then "750" else "700";
|
||||||
WorkingDirectory = spath;
|
WorkingDirectory = spath;
|
||||||
# Only try loading the credentialsFile if the dns challenge is enabled
|
# Only try loading the credentialsFile if the dns challenge is enabled
|
||||||
EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null;
|
EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null;
|
||||||
@ -328,12 +352,13 @@ in
|
|||||||
cp -p ${spath}/certificates/${keyName}.key key.pem
|
cp -p ${spath}/certificates/${keyName}.key key.pem
|
||||||
cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
|
cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
|
||||||
cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
|
cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
|
||||||
ln -s fullchain.pem cert.pem
|
ln -sf fullchain.pem cert.pem
|
||||||
cat key.pem fullchain.pem > full.pem
|
cat key.pem fullchain.pem > full.pem
|
||||||
chmod ${rights} *.pem
|
|
||||||
chown '${data.user}:${data.group}' *.pem
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
chmod ${fileMode} *.pem
|
||||||
|
chown '${data.user}:${data.group}' *.pem
|
||||||
|
|
||||||
${data.postRun}
|
${data.postRun}
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
@ -375,7 +400,7 @@ in
|
|||||||
|
|
||||||
# Give key acme permissions
|
# Give key acme permissions
|
||||||
chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem
|
chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem
|
||||||
chmod ${rights} "${apath}/"{key,fullchain,full}.pem
|
chmod ${fileMode} "${apath}/"{key,fullchain,full}.pem
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
@ -400,7 +425,17 @@ in
|
|||||||
systemd.tmpfiles.rules =
|
systemd.tmpfiles.rules =
|
||||||
map (data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}") (filter (data: data.webroot != null) (attrValues cfg.certs));
|
map (data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}") (filter (data: data.webroot != null) (attrValues cfg.certs));
|
||||||
|
|
||||||
systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
|
systemd.timers = let
|
||||||
|
# Allow systemd to pick a convenient time within the day
|
||||||
|
# to run the check.
|
||||||
|
# This allows the coalescing of multiple timer jobs.
|
||||||
|
# We divide by the number of certificates so that if you
|
||||||
|
# have many certificates, the renewals are distributed over
|
||||||
|
# the course of the day to avoid rate limits.
|
||||||
|
numCerts = length (attrNames cfg.certs);
|
||||||
|
_24hSecs = 60 * 60 * 24;
|
||||||
|
AccuracySec = "${toString (_24hSecs / numCerts)}s";
|
||||||
|
in flip mapAttrs' cfg.certs (cert: data: nameValuePair
|
||||||
("acme-${cert}")
|
("acme-${cert}")
|
||||||
({
|
({
|
||||||
description = "Renew ACME Certificate for ${cert}";
|
description = "Renew ACME Certificate for ${cert}";
|
||||||
@ -409,8 +444,9 @@ in
|
|||||||
OnCalendar = cfg.renewInterval;
|
OnCalendar = cfg.renewInterval;
|
||||||
Unit = "acme-${cert}.service";
|
Unit = "acme-${cert}.service";
|
||||||
Persistent = "yes";
|
Persistent = "yes";
|
||||||
AccuracySec = "5m";
|
inherit AccuracySec;
|
||||||
RandomizedDelaySec = "1h";
|
# Skew randomly within the day, per https://letsencrypt.org/docs/integration-guide/.
|
||||||
|
RandomizedDelaySec = "24h";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -59,10 +59,8 @@ in
|
|||||||
exec ${package}/bin/google_authorized_keys "$@"
|
exec ${package}/bin/google_authorized_keys "$@"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
services.openssh.extraConfig = ''
|
services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command_google_oslogin %u";
|
||||||
AuthorizedKeysCommand /etc/ssh/authorized_keys_command_google_oslogin %u
|
services.openssh.authorizedKeysCommandUser = "nobody";
|
||||||
AuthorizedKeysCommandUser nobody
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
185
nixos/modules/security/tpm2.nix
Normal file
185
nixos/modules/security/tpm2.nix
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
{ lib, pkgs, config, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.security.tpm2;
|
||||||
|
|
||||||
|
# This snippet is taken from tpm2-tss/dist/tpm-udev.rules, but modified to allow custom user/groups
|
||||||
|
# The idea is that the tssUser is allowed to acess the TPM and kernel TPM resource manager, while
|
||||||
|
# the tssGroup is only allowed to access the kernel resource manager
|
||||||
|
# Therefore, if either of the two are null, the respective part isn't generated
|
||||||
|
udevRules = tssUser: tssGroup: ''
|
||||||
|
${lib.optionalString (tssUser != null) ''KERNEL=="tpm[0-9]*", MODE="0660", OWNER="${tssUser}"''}
|
||||||
|
${lib.optionalString (tssUser != null || tssGroup != null)
|
||||||
|
''KERNEL=="tpmrm[0-9]*", MODE="0660"''
|
||||||
|
+ lib.optionalString (tssUser != null) '', OWNER="${tssUser}"''
|
||||||
|
+ lib.optionalString (tssGroup != null) '', GROUP="${tssGroup}"''
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in {
|
||||||
|
options.security.tpm2 = {
|
||||||
|
enable = lib.mkEnableOption "Trusted Platform Module 2 support";
|
||||||
|
|
||||||
|
tssUser = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Name of the tpm device-owner and service user, set if applyUdevRules is
|
||||||
|
set.
|
||||||
|
'';
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = if cfg.abrmd.enable then "tss" else "root";
|
||||||
|
defaultText = ''"tss" when using the userspace resource manager,'' +
|
||||||
|
''"root" otherwise'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tssGroup = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Group of the tpm kernel resource manager (tpmrm) device-group, set if
|
||||||
|
applyUdevRules is set.
|
||||||
|
'';
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = "tss";
|
||||||
|
};
|
||||||
|
|
||||||
|
applyUdevRules = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Whether to make the /dev/tpm[0-9] devices accessible by the tssUser, or
|
||||||
|
the /dev/tpmrm[0-9] by tssGroup respectively
|
||||||
|
'';
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
abrmd = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
Trusted Platform 2 userspace resource manager daemon
|
||||||
|
'';
|
||||||
|
|
||||||
|
package = lib.mkOption {
|
||||||
|
description = "tpm2-abrmd package to use";
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.tpm2-abrmd;
|
||||||
|
defaultText = "pkgs.tpm2-abrmd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pkcs11 = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
TPM2 PKCS#11 tool and shared library in system path
|
||||||
|
(<literal>/run/current-system/sw/lib/libtpm2_pkcs11.so</literal>)
|
||||||
|
'';
|
||||||
|
|
||||||
|
package = lib.mkOption {
|
||||||
|
description = "tpm2-pkcs11 package to use";
|
||||||
|
type = lib.types.package;
|
||||||
|
default = pkgs.tpm2-pkcs11;
|
||||||
|
defaultText = "pkgs.tpm2-pkcs11";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
tctiEnvironment = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Set common TCTI environment variables to the specified value.
|
||||||
|
The variables are
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>TPM2TOOLS_TCTI</literal>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>TPM2_PKCS11_TCTI</literal>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
'';
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
The name of the TPM command transmission interface (TCTI) library to
|
||||||
|
use.
|
||||||
|
'';
|
||||||
|
type = lib.types.enum [ "tabrmd" "device" ];
|
||||||
|
default = "device";
|
||||||
|
};
|
||||||
|
|
||||||
|
deviceConf = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Configuration part of the device TCTI, e.g. the path to the TPM device.
|
||||||
|
Applies if interface is set to "device".
|
||||||
|
The format is specified in the
|
||||||
|
<link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
|
||||||
|
tpm2-tools repository</link>.
|
||||||
|
'';
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "/dev/tpmrm0";
|
||||||
|
};
|
||||||
|
|
||||||
|
tabrmdConf = lib.mkOption {
|
||||||
|
description = ''
|
||||||
|
Configuration part of the tabrmd TCTI, like the D-Bus bus name.
|
||||||
|
Applies if interface is set to "tabrmd".
|
||||||
|
The format is specified in the
|
||||||
|
<link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
|
||||||
|
tpm2-tools repository</link>.
|
||||||
|
'';
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "bus_name=com.intel.tss2.Tabrmd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
{
|
||||||
|
# PKCS11 tools and library
|
||||||
|
environment.systemPackages = lib.mkIf cfg.pkcs11.enable [
|
||||||
|
(lib.getBin cfg.pkcs11.package)
|
||||||
|
(lib.getLib cfg.pkcs11.package)
|
||||||
|
];
|
||||||
|
|
||||||
|
services.udev.extraRules = lib.mkIf cfg.applyUdevRules
|
||||||
|
(udevRules cfg.tssUser cfg.tssGroup);
|
||||||
|
|
||||||
|
# Create the tss user and group only if the default value is used
|
||||||
|
users.users.${cfg.tssUser} = lib.mkIf (cfg.tssUser == "tss") {
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
users.groups.${cfg.tssGroup} = lib.mkIf (cfg.tssGroup == "tss") {};
|
||||||
|
|
||||||
|
environment.variables = lib.mkIf cfg.tctiEnvironment.enable (
|
||||||
|
lib.attrsets.genAttrs [
|
||||||
|
"TPM2TOOLS_TCTI"
|
||||||
|
"TPM2_PKCS11_TCTI"
|
||||||
|
] (_: ''${cfg.tctiEnvironment.interface}:${
|
||||||
|
if cfg.tctiEnvironment.interface == "tabrmd" then
|
||||||
|
cfg.tctiEnvironment.tabrmdConf
|
||||||
|
else
|
||||||
|
cfg.tctiEnvironment.deviceConf
|
||||||
|
}'')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(lib.mkIf cfg.abrmd.enable {
|
||||||
|
systemd.services."tpm2-abrmd" = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "dbus";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 30;
|
||||||
|
BusName = "com.intel.tss2.Tabrmd";
|
||||||
|
StandardOutput = "syslog";
|
||||||
|
ExecStart = "${cfg.abrmd.package}/bin/tpm2-abrmd";
|
||||||
|
User = "tss";
|
||||||
|
Group = "nogroup";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.dbus.packages = lib.singleton cfg.abrmd.package;
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
|
meta.maintainers = with lib.maintainers; [ lschuermann ];
|
||||||
|
}
|
81
nixos/modules/services/computing/foldingathome/client.nix
Normal file
81
nixos/modules/services/computing/foldingathome/client.nix
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.foldingathome;
|
||||||
|
|
||||||
|
args =
|
||||||
|
["--team" "${toString cfg.team}"]
|
||||||
|
++ lib.optionals (cfg.user != null) ["--user" cfg.user]
|
||||||
|
++ cfg.extraArgs
|
||||||
|
;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(mkRenamedOptionModule [ "services" "foldingAtHome" ] [ "services" "foldingathome" ])
|
||||||
|
(mkRenamedOptionModule [ "services" "foldingathome" "nickname" ] [ "services" "foldingathome" "user" ])
|
||||||
|
(mkRemovedOptionModule [ "services" "foldingathome" "config" ] ''
|
||||||
|
Use <literal>services.foldingathome.extraArgs instead<literal>
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
options.services.foldingathome = {
|
||||||
|
enable = mkEnableOption "Enable the Folding@home client";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.fahclient;
|
||||||
|
defaultText = "pkgs.fahclient";
|
||||||
|
description = ''
|
||||||
|
Which Folding@home client to use.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The user associated with the reported computation results. This will
|
||||||
|
be used in the ranking statistics.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
team = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 236565;
|
||||||
|
description = ''
|
||||||
|
The team ID associated with the reported computation results. This
|
||||||
|
will be used in the ranking statistics.
|
||||||
|
|
||||||
|
By default, use the NixOS folding@home team ID is being used.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraArgs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Extra startup options for the FAHClient. Run
|
||||||
|
<literal>FAHClient --help</literal> to find all the available options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.foldingathome = {
|
||||||
|
description = "Folding@home client";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
script = ''
|
||||||
|
exec ${cfg.package}/bin/FAHClient ${lib.escapeShellArgs args}
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = true;
|
||||||
|
StateDirectory = "foldingathome";
|
||||||
|
WorkingDirectory = "%S/foldingathome";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
maintainers = with lib.maintainers; [ zimbatm ];
|
||||||
|
};
|
||||||
|
}
|
@ -21,6 +21,11 @@ let
|
|||||||
installOptions =
|
installOptions =
|
||||||
"${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}";
|
"${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}";
|
||||||
|
|
||||||
|
settingsFile = pkgs.writeText "my.cnf" (
|
||||||
|
generators.toINI { listsAsDuplicateKeys = true; } cfg.settings +
|
||||||
|
optionalString (cfg.extraOptions != null) "[mysqld]\n${cfg.extraOptions}"
|
||||||
|
);
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -76,9 +81,64 @@ in
|
|||||||
description = "Location where MySQL stores its table files";
|
description = "Location where MySQL stores its table files";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
configFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = settingsFile;
|
||||||
|
defaultText = "settingsFile";
|
||||||
|
description = ''
|
||||||
|
Override the configuration file used by MySQL. By default,
|
||||||
|
NixOS generates one automatically from <option>services.mysql.settings</option>.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
pkgs.writeText "my.cnf" '''
|
||||||
|
[mysqld]
|
||||||
|
datadir = /var/lib/mysql
|
||||||
|
bind-address = 127.0.0.1
|
||||||
|
port = 3336
|
||||||
|
plugin-load-add = auth_socket.so
|
||||||
|
|
||||||
|
!includedir /etc/mysql/conf.d/
|
||||||
|
''';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = with types; attrsOf (attrsOf (oneOf [ bool int str (listOf str) ]));
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
MySQL configuration. Refer to
|
||||||
|
<link xlink:href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html"/>,
|
||||||
|
<link xlink:href="https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html"/>,
|
||||||
|
and <link xlink:href="https://mariadb.com/kb/en/server-system-variables/"/>
|
||||||
|
for details on supported values.
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
MySQL configuration options such as <literal>--quick</literal> should be treated as
|
||||||
|
boolean options and provided values such as <literal>true</literal>, <literal>false</literal>,
|
||||||
|
<literal>1</literal>, or <literal>0</literal>. See the provided example below.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
mysqld = {
|
||||||
|
key_buffer_size = "6G";
|
||||||
|
table_cache = 1600;
|
||||||
|
log-error = "/var/log/mysql_err.log";
|
||||||
|
plugin-load-add = [ "server_audit" "ed25519=auth_ed25519" ];
|
||||||
|
};
|
||||||
|
mysqldump = {
|
||||||
|
quick = true;
|
||||||
|
max_allowed_packet = "16M";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraOptions = mkOption {
|
extraOptions = mkOption {
|
||||||
type = types.lines;
|
type = with types; nullOr lines;
|
||||||
default = "";
|
default = null;
|
||||||
example = ''
|
example = ''
|
||||||
key_buffer_size = 6G
|
key_buffer_size = 6G
|
||||||
table_cache = 1600
|
table_cache = 1600
|
||||||
@ -252,10 +312,27 @@ in
|
|||||||
|
|
||||||
config = mkIf config.services.mysql.enable {
|
config = mkIf config.services.mysql.enable {
|
||||||
|
|
||||||
|
warnings = optional (cfg.extraOptions != null) "services.mysql.`extraOptions` is deprecated, please use services.mysql.`settings`.";
|
||||||
|
|
||||||
services.mysql.dataDir =
|
services.mysql.dataDir =
|
||||||
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
|
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
|
||||||
else "/var/mysql");
|
else "/var/mysql");
|
||||||
|
|
||||||
|
services.mysql.settings.mysqld = mkMerge [
|
||||||
|
{
|
||||||
|
datadir = cfg.dataDir;
|
||||||
|
bind-address = mkIf (cfg.bind != null) cfg.bind;
|
||||||
|
port = cfg.port;
|
||||||
|
plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so";
|
||||||
|
}
|
||||||
|
(mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") {
|
||||||
|
log-bin = "mysql-bin-${toString cfg.replication.serverId}";
|
||||||
|
log-bin-index = "mysql-bin-${toString cfg.replication.serverId}.index";
|
||||||
|
relay-log = "mysql-relay-bin";
|
||||||
|
server-id = cfg.replication.serverId;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
users.users.mysql = {
|
users.users.mysql = {
|
||||||
description = "MySQL server user";
|
description = "MySQL server user";
|
||||||
group = "mysql";
|
group = "mysql";
|
||||||
@ -266,25 +343,7 @@ in
|
|||||||
|
|
||||||
environment.systemPackages = [mysql];
|
environment.systemPackages = [mysql];
|
||||||
|
|
||||||
environment.etc."my.cnf".text =
|
environment.etc."my.cnf".source = cfg.configFile;
|
||||||
''
|
|
||||||
[mysqld]
|
|
||||||
port = ${toString cfg.port}
|
|
||||||
datadir = ${cfg.dataDir}
|
|
||||||
${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" }
|
|
||||||
${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave")
|
|
||||||
''
|
|
||||||
log-bin=mysql-bin-${toString cfg.replication.serverId}
|
|
||||||
log-bin-index=mysql-bin-${toString cfg.replication.serverId}.index
|
|
||||||
relay-log=mysql-relay-bin
|
|
||||||
server-id = ${toString cfg.replication.serverId}
|
|
||||||
''}
|
|
||||||
${optionalString (cfg.ensureUsers != [])
|
|
||||||
''
|
|
||||||
plugin-load-add = auth_socket.so
|
|
||||||
''}
|
|
||||||
${cfg.extraOptions}
|
|
||||||
'';
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules = [
|
systemd.tmpfiles.rules = [
|
||||||
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
|
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
|
||||||
@ -297,7 +356,7 @@ in
|
|||||||
|
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
restartTriggers = [ config.environment.etc."my.cnf".source ];
|
restartTriggers = [ cfg.configFile ];
|
||||||
|
|
||||||
unitConfig.RequiresMountsFor = "${cfg.dataDir}";
|
unitConfig.RequiresMountsFor = "${cfg.dataDir}";
|
||||||
|
|
||||||
|
32
nixos/modules/services/desktops/malcontent.nix
Normal file
32
nixos/modules/services/desktops/malcontent.nix
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Malcontent daemon.
|
||||||
|
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.malcontent = {
|
||||||
|
|
||||||
|
enable = mkEnableOption "Malcontent";
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf config.services.malcontent.enable {
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.malcontent ];
|
||||||
|
|
||||||
|
services.dbus.packages = [ pkgs.malcontent ];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -14,18 +14,34 @@ let
|
|||||||
base_dir = ${baseDir}
|
base_dir = ${baseDir}
|
||||||
protocols = ${concatStringsSep " " cfg.protocols}
|
protocols = ${concatStringsSep " " cfg.protocols}
|
||||||
sendmail_path = /run/wrappers/bin/sendmail
|
sendmail_path = /run/wrappers/bin/sendmail
|
||||||
|
# defining mail_plugins must be done before the first protocol {} filter because of https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion
|
||||||
|
mail_plugins = $mail_plugins ${concatStringsSep " " cfg.mailPlugins.globally.enable}
|
||||||
''
|
''
|
||||||
|
|
||||||
(if cfg.sslServerCert == null then ''
|
(
|
||||||
ssl = no
|
concatStringsSep "\n" (
|
||||||
disable_plaintext_auth = no
|
mapAttrsToList (
|
||||||
'' else ''
|
protocol: plugins: ''
|
||||||
ssl_cert = <${cfg.sslServerCert}
|
protocol ${protocol} {
|
||||||
ssl_key = <${cfg.sslServerKey}
|
mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable}
|
||||||
${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
|
}
|
||||||
ssl_dh = <${config.security.dhparams.params.dovecot2.path}
|
''
|
||||||
disable_plaintext_auth = yes
|
) cfg.mailPlugins.perProtocol
|
||||||
'')
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
if cfg.sslServerCert == null then ''
|
||||||
|
ssl = no
|
||||||
|
disable_plaintext_auth = no
|
||||||
|
'' else ''
|
||||||
|
ssl_cert = <${cfg.sslServerCert}
|
||||||
|
ssl_key = <${cfg.sslServerKey}
|
||||||
|
${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
|
||||||
|
ssl_dh = <${config.security.dhparams.params.dovecot2.path}
|
||||||
|
disable_plaintext_auth = yes
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
''
|
''
|
||||||
default_internal_user = ${cfg.user}
|
default_internal_user = ${cfg.user}
|
||||||
@ -45,55 +61,58 @@ let
|
|||||||
}
|
}
|
||||||
''
|
''
|
||||||
|
|
||||||
(optionalString cfg.enablePAM ''
|
(
|
||||||
userdb {
|
optionalString cfg.enablePAM ''
|
||||||
driver = passwd
|
userdb {
|
||||||
}
|
driver = passwd
|
||||||
|
|
||||||
passdb {
|
|
||||||
driver = pam
|
|
||||||
args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
|
|
||||||
}
|
|
||||||
'')
|
|
||||||
|
|
||||||
(optionalString (cfg.sieveScripts != {}) ''
|
|
||||||
plugin {
|
|
||||||
${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
|
|
||||||
}
|
|
||||||
'')
|
|
||||||
|
|
||||||
(optionalString (cfg.mailboxes != []) ''
|
|
||||||
protocol imap {
|
|
||||||
namespace inbox {
|
|
||||||
inbox=yes
|
|
||||||
${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
'')
|
|
||||||
|
|
||||||
(optionalString cfg.enableQuota ''
|
passdb {
|
||||||
mail_plugins = $mail_plugins quota
|
driver = pam
|
||||||
service quota-status {
|
args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
|
||||||
executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
|
|
||||||
inet_listener {
|
|
||||||
port = ${cfg.quotaPort}
|
|
||||||
}
|
}
|
||||||
client_limit = 1
|
''
|
||||||
}
|
)
|
||||||
|
|
||||||
protocol imap {
|
(
|
||||||
mail_plugins = $mail_plugins imap_quota
|
optionalString (cfg.sieveScripts != {}) ''
|
||||||
}
|
plugin {
|
||||||
|
${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
|
||||||
|
}
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
plugin {
|
(
|
||||||
quota_rule = *:storage=${cfg.quotaGlobalPerUser}
|
optionalString (cfg.mailboxes != []) ''
|
||||||
quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
|
protocol imap {
|
||||||
quota_status_success = DUNNO
|
namespace inbox {
|
||||||
quota_status_nouser = DUNNO
|
inbox=yes
|
||||||
quota_status_overquota = "552 5.2.2 Mailbox is full"
|
${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
|
||||||
quota_grace = 10%%
|
}
|
||||||
}
|
}
|
||||||
'')
|
''
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
optionalString cfg.enableQuota ''
|
||||||
|
service quota-status {
|
||||||
|
executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
|
||||||
|
inet_listener {
|
||||||
|
port = ${cfg.quotaPort}
|
||||||
|
}
|
||||||
|
client_limit = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin {
|
||||||
|
quota_rule = *:storage=${cfg.quotaGlobalPerUser}
|
||||||
|
quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
|
||||||
|
quota_status_success = DUNNO
|
||||||
|
quota_status_nouser = DUNNO
|
||||||
|
quota_status_overquota = "552 5.2.2 Mailbox is full"
|
||||||
|
quota_grace = 10%%
|
||||||
|
}
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
cfg.extraConfig
|
cfg.extraConfig
|
||||||
];
|
];
|
||||||
@ -107,7 +126,7 @@ let
|
|||||||
mailbox "${mailbox.name}" {
|
mailbox "${mailbox.name}" {
|
||||||
auto = ${toString mailbox.auto}
|
auto = ${toString mailbox.auto}
|
||||||
'' + optionalString (mailbox.specialUse != null) ''
|
'' + optionalString (mailbox.specialUse != null) ''
|
||||||
special_use = \${toString mailbox.specialUse}
|
special_use = \${toString mailbox.specialUse}
|
||||||
'' + "}";
|
'' + "}";
|
||||||
|
|
||||||
mailboxes = { ... }: {
|
mailboxes = { ... }: {
|
||||||
@ -160,7 +179,7 @@ in
|
|||||||
|
|
||||||
protocols = mkOption {
|
protocols = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [];
|
||||||
description = "Additional listeners to start when Dovecot is enabled.";
|
description = "Additional listeners to start when Dovecot is enabled.";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,6 +202,43 @@ in
|
|||||||
description = "Additional entries to put verbatim into Dovecot's config file.";
|
description = "Additional entries to put verbatim into Dovecot's config file.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mailPlugins =
|
||||||
|
let
|
||||||
|
plugins = hint: types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "mail plugins to enable as a list of strings to append to the ${hint} <literal>$mail_plugins</literal> configuration variable";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mkOption {
|
||||||
|
type = with types; submodule {
|
||||||
|
options = {
|
||||||
|
globally = mkOption {
|
||||||
|
description = "Additional entries to add to the mail_plugins variable for all protocols";
|
||||||
|
type = plugins "top-level";
|
||||||
|
example = { enable = [ "virtual" ]; };
|
||||||
|
default = { enable = []; };
|
||||||
|
};
|
||||||
|
perProtocol = mkOption {
|
||||||
|
description = "Additional entries to add to the mail_plugins variable, per protocol";
|
||||||
|
type = attrsOf (plugins "corresponding per-protocol");
|
||||||
|
default = {};
|
||||||
|
example = { imap = [ "imap_acl" ]; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
description = "Additional entries to add to the mail_plugins variable, globally and per protocol";
|
||||||
|
example = {
|
||||||
|
globally.enable = [ "acl" ];
|
||||||
|
perProtocol.imap.enable = [ "imap_acl" ];
|
||||||
|
};
|
||||||
|
default = { globally.enable = []; perProtocol = {}; };
|
||||||
|
};
|
||||||
|
|
||||||
configFile = mkOption {
|
configFile = mkOption {
|
||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
default = null;
|
default = null;
|
||||||
@ -305,27 +361,33 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
params.dovecot2 = {};
|
params.dovecot2 = {};
|
||||||
};
|
};
|
||||||
services.dovecot2.protocols =
|
services.dovecot2.protocols =
|
||||||
optional cfg.enableImap "imap"
|
optional cfg.enableImap "imap"
|
||||||
++ optional cfg.enablePop3 "pop3"
|
++ optional cfg.enablePop3 "pop3"
|
||||||
++ optional cfg.enableLmtp "lmtp";
|
++ optional cfg.enableLmtp "lmtp";
|
||||||
|
|
||||||
|
services.dovecot2.mailPlugins = mkIf cfg.enableQuota {
|
||||||
|
globally.enable = [ "quota" ];
|
||||||
|
perProtocol.imap.enable = [ "imap_quota" ];
|
||||||
|
};
|
||||||
|
|
||||||
users.users = {
|
users.users = {
|
||||||
dovenull =
|
dovenull =
|
||||||
{ uid = config.ids.uids.dovenull2;
|
{
|
||||||
|
uid = config.ids.uids.dovenull2;
|
||||||
description = "Dovecot user for untrusted logins";
|
description = "Dovecot user for untrusted logins";
|
||||||
group = "dovenull";
|
group = "dovenull";
|
||||||
};
|
};
|
||||||
} // optionalAttrs (cfg.user == "dovecot2") {
|
} // optionalAttrs (cfg.user == "dovecot2") {
|
||||||
dovecot2 =
|
dovecot2 =
|
||||||
{ uid = config.ids.uids.dovecot2;
|
{
|
||||||
description = "Dovecot user";
|
uid = config.ids.uids.dovecot2;
|
||||||
group = cfg.group;
|
description = "Dovecot user";
|
||||||
};
|
group = cfg.group;
|
||||||
|
};
|
||||||
} // optionalAttrs (cfg.createMailUser && cfg.mailUser != null) {
|
} // optionalAttrs (cfg.createMailUser && cfg.mailUser != null) {
|
||||||
${cfg.mailUser} =
|
${cfg.mailUser} =
|
||||||
{ description = "Virtual Mail User"; } //
|
{ description = "Virtual Mail User"; } // optionalAttrs (cfg.mailGroup != null)
|
||||||
optionalAttrs (cfg.mailGroup != null)
|
|
||||||
{ group = cfg.mailGroup; };
|
{ group = cfg.mailGroup; };
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -334,7 +396,7 @@ in
|
|||||||
} // optionalAttrs (cfg.group == "dovecot2") {
|
} // optionalAttrs (cfg.group == "dovecot2") {
|
||||||
dovecot2.gid = config.ids.gids.dovecot2;
|
dovecot2.gid = config.ids.gids.dovecot2;
|
||||||
} // optionalAttrs (cfg.createMailUser && cfg.mailGroup != null) {
|
} // optionalAttrs (cfg.createMailUser && cfg.mailGroup != null) {
|
||||||
${cfg.mailGroup} = { };
|
${cfg.mailGroup} = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.etc."dovecot/modules".source = modulesDir;
|
environment.etc."dovecot/modules".source = modulesDir;
|
||||||
@ -363,15 +425,19 @@ in
|
|||||||
rm -rf ${stateDir}/sieve
|
rm -rf ${stateDir}/sieve
|
||||||
'' + optionalString (cfg.sieveScripts != {}) ''
|
'' + optionalString (cfg.sieveScripts != {}) ''
|
||||||
mkdir -p ${stateDir}/sieve
|
mkdir -p ${stateDir}/sieve
|
||||||
${concatStringsSep "\n" (mapAttrsToList (to: from: ''
|
${concatStringsSep "\n" (
|
||||||
if [ -d '${from}' ]; then
|
mapAttrsToList (
|
||||||
mkdir '${stateDir}/sieve/${to}'
|
to: from: ''
|
||||||
cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
|
if [ -d '${from}' ]; then
|
||||||
else
|
mkdir '${stateDir}/sieve/${to}'
|
||||||
cp -p '${from}' '${stateDir}/sieve/${to}'
|
cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
|
||||||
fi
|
else
|
||||||
${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
|
cp -p '${from}' '${stateDir}/sieve/${to}'
|
||||||
'') cfg.sieveScripts)}
|
fi
|
||||||
|
${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
|
||||||
|
''
|
||||||
|
) cfg.sieveScripts
|
||||||
|
)}
|
||||||
chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
|
chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -379,17 +445,21 @@ in
|
|||||||
environment.systemPackages = [ dovecotPkg ];
|
environment.systemPackages = [ dovecotPkg ];
|
||||||
|
|
||||||
assertions = [
|
assertions = [
|
||||||
{ assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
|
{
|
||||||
|
assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
|
||||||
message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
|
message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
|
||||||
}
|
}
|
||||||
{ assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
|
{
|
||||||
&& (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
|
assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
|
||||||
|
&& (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
|
||||||
message = "dovecot needs both sslServerCert and sslServerKey defined for working crypto";
|
message = "dovecot needs both sslServerCert and sslServerKey defined for working crypto";
|
||||||
}
|
}
|
||||||
{ assertion = cfg.showPAMFailure -> cfg.enablePAM;
|
{
|
||||||
|
assertion = cfg.showPAMFailure -> cfg.enablePAM;
|
||||||
message = "dovecot is configured with showPAMFailure while enablePAM is disabled";
|
message = "dovecot is configured with showPAMFailure while enablePAM is disabled";
|
||||||
}
|
}
|
||||||
{ assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
|
{
|
||||||
|
assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
|
||||||
message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set";
|
message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
79
nixos/modules/services/misc/ankisyncd.nix
Normal file
79
nixos/modules/services/misc/ankisyncd.nix
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.ankisyncd;
|
||||||
|
|
||||||
|
name = "ankisyncd";
|
||||||
|
|
||||||
|
stateDir = "/var/lib/${name}";
|
||||||
|
|
||||||
|
authDbPath = "${stateDir}/auth.db";
|
||||||
|
|
||||||
|
sessionDbPath = "${stateDir}/session.db";
|
||||||
|
|
||||||
|
configFile = pkgs.writeText "ankisyncd.conf" (lib.generators.toINI {} {
|
||||||
|
sync_app = {
|
||||||
|
host = cfg.host;
|
||||||
|
port = cfg.port;
|
||||||
|
data_root = stateDir;
|
||||||
|
auth_db_path = authDbPath;
|
||||||
|
session_db_path = sessionDbPath;
|
||||||
|
|
||||||
|
base_url = "/sync/";
|
||||||
|
base_media_url = "/msync/";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.ankisyncd = {
|
||||||
|
enable = mkEnableOption "ankisyncd";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.ankisyncd;
|
||||||
|
defaultText = literalExample "pkgs.ankisyncd";
|
||||||
|
description = "The package to use for the ankisyncd command.";
|
||||||
|
};
|
||||||
|
|
||||||
|
host = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "localhost";
|
||||||
|
description = "ankisyncd host";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 27701;
|
||||||
|
description = "ankisyncd port";
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether to open the firewall for the specified port.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||||||
|
|
||||||
|
environment.etc."ankisyncd/ankisyncd.conf".source = configFile;
|
||||||
|
|
||||||
|
systemd.services.ankisyncd = {
|
||||||
|
description = "ankisyncd - Anki sync server";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
path = [ cfg.package ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
DynamicUser = true;
|
||||||
|
StateDirectory = name;
|
||||||
|
ExecStart = "${cfg.package}/bin/ankisyncd";
|
||||||
|
Restart = "always";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -48,5 +48,5 @@ in {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with maintainers; [ gnidorah ma27 ];
|
meta.maintainers = with maintainers; [ gnidorah ];
|
||||||
}
|
}
|
||||||
|
@ -61,10 +61,7 @@ in
|
|||||||
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
|
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
|
||||||
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
|
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
|
||||||
|
|
||||||
users.groups = singleton
|
users.groups.disnix.gid = config.ids.gids.disnix;
|
||||||
{ name = "disnix";
|
|
||||||
gid = config.ids.gids.disnix;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = {
|
systemd.services = {
|
||||||
disnix = mkIf cfg.enableMultiUser {
|
disnix = mkIf cfg.enableMultiUser {
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
stateDir = "/var/lib/foldingathome";
|
|
||||||
cfg = config.services.foldingAtHome;
|
|
||||||
fahUser = "foldingathome";
|
|
||||||
in {
|
|
||||||
|
|
||||||
###### interface
|
|
||||||
|
|
||||||
options = {
|
|
||||||
|
|
||||||
services.foldingAtHome = {
|
|
||||||
|
|
||||||
enable = mkOption {
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Whether to enable the Folding@Home to use idle CPU time.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
nickname = mkOption {
|
|
||||||
default = "Anonymous";
|
|
||||||
description = ''
|
|
||||||
A unique handle for statistics.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkOption {
|
|
||||||
default = "";
|
|
||||||
description = ''
|
|
||||||
Extra configuration. Contents will be added verbatim to the
|
|
||||||
configuration file.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
###### implementation
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
users.users.${fahUser} =
|
|
||||||
{ uid = config.ids.uids.foldingathome;
|
|
||||||
description = "Folding@Home user";
|
|
||||||
home = stateDir;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.foldingathome = {
|
|
||||||
after = [ "network.target" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
preStart = ''
|
|
||||||
mkdir -m 0755 -p ${stateDir}
|
|
||||||
chown ${fahUser} ${stateDir}
|
|
||||||
cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg
|
|
||||||
'';
|
|
||||||
script = "${pkgs.su}/bin/su -s ${pkgs.runtimeShell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.foldingAtHome.config = ''
|
|
||||||
[settings]
|
|
||||||
username=${cfg.nickname}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
@ -96,7 +96,20 @@ in {
|
|||||||
|
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
type = with types; nullOr attrs;
|
# Migrate to new option types later: https://github.com/NixOS/nixpkgs/pull/75584
|
||||||
|
type = with lib.types; let
|
||||||
|
valueType = nullOr (oneOf [
|
||||||
|
bool
|
||||||
|
int
|
||||||
|
float
|
||||||
|
str
|
||||||
|
(lazyAttrsOf valueType)
|
||||||
|
(listOf valueType)
|
||||||
|
]) // {
|
||||||
|
description = "Yaml value";
|
||||||
|
emptyValue.value = {};
|
||||||
|
};
|
||||||
|
in valueType;
|
||||||
example = literalExample ''
|
example = literalExample ''
|
||||||
{
|
{
|
||||||
homeassistant = {
|
homeassistant = {
|
||||||
|
@ -111,6 +111,9 @@ app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
|
|||||||
|
|
||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
hasLocalPostgresDB = let args = cfg.database_args; in
|
||||||
|
usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ]));
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
services.matrix-synapse = {
|
services.matrix-synapse = {
|
||||||
@ -354,13 +357,6 @@ in {
|
|||||||
The database engine name. Can be sqlite or psycopg2.
|
The database engine name. Can be sqlite or psycopg2.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
create_local_database = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to create a local database automatically.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
database_name = mkOption {
|
database_name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "matrix-synapse";
|
default = "matrix-synapse";
|
||||||
@ -657,6 +653,25 @@ in {
|
|||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{ assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
|
||||||
|
message = ''
|
||||||
|
Cannot deploy matrix-synapse with a configuration for a local postgresql database
|
||||||
|
and a missing postgresql service. Since 20.03 it's mandatory to manually configure the
|
||||||
|
database (please read the thread in https://github.com/NixOS/nixpkgs/pull/80447 for
|
||||||
|
further reference).
|
||||||
|
|
||||||
|
If you
|
||||||
|
- try to deploy a fresh synapse, you need to configure the database yourself. An example
|
||||||
|
for this can be found in <nixpkgs/nixos/tests/matrix-synapse.nix>
|
||||||
|
- update your existing matrix-synapse instance, you simply need to add `services.postgresql.enable = true`
|
||||||
|
to your configuration.
|
||||||
|
|
||||||
|
For further information about this update, please read the release-notes of 20.03 carefully.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
users.users.matrix-synapse = {
|
users.users.matrix-synapse = {
|
||||||
group = "matrix-synapse";
|
group = "matrix-synapse";
|
||||||
home = cfg.dataDir;
|
home = cfg.dataDir;
|
||||||
@ -669,18 +684,9 @@ in {
|
|||||||
gid = config.ids.gids.matrix-synapse;
|
gid = config.ids.gids.matrix-synapse;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresql = mkIf (usePostgresql && cfg.create_local_database) {
|
|
||||||
enable = mkDefault true;
|
|
||||||
ensureDatabases = [ cfg.database_name ];
|
|
||||||
ensureUsers = [{
|
|
||||||
name = cfg.database_user;
|
|
||||||
ensurePermissions = { "DATABASE \"${cfg.database_name}\"" = "ALL PRIVILEGES"; };
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.matrix-synapse = {
|
systemd.services.matrix-synapse = {
|
||||||
description = "Synapse Matrix homeserver";
|
description = "Synapse Matrix homeserver";
|
||||||
after = [ "network.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service" ;
|
after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
${cfg.package}/bin/homeserver \
|
${cfg.package}/bin/homeserver \
|
||||||
@ -709,6 +715,12 @@ in {
|
|||||||
The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0
|
The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0
|
||||||
as the behavior is now obsolete.
|
as the behavior is now obsolete.
|
||||||
'')
|
'')
|
||||||
|
(mkRemovedOptionModule [ "services" "matrix-synapse" "create_local_database" ] ''
|
||||||
|
Database configuration must be done manually. An exemplary setup is demonstrated in
|
||||||
|
<nixpkgs/nixos/tests/matrix-synapse.nix>
|
||||||
|
'')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
meta.doc = ./matrix-synapse.xml;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,26 +40,35 @@ let
|
|||||||
in join config.networking.hostName config.networking.domain;
|
in join config.networking.hostName config.networking.domain;
|
||||||
in {
|
in {
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "myhostname";
|
<link linkend="opt-networking.hostName">hostName</link> = "myhostname";
|
||||||
domain = "example.org";
|
<link linkend="opt-networking.domain">domain</link> = "example.org";
|
||||||
};
|
};
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
||||||
|
|
||||||
|
<link linkend="opt-services.postgresql.enable">services.postgresql.enable</link> = true;
|
||||||
|
<link linkend="opt-services.postgresql.initialScript">services.postgresql.initialScript</link> = ''
|
||||||
|
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||||
|
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||||
|
TEMPLATE template0
|
||||||
|
LC_COLLATE = "C"
|
||||||
|
LC_CTYPE = "C";
|
||||||
|
'';
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
||||||
# only recommendedProxySettings and recommendedGzipSettings are strictly required,
|
# only recommendedProxySettings and recommendedGzipSettings are strictly required,
|
||||||
# but the rest make sense as well
|
# but the rest make sense as well
|
||||||
recommendedTlsSettings = true;
|
<link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
|
||||||
recommendedOptimisation = true;
|
<link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
|
||||||
recommendedGzipSettings = true;
|
<link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
|
||||||
recommendedProxySettings = true;
|
<link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
|
||||||
|
|
||||||
virtualHosts = {
|
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
||||||
# This host section can be placed on a different host than the rest,
|
# This host section can be placed on a different host than the rest,
|
||||||
# i.e. to delegate from the host being accessible as ${config.networking.domain}
|
# i.e. to delegate from the host being accessible as ${config.networking.domain}
|
||||||
# to another host actually running the Matrix homeserver.
|
# to another host actually running the Matrix homeserver.
|
||||||
"${config.networking.domain}" = {
|
"${config.networking.domain}" = {
|
||||||
locations."= /.well-known/matrix/server".extraConfig =
|
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/server".extraConfig</link> =
|
||||||
let
|
let
|
||||||
# use 443 instead of the default 8448 port to unite
|
# use 443 instead of the default 8448 port to unite
|
||||||
# the client-server and server-server port for simplicity
|
# the client-server and server-server port for simplicity
|
||||||
@ -68,7 +77,7 @@ in {
|
|||||||
add_header Content-Type application/json;
|
add_header Content-Type application/json;
|
||||||
return 200 '${builtins.toJSON server}';
|
return 200 '${builtins.toJSON server}';
|
||||||
'';
|
'';
|
||||||
locations."= /.well-known/matrix/client".extraConfig =
|
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/client".extraConfig</link> =
|
||||||
let
|
let
|
||||||
client = {
|
client = {
|
||||||
"m.homeserver" = { "base_url" = "https://${fqdn}"; };
|
"m.homeserver" = { "base_url" = "https://${fqdn}"; };
|
||||||
@ -84,34 +93,37 @@ in {
|
|||||||
|
|
||||||
# Reverse proxy for Matrix client-server and server-server communication
|
# Reverse proxy for Matrix client-server and server-server communication
|
||||||
${fqdn} = {
|
${fqdn} = {
|
||||||
enableACME = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
||||||
forceSSL = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
||||||
|
|
||||||
# Or do a redirect instead of the 404, or whatever is appropriate for you.
|
# Or do a redirect instead of the 404, or whatever is appropriate for you.
|
||||||
# But do not put a Matrix Web client here! See the Riot Web section below.
|
# But do not put a Matrix Web client here! See the Riot Web section below.
|
||||||
locations."/".extraConfig = ''
|
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."/".extraConfig</link> = ''
|
||||||
return 404;
|
return 404;
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# forward all Matrix API calls to the synapse Matrix homeserver
|
# forward all Matrix API calls to the synapse Matrix homeserver
|
||||||
locations."/_matrix" = {
|
locations."/_matrix" = {
|
||||||
proxyPass = "http://[::1]:8008"; # without a trailing /
|
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">proxyPass</link> = "http://[::1]:8008"; # without a trailing /
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.matrix-synapse = {
|
services.matrix-synapse = {
|
||||||
enable = true;
|
<link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
|
||||||
server_name = config.networking.domain;
|
<link linkend="opt-services.matrix-synapse.server_name">server_name</link> = config.networking.domain;
|
||||||
listeners = [
|
<link linkend="opt-services.matrix-synapse.listeners">listeners</link> = [
|
||||||
{
|
{
|
||||||
port = 8008;
|
<link linkend="opt-services.matrix-synapse.listeners._.port">port</link> = 8008;
|
||||||
bind_address = "::1";
|
<link linkend="opt-services.matrix-synapse.listeners._.bind_address">bind_address</link> = "::1";
|
||||||
type = "http";
|
<link linkend="opt-services.matrix-synapse.listeners._.type">type</link> = "http";
|
||||||
tls = false;
|
<link linkend="opt-services.matrix-synapse.listeners._.tls">tls</link> = false;
|
||||||
x_forwarded = true;
|
<link linkend="opt-services.matrix-synapse.listeners._.x_forwarded">x_forwarded</link> = true;
|
||||||
resources = [
|
<link linkend="opt-services.matrix-synapse.listeners._.resources">resources</link> = [
|
||||||
{ names = [ "client" "federation" ]; compress = false; }
|
{
|
||||||
|
<link linkend="opt-services.matrix-synapse.listeners._.resources._.names">names</link> = [ "client" "federation" ];
|
||||||
|
<link linkend="opt-services.matrix-synapse.listeners._.resources._.compress">compress</link> = false;
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -135,10 +147,10 @@ in {
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you want to run a server with public registration by anybody, you can
|
If you want to run a server with public registration by anybody, you can
|
||||||
then enable <option>services.matrix-synapse.enable_registration =
|
then enable <literal><link linkend="opt-services.matrix-synapse.enable_registration">services.matrix-synapse.enable_registration</link> =
|
||||||
true;</option>. Otherwise, or you can generate a registration secret with
|
true;</literal>. Otherwise, or you can generate a registration secret with
|
||||||
<command>pwgen -s 64 1</command> and set it with
|
<command>pwgen -s 64 1</command> and set it with
|
||||||
<option>services.matrix-synapse.registration_shared_secret</option>. To
|
<option><link linkend="opt-services.matrix-synapse.registration_shared_secret">services.matrix-synapse.registration_shared_secret</link></option>. To
|
||||||
create a new user or admin, run the following after you have set the secret
|
create a new user or admin, run the following after you have set the secret
|
||||||
and have rebuilt NixOS:
|
and have rebuilt NixOS:
|
||||||
<screen>
|
<screen>
|
||||||
@ -154,8 +166,8 @@ Success!
|
|||||||
<literal>@your-username:example.org</literal>. Note that the registration
|
<literal>@your-username:example.org</literal>. Note that the registration
|
||||||
secret ends up in the nix store and therefore is world-readable by any user
|
secret ends up in the nix store and therefore is world-readable by any user
|
||||||
on your machine, so it makes sense to only temporarily activate the
|
on your machine, so it makes sense to only temporarily activate the
|
||||||
<option>registration_shared_secret</option> option until a better solution
|
<link linkend="opt-services.matrix-synapse.registration_shared_secret">registration_shared_secret</link>
|
||||||
for NixOS is in place.
|
option until a better solution for NixOS is in place.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
<section xml:id="module-services-matrix-riot-web">
|
<section xml:id="module-services-matrix-riot-web">
|
||||||
@ -177,15 +189,24 @@ Success!
|
|||||||
Matrix Now!</link> for a list of existing clients and their supported
|
Matrix Now!</link> for a list of existing clients and their supported
|
||||||
featureset.
|
featureset.
|
||||||
<programlisting>
|
<programlisting>
|
||||||
services.nginx.virtualHosts."riot.${fqdn}" = {
|
{
|
||||||
enableACME = true;
|
services.nginx.virtualHosts."riot.${fqdn}" = {
|
||||||
forceSSL = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
||||||
serverAliases = [
|
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
||||||
"riot.${config.networking.domain}"
|
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [
|
||||||
];
|
"riot.${config.networking.domain}"
|
||||||
|
];
|
||||||
|
|
||||||
root = pkgs.riot-web;
|
<link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.riot-web.override {
|
||||||
};
|
conf = {
|
||||||
|
default_server_config."m.homeserver" = {
|
||||||
|
"base_url" = "${config.networking.domain}";
|
||||||
|
"server_name" = "${fqdn}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
@ -88,9 +88,7 @@ in {
|
|||||||
exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
|
exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
services.openssh.extraConfig = ''
|
services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command";
|
||||||
AuthorizedKeysCommand /etc/ssh/authorized_keys_command
|
services.openssh.authorizedKeysCommandUser = "nobody";
|
||||||
AuthorizedKeysCommandUser nobody
|
|
||||||
'';
|
|
||||||
})];
|
})];
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,8 @@ in {
|
|||||||
`config.services.zoneminder.database.createLocally` to true. Otherwise,
|
`config.services.zoneminder.database.createLocally` to true. Otherwise,
|
||||||
when set to `false` (the default), you will have to create the database
|
when set to `false` (the default), you will have to create the database
|
||||||
and database user as well as populate the database yourself.
|
and database user as well as populate the database yourself.
|
||||||
|
Additionally, you will need to run `zmupdate.pl` yourself when
|
||||||
|
upgrading to a newer version.
|
||||||
'';
|
'';
|
||||||
|
|
||||||
webserver = mkOption {
|
webserver = mkOption {
|
||||||
@ -330,6 +332,8 @@ in {
|
|||||||
${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql
|
${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql
|
||||||
touch "/var/lib/${dirName}/db-created"
|
touch "/var/lib/${dirName}/db-created"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
${zoneminder}/bin/zmupdate.pl -nointeractive
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
User = user;
|
User = user;
|
||||||
|
@ -135,7 +135,6 @@ in {
|
|||||||
|
|
||||||
serviceConfig.TimeoutStartSec=300;
|
serviceConfig.TimeoutStartSec=300;
|
||||||
};
|
};
|
||||||
virtualisation.docker.enable = mkDefault true;
|
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@ let
|
|||||||
|
|
||||||
# a wrapper that verifies that the configuration is valid
|
# a wrapper that verifies that the configuration is valid
|
||||||
promtoolCheck = what: name: file:
|
promtoolCheck = what: name: file:
|
||||||
pkgs.runCommand
|
if cfg.checkConfig then
|
||||||
"${name}-${replaceStrings [" "] [""] what}-checked"
|
pkgs.runCommand
|
||||||
{ buildInputs = [ cfg.package ]; } ''
|
"${name}-${replaceStrings [" "] [""] what}-checked"
|
||||||
ln -s ${file} $out
|
{ buildInputs = [ cfg.package ]; } ''
|
||||||
promtool ${what} $out
|
ln -s ${file} $out
|
||||||
'';
|
promtool ${what} $out
|
||||||
|
'' else file;
|
||||||
|
|
||||||
# Pretty-print JSON to a file
|
# Pretty-print JSON to a file
|
||||||
writePrettyJSON = name: x:
|
writePrettyJSON = name: x:
|
||||||
@ -601,6 +602,20 @@ in {
|
|||||||
if Prometheus is served via a reverse proxy).
|
if Prometheus is served via a reverse proxy).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
checkConfig = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Check configuration with <literal>promtool
|
||||||
|
check</literal>. The call to <literal>promtool</literal> is
|
||||||
|
subject to sandboxing by Nix. When credentials are stored in
|
||||||
|
external files (<literal>password_file</literal>,
|
||||||
|
<literal>bearer_token_file</literal>, etc), they will not be
|
||||||
|
visible to <literal>promtool</literal> and it will report
|
||||||
|
errors, despite a correct configuration.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
@ -29,6 +29,7 @@ let
|
|||||||
"fritzbox"
|
"fritzbox"
|
||||||
"json"
|
"json"
|
||||||
"mail"
|
"mail"
|
||||||
|
"mikrotik"
|
||||||
"minio"
|
"minio"
|
||||||
"nextcloud"
|
"nextcloud"
|
||||||
"nginx"
|
"nginx"
|
||||||
@ -197,13 +198,25 @@ in
|
|||||||
|
|
||||||
config = mkMerge ([{
|
config = mkMerge ([{
|
||||||
assertions = [ {
|
assertions = [ {
|
||||||
assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
|
assertion = cfg.snmp.enable -> (
|
||||||
|
(cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null)
|
||||||
|
);
|
||||||
message = ''
|
message = ''
|
||||||
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
|
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
|
||||||
or `services.prometheus.exporters.snmp.configurationPath' set!
|
or `services.prometheus.exporters.snmp.configurationPath' set!
|
||||||
'';
|
'';
|
||||||
} {
|
} {
|
||||||
assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {});
|
assertion = cfg.mikrotik.enable -> (
|
||||||
|
(cfg.mikrotik.configFile == null) != (cfg.mikrotik.configuration == null)
|
||||||
|
);
|
||||||
|
message = ''
|
||||||
|
Please specify either `services.prometheus.exporters.mikrotik.configuration'
|
||||||
|
or `services.prometheus.exporters.mikrotik.configFile'.
|
||||||
|
'';
|
||||||
|
} {
|
||||||
|
assertion = cfg.mail.enable -> (
|
||||||
|
(cfg.mail.configFile == null) != (cfg.mail.configuration == null)
|
||||||
|
);
|
||||||
message = ''
|
message = ''
|
||||||
Please specify either 'services.prometheus.exporters.mail.configuration'
|
Please specify either 'services.prometheus.exporters.mail.configuration'
|
||||||
or 'services.prometheus.exporters.mail.configFile'.
|
or 'services.prometheus.exporters.mail.configFile'.
|
||||||
|
@ -61,7 +61,7 @@ in {
|
|||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--config.file ${adjustedConfigFile} \
|
--config.file ${escapeShellArg adjustedConfigFile} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||||
|
@ -66,7 +66,7 @@ in
|
|||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
|
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
|
||||||
-log.format ${cfg.logFormat} \
|
-log.format ${escapeShellArg cfg.logFormat} \
|
||||||
-log.level ${cfg.logLevel} \
|
-log.level ${cfg.logLevel} \
|
||||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
${collectSettingsArgs} \
|
${collectSettingsArgs} \
|
||||||
|
@ -30,7 +30,7 @@ in
|
|||||||
${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \
|
${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \
|
||||||
--listen ${cfg.listenAddress}:${toString cfg.port} \
|
--listen ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--dnsmasq ${cfg.dnsmasqListenAddress} \
|
--dnsmasq ${cfg.dnsmasqListenAddress} \
|
||||||
--leases_path ${cfg.leasesPath} \
|
--leases_path ${escapeShellArg cfg.leasesPath} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -64,7 +64,7 @@ in
|
|||||||
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
|
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--web.telemetry-path ${cfg.telemetryPath} \
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
--dovecot.socket-path ${cfg.socketPath} \
|
--dovecot.socket-path ${escapeShellArg cfg.socketPath} \
|
||||||
--dovecot.scopes ${concatStringsSep "," cfg.scopes} \
|
--dovecot.scopes ${concatStringsSep "," cfg.scopes} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
|
@ -27,7 +27,7 @@ in
|
|||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
|
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
|
||||||
--port ${toString cfg.port} \
|
--port ${toString cfg.port} \
|
||||||
${cfg.url} ${cfg.configFile} \
|
${cfg.url} ${escapeShellArg cfg.configFile} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -90,7 +90,7 @@ let
|
|||||||
Timeout until mails are considered "didn't make it".
|
Timeout until mails are considered "didn't make it".
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
disableFileDelition = mkOption {
|
disableFileDeletion = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
@ -127,8 +127,8 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
configuration = mkOption {
|
configuration = mkOption {
|
||||||
type = types.submodule exporterOptions;
|
type = types.nullOr (types.submodule exporterOptions);
|
||||||
default = {};
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
Specify the mailexporter configuration file to use.
|
Specify the mailexporter configuration file to use.
|
||||||
'';
|
'';
|
||||||
@ -147,8 +147,9 @@ in
|
|||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.prometheus-mail-exporter}/bin/mailexporter \
|
${pkgs.prometheus-mail-exporter}/bin/mailexporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
--config.file ${
|
--config.file ${
|
||||||
if cfg.configuration != {} then configurationFile else cfg.configFile
|
if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile)
|
||||||
} \
|
} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
{ config, lib, pkgs, options }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.prometheus.exporters.mikrotik;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
port = 9436;
|
||||||
|
extraOpts = {
|
||||||
|
configFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to a mikrotik exporter configuration file. Mutually exclusive with
|
||||||
|
<option>configuration</option> option.
|
||||||
|
'';
|
||||||
|
example = literalExample "./mikrotik.yml";
|
||||||
|
};
|
||||||
|
|
||||||
|
configuration = mkOption {
|
||||||
|
type = types.nullOr types.attrs;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Mikrotik exporter configuration as nix attribute set. Mutually exclusive with
|
||||||
|
<option>configFile</option> option.
|
||||||
|
|
||||||
|
See <link xlink:href="https://github.com/nshttpd/mikrotik-exporter/blob/master/README.md"/>
|
||||||
|
for the description of the configuration file format.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
devices = [
|
||||||
|
{
|
||||||
|
name = "my_router";
|
||||||
|
address = "10.10.0.1";
|
||||||
|
user = "prometheus";
|
||||||
|
password = "changeme";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
features = {
|
||||||
|
bgp = true;
|
||||||
|
dhcp = true;
|
||||||
|
routes = true;
|
||||||
|
optics = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
serviceOpts = let
|
||||||
|
configFile = if cfg.configFile != null
|
||||||
|
then cfg.configFile
|
||||||
|
else "${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}";
|
||||||
|
in {
|
||||||
|
serviceConfig = {
|
||||||
|
# -port is misleading name, it actually accepts address too
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \
|
||||||
|
-config-file=${escapeShellArg configFile} \
|
||||||
|
-port=${cfg.listenAddress}:${toString cfg.port} \
|
||||||
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -54,8 +54,8 @@ in
|
|||||||
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
|
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
|
||||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
-minio.server ${cfg.minioAddress} \
|
-minio.server ${cfg.minioAddress} \
|
||||||
-minio.access-key ${cfg.minioAccessKey} \
|
-minio.access-key ${escapeShellArg cfg.minioAccessKey} \
|
||||||
-minio.access-secret ${cfg.minioAccessSecret} \
|
-minio.access-secret ${escapeShellArg cfg.minioAccessSecret} \
|
||||||
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
|
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
|
@ -50,7 +50,7 @@ in
|
|||||||
-u ${cfg.username} \
|
-u ${cfg.username} \
|
||||||
-t ${cfg.timeout} \
|
-t ${cfg.timeout} \
|
||||||
-l ${cfg.url} \
|
-l ${cfg.url} \
|
||||||
-p @${cfg.passwordFile} \
|
-p ${escapeShellArg "@${cfg.passwordFile}"} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,17 @@ in
|
|||||||
Whether to perform certificate verification for https.
|
Whether to perform certificate verification for https.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
constLabels = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [
|
||||||
|
"label1=value1"
|
||||||
|
"label2=value2"
|
||||||
|
];
|
||||||
|
description = ''
|
||||||
|
A list of constant labels that will be used in every metric.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
serviceOpts = {
|
serviceOpts = {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
@ -40,6 +50,7 @@ in
|
|||||||
--nginx.ssl-verify ${toString cfg.sslVerify} \
|
--nginx.ssl-verify ${toString cfg.sslVerify} \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--web.telemetry-path ${cfg.telemetryPath} \
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
|
--prometheus.const-labels ${concatStringsSep "," cfg.constLabels} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -67,15 +67,15 @@ in
|
|||||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--web.telemetry-path ${cfg.telemetryPath} \
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
--postfix.showq_path ${cfg.showqPath} \
|
--postfix.showq_path ${escapeShellArg cfg.showqPath} \
|
||||||
${concatStringsSep " \\\n " (cfg.extraFlags
|
${concatStringsSep " \\\n " (cfg.extraFlags
|
||||||
++ optional cfg.systemd.enable "--systemd.enable"
|
++ optional cfg.systemd.enable "--systemd.enable"
|
||||||
++ optional cfg.systemd.enable (if cfg.systemd.slice != null
|
++ optional cfg.systemd.enable (if cfg.systemd.slice != null
|
||||||
then "--systemd.slice ${cfg.systemd.slice}"
|
then "--systemd.slice ${cfg.systemd.slice}"
|
||||||
else "--systemd.unit ${cfg.systemd.unit}")
|
else "--systemd.unit ${cfg.systemd.unit}")
|
||||||
++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null))
|
++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null))
|
||||||
"--systemd.journal_path ${cfg.systemd.journalPath}"
|
"--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}"
|
||||||
++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${cfg.logfilePath}")}
|
++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}")}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@ in
|
|||||||
|
|
||||||
configuration = mkOption {
|
configuration = mkOption {
|
||||||
type = types.nullOr types.attrs;
|
type = types.nullOr types.attrs;
|
||||||
default = {};
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
|
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
|
||||||
'';
|
'';
|
||||||
@ -36,15 +36,15 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
logFormat = mkOption {
|
logFormat = mkOption {
|
||||||
type = types.str;
|
type = types.enum ["logfmt" "json"];
|
||||||
default = "logger:stderr";
|
default = "logfmt";
|
||||||
description = ''
|
description = ''
|
||||||
Set the log target and format.
|
Output format of log messages.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
logLevel = mkOption {
|
logLevel = mkOption {
|
||||||
type = types.enum ["debug" "info" "warn" "error" "fatal"];
|
type = types.enum ["debug" "info" "warn" "error"];
|
||||||
default = "info";
|
default = "info";
|
||||||
description = ''
|
description = ''
|
||||||
Only log messages with the given severity or above.
|
Only log messages with the given severity or above.
|
||||||
@ -54,13 +54,13 @@ in
|
|||||||
serviceOpts = let
|
serviceOpts = let
|
||||||
configFile = if cfg.configurationPath != null
|
configFile = if cfg.configurationPath != null
|
||||||
then cfg.configurationPath
|
then cfg.configurationPath
|
||||||
else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
|
else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}";
|
||||||
in {
|
in {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
|
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
|
||||||
--config.file=${configFile} \
|
--config.file=${escapeShellArg configFile} \
|
||||||
--log.format=${cfg.logFormat} \
|
--log.format=${escapeShellArg cfg.logFormat} \
|
||||||
--log.level=${cfg.logLevel} \
|
--log.level=${cfg.logLevel} \
|
||||||
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
|
@ -55,8 +55,8 @@ in
|
|||||||
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
|
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
|
||||||
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
|
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
-unifi.addr ${cfg.unifiAddress} \
|
-unifi.addr ${cfg.unifiAddress} \
|
||||||
-unifi.username ${cfg.unifiUsername} \
|
-unifi.username ${escapeShellArg cfg.unifiUsername} \
|
||||||
-unifi.password ${cfg.unifiPassword} \
|
-unifi.password ${escapeShellArg cfg.unifiPassword} \
|
||||||
-unifi.timeout ${cfg.unifiTimeout} \
|
-unifi.timeout ${cfg.unifiTimeout} \
|
||||||
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
|
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
|
||||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||||
|
@ -74,10 +74,10 @@ in
|
|||||||
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
|
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
|
||||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
--web.telemetry-path ${cfg.telemetryPath} \
|
--web.telemetry-path ${cfg.telemetryPath} \
|
||||||
--varnishstat-path ${cfg.varnishStatPath} \
|
--varnishstat-path ${escapeShellArg cfg.varnishStatPath} \
|
||||||
${concatStringsSep " \\\n " (cfg.extraFlags
|
${concatStringsSep " \\\n " (cfg.extraFlags
|
||||||
++ optional (cfg.healthPath != null) "--web.health-path ${cfg.healthPath}"
|
++ optional (cfg.healthPath != null) "--web.health-path ${cfg.healthPath}"
|
||||||
++ optional (cfg.instance != null) "-n ${cfg.instance}"
|
++ optional (cfg.instance != null) "-n ${escapeShellArg cfg.instance}"
|
||||||
++ optional cfg.noExit "--no-exit"
|
++ optional cfg.noExit "--no-exit"
|
||||||
++ optional cfg.withGoMetrics "--with-go-metrics"
|
++ optional cfg.withGoMetrics "--with-go-metrics"
|
||||||
++ optional cfg.verbose "--verbose"
|
++ optional cfg.verbose "--verbose"
|
||||||
|
@ -59,7 +59,7 @@ in {
|
|||||||
${optionalString cfg.verbose "-v"} \
|
${optionalString cfg.verbose "-v"} \
|
||||||
${optionalString cfg.singleSubnetPerField "-s"} \
|
${optionalString cfg.singleSubnetPerField "-s"} \
|
||||||
${optionalString cfg.withRemoteIp "-r"} \
|
${optionalString cfg.withRemoteIp "-r"} \
|
||||||
${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"}
|
${optionalString (cfg.wireguardConfig != null) "-n ${escapeShellArg cfg.wireguardConfig}"}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -29,17 +29,13 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Additional /etc/hosts entries for peers with an associated hostname
|
# Additional /etc/hosts entries for peers with an associated hostname
|
||||||
cjdnsExtraHosts = import (pkgs.runCommand "cjdns-hosts" {}
|
cjdnsExtraHosts = pkgs.runCommandNoCC "cjdns-hosts" {} ''
|
||||||
# Generate a builder that produces an output usable as a Nix string value
|
exec >$out
|
||||||
''
|
${concatStringsSep "\n" (mapAttrsToList (k: v:
|
||||||
exec >$out
|
optionalString (v.hostname != "")
|
||||||
echo \'\'
|
"echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
|
||||||
${concatStringsSep "\n" (mapAttrsToList (k: v:
|
(cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
|
||||||
optionalString (v.hostname != "")
|
'';
|
||||||
"echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
|
|
||||||
(cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
|
|
||||||
echo \'\'
|
|
||||||
'');
|
|
||||||
|
|
||||||
parseModules = x:
|
parseModules = x:
|
||||||
x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
|
x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
|
||||||
@ -144,13 +140,15 @@ in
|
|||||||
connectTo = mkOption {
|
connectTo = mkOption {
|
||||||
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
|
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
|
||||||
default = { };
|
default = { };
|
||||||
example = {
|
example = literalExample ''
|
||||||
"192.168.1.1:27313" = {
|
{
|
||||||
hostname = "homer.hype";
|
"192.168.1.1:27313" = {
|
||||||
password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
|
hostname = "homer.hype";
|
||||||
publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
|
password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
|
||||||
};
|
publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
description = ''
|
description = ''
|
||||||
Credentials for making UDP tunnels.
|
Credentials for making UDP tunnels.
|
||||||
'';
|
'';
|
||||||
@ -189,13 +187,15 @@ in
|
|||||||
connectTo = mkOption {
|
connectTo = mkOption {
|
||||||
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
|
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
|
||||||
default = { };
|
default = { };
|
||||||
example = {
|
example = literalExample ''
|
||||||
"01:02:03:04:05:06" = {
|
{
|
||||||
hostname = "homer.hype";
|
"01:02:03:04:05:06" = {
|
||||||
password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
|
hostname = "homer.hype";
|
||||||
publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
|
password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
|
||||||
};
|
publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
description = ''
|
description = ''
|
||||||
Credentials for connecting look similar to UDP credientials
|
Credentials for connecting look similar to UDP credientials
|
||||||
except they begin with the mac address.
|
except they begin with the mac address.
|
||||||
@ -278,7 +278,7 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.extraHosts = mkIf cfg.addExtraHosts cjdnsExtraHosts;
|
networking.hostFiles = mkIf cfg.addExtraHosts [ cjdnsExtraHosts ];
|
||||||
|
|
||||||
assertions = [
|
assertions = [
|
||||||
{ assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != null );
|
{ assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != null );
|
||||||
|
@ -546,9 +546,13 @@ in
|
|||||||
options nf_conntrack nf_conntrack_helper=1
|
options nf_conntrack nf_conntrack_helper=1
|
||||||
'';
|
'';
|
||||||
|
|
||||||
assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter;
|
assertions = [
|
||||||
message = "This kernel does not support rpfilter"; }
|
# This is approximately "checkReversePath -> kernelHasRPFilter",
|
||||||
];
|
# but the checkReversePath option can include non-boolean
|
||||||
|
# values.
|
||||||
|
{ assertion = cfg.checkReversePath == false || kernelHasRPFilter;
|
||||||
|
message = "This kernel does not support rpfilter"; }
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services.firewall = {
|
systemd.services.firewall = {
|
||||||
description = "Firewall";
|
description = "Firewall";
|
||||||
|
@ -10,14 +10,15 @@ let
|
|||||||
{
|
{
|
||||||
description = "FreeRadius server";
|
description = "FreeRadius server";
|
||||||
wantedBy = ["multi-user.target"];
|
wantedBy = ["multi-user.target"];
|
||||||
after = ["network-online.target"];
|
after = ["network.target"];
|
||||||
wants = ["network-online.target"];
|
wants = ["network.target"];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
|
${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout -xx";
|
ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout" +
|
||||||
|
optionalString cfg.debug " -xx";
|
||||||
ExecReload = [
|
ExecReload = [
|
||||||
"${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
|
"${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
|
||||||
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
|
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
|
||||||
@ -41,6 +42,16 @@ let
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to enable debug logging for freeradius (-xx
|
||||||
|
option). This should not be left on, since it includes
|
||||||
|
sensitive data such as passwords in the logs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
@ -66,6 +77,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.freeradius = freeradiusService cfg;
|
systemd.services.freeradius = freeradiusService cfg;
|
||||||
|
warnings = optional cfg.debug "Freeradius debug logging is enabled. This will log passwords in plaintext to the journal!";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +26,18 @@ with lib;
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "haproxy";
|
||||||
|
description = "User account under which haproxy runs.";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "haproxy";
|
||||||
|
description = "Group account under which haproxy runs.";
|
||||||
|
};
|
||||||
|
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
type = types.nullOr types.lines;
|
type = types.nullOr types.lines;
|
||||||
default = null;
|
default = null;
|
||||||
@ -49,7 +61,8 @@ with lib;
|
|||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
DynamicUser = true;
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
# when running the config test, don't be quiet so we can see what goes wrong
|
# when running the config test, don't be quiet so we can see what goes wrong
|
||||||
ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}";
|
ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}";
|
||||||
@ -60,5 +73,16 @@ with lib;
|
|||||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
users.users = optionalAttrs (cfg.user == "haproxy") {
|
||||||
|
haproxy = {
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups = optionalAttrs (cfg.group == "haproxy") {
|
||||||
|
haproxy = {};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ let
|
|||||||
|
|
||||||
iodinedUser = "iodined";
|
iodinedUser = "iodined";
|
||||||
|
|
||||||
|
/* is this path made unreadable by ProtectHome = true ? */
|
||||||
|
isProtected = x: hasPrefix "/root" x || hasPrefix "/home" x;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
@ -35,45 +37,48 @@ in
|
|||||||
corresponding attribute name.
|
corresponding attribute name.
|
||||||
'';
|
'';
|
||||||
example = literalExample ''
|
example = literalExample ''
|
||||||
{
|
{
|
||||||
foo = {
|
foo = {
|
||||||
server = "tunnel.mdomain.com";
|
server = "tunnel.mdomain.com";
|
||||||
relay = "8.8.8.8";
|
relay = "8.8.8.8";
|
||||||
extraConfig = "-v";
|
extraConfig = "-v";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
'';
|
'';
|
||||||
type = types.attrsOf (types.submodule (
|
type = types.attrsOf (
|
||||||
{
|
types.submodule (
|
||||||
options = {
|
{
|
||||||
server = mkOption {
|
options = {
|
||||||
type = types.str;
|
server = mkOption {
|
||||||
default = "";
|
type = types.str;
|
||||||
description = "Domain or Subdomain of server running iodined";
|
default = "";
|
||||||
example = "tunnel.mydomain.com";
|
description = "Hostname of server running iodined";
|
||||||
};
|
example = "tunnel.mydomain.com";
|
||||||
|
};
|
||||||
|
|
||||||
relay = mkOption {
|
relay = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = "DNS server to use as a intermediate relay to the iodined server";
|
description = "DNS server to use as an intermediate relay to the iodined server";
|
||||||
example = "8.8.8.8";
|
example = "8.8.8.8";
|
||||||
};
|
};
|
||||||
|
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = "Additional command line parameters";
|
description = "Additional command line parameters";
|
||||||
example = "-l 192.168.1.10 -p 23";
|
example = "-l 192.168.1.10 -p 23";
|
||||||
};
|
};
|
||||||
|
|
||||||
passwordFile = mkOption {
|
passwordFile = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = "File that contains password";
|
description = "Path to a file containing the password.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}));
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
@ -121,31 +126,67 @@ in
|
|||||||
boot.kernelModules = [ "tun" ];
|
boot.kernelModules = [ "tun" ];
|
||||||
|
|
||||||
systemd.services =
|
systemd.services =
|
||||||
let
|
let
|
||||||
createIodineClientService = name: cfg:
|
createIodineClientService = name: cfg:
|
||||||
{
|
{
|
||||||
description = "iodine client - ${name}";
|
description = "iodine client - ${name}";
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
|
script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${builtins.toString cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
RestartSec = "30s";
|
RestartSec = "30s";
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
|
|
||||||
|
# hardening :
|
||||||
|
# Filesystem access
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true" ;
|
||||||
|
PrivateTmp = true;
|
||||||
|
ReadWritePaths = "/dev/net/tun";
|
||||||
|
PrivateDevices = false;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
# Caps
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
# Misc.
|
||||||
|
LockPersonality = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
listToAttrs (
|
||||||
|
mapAttrsToList
|
||||||
|
(name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
|
||||||
|
cfg.clients
|
||||||
|
) // {
|
||||||
|
iodined = mkIf (cfg.server.enable) {
|
||||||
|
description = "iodine, ip over dns server daemon";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${builtins.toString cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
|
||||||
|
serviceConfig = {
|
||||||
|
# Filesystem access
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true" ;
|
||||||
|
PrivateTmp = true;
|
||||||
|
ReadWritePaths = "/dev/net/tun";
|
||||||
|
PrivateDevices = false;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
# Caps
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
# Misc.
|
||||||
|
LockPersonality = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
in
|
|
||||||
listToAttrs (
|
|
||||||
mapAttrsToList
|
|
||||||
(name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
|
|
||||||
cfg.clients
|
|
||||||
) // {
|
|
||||||
iodined = mkIf (cfg.server.enable) {
|
|
||||||
description = "iodine, ip over dns server daemon";
|
|
||||||
after = [ "network.target" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.${iodinedUser} = {
|
users.users.${iodinedUser} = {
|
||||||
uid = config.ids.uids.iodined;
|
uid = config.ids.uids.iodined;
|
||||||
|
@ -65,7 +65,7 @@ let
|
|||||||
let
|
let
|
||||||
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
|
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
|
||||||
destinationIP = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 0;
|
destinationIP = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 0;
|
||||||
destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 1;
|
destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else builtins.replaceStrings ["-"] [":"] (elemAt m 1);
|
||||||
in ''
|
in ''
|
||||||
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from the host itself
|
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from the host itself
|
||||||
iptables -w -t nat -A nixos-nat-out \
|
iptables -w -t nat -A nixos-nat-out \
|
||||||
|
75
nixos/modules/services/networking/nix-store-gcs-proxy.nix
Normal file
75
nixos/modules/services/networking/nix-store-gcs-proxy.nix
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
opts = { name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
example = true;
|
||||||
|
description = "Whether to enable proxy for this bucket";
|
||||||
|
};
|
||||||
|
bucketName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
example = "my-bucket-name";
|
||||||
|
description = "Name of Google storage bucket";
|
||||||
|
};
|
||||||
|
address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "localhost:3000";
|
||||||
|
description = "The address of the proxy.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
enabledProxies = lib.filterAttrs (n: v: v.enable) config.services.nix-store-gcs-proxy;
|
||||||
|
mapProxies = function: lib.mkMerge (lib.mapAttrsToList function enabledProxies);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.nix-store-gcs-proxy = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule opts);
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
An attribute set describing an HTTP to GCS proxy that allows us to use GCS
|
||||||
|
bucket via HTTP protocol.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config.systemd.services = mapProxies (name: cfg: {
|
||||||
|
"nix-store-gcs-proxy-${name}" = {
|
||||||
|
description = "A HTTP nix store that proxies requests to Google Storage";
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
RestartSec = 5;
|
||||||
|
StartLimitInterval = 10;
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.nix-store-gcs-proxy}/bin/nix-store-gcs-proxy \
|
||||||
|
--bucket-name ${cfg.bucketName} \
|
||||||
|
--addr ${cfg.address}
|
||||||
|
'';
|
||||||
|
|
||||||
|
DynamicUser = true;
|
||||||
|
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
LockPersonality = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
meta.maintainers = [ maintainers.mrkkrp ];
|
||||||
|
}
|
@ -23,6 +23,8 @@ let
|
|||||||
restrict -6 ::1
|
restrict -6 ::1
|
||||||
|
|
||||||
${toString (map (server: "server " + server + " iburst\n") cfg.servers)}
|
${toString (map (server: "server " + server + " iburst\n") cfg.servers)}
|
||||||
|
|
||||||
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup ${toString cfg.extraFlags}";
|
ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup ${toString cfg.extraFlags}";
|
||||||
@ -81,6 +83,17 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
example = ''
|
||||||
|
fudge 127.127.1.0 stratum 10
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Additional text appended to <filename>ntp.conf</filename>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraFlags = mkOption {
|
extraFlags = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
description = "Extra flags passed to the ntpd command.";
|
description = "Extra flags passed to the ntpd command.";
|
||||||
|
@ -244,7 +244,7 @@ in
|
|||||||
group = "rslsync";
|
group = "rslsync";
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups = [ { name = "rslsync"; } ];
|
users.groups.rslsync = {};
|
||||||
|
|
||||||
systemd.services.resilio = with pkgs; {
|
systemd.services.resilio = with pkgs; {
|
||||||
description = "Resilio Sync Service";
|
description = "Resilio Sync Service";
|
||||||
|
@ -26,13 +26,14 @@ in {
|
|||||||
description = "The shorewall package to use.";
|
description = "The shorewall package to use.";
|
||||||
};
|
};
|
||||||
configs = lib.mkOption {
|
configs = lib.mkOption {
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.lines;
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = ''
|
||||||
This option defines the Shorewall configs.
|
This option defines the Shorewall configs.
|
||||||
The attribute name defines the name of the config,
|
The attribute name defines the name of the config,
|
||||||
and the attribute value defines the content of the config.
|
and the attribute value defines the content of the config.
|
||||||
'';
|
'';
|
||||||
|
apply = lib.mapAttrs (name: text: pkgs.writeText "${name}" text);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -62,7 +63,7 @@ in {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
environment = {
|
environment = {
|
||||||
etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {text=conf;}) cfg.configs;
|
etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {source=conf;}) cfg.configs;
|
||||||
systemPackages = [ cfg.package ];
|
systemPackages = [ cfg.package ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -26,13 +26,14 @@ in {
|
|||||||
description = "The shorewall package to use.";
|
description = "The shorewall package to use.";
|
||||||
};
|
};
|
||||||
configs = lib.mkOption {
|
configs = lib.mkOption {
|
||||||
type = types.attrsOf types.str;
|
type = types.attrsOf types.lines;
|
||||||
default = {};
|
default = {};
|
||||||
description = ''
|
description = ''
|
||||||
This option defines the Shorewall configs.
|
This option defines the Shorewall configs.
|
||||||
The attribute name defines the name of the config,
|
The attribute name defines the name of the config,
|
||||||
and the attribute value defines the content of the config.
|
and the attribute value defines the content of the config.
|
||||||
'';
|
'';
|
||||||
|
apply = lib.mapAttrs (name: text: pkgs.writeText "${name}" text);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -62,7 +63,7 @@ in {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
environment = {
|
environment = {
|
||||||
etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {text=conf;}) cfg.configs;
|
etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {source=conf;}) cfg.configs;
|
||||||
systemPackages = [ cfg.package ];
|
systemPackages = [ cfg.package ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
61
nixos/modules/services/networking/smartdns.nix
Normal file
61
nixos/modules/services/networking/smartdns.nix
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{ lib, pkgs, config, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib.types) attrsOf coercedTo listOf oneOf str int bool;
|
||||||
|
cfg = config.services.smartdns;
|
||||||
|
|
||||||
|
confFile = pkgs.writeText "smartdns.conf" (with generators;
|
||||||
|
toKeyValue {
|
||||||
|
mkKeyValue = mkKeyValueDefault {
|
||||||
|
mkValueString = v:
|
||||||
|
if isBool v then
|
||||||
|
if v then "yes" else "no"
|
||||||
|
else
|
||||||
|
mkValueStringDefault { } v;
|
||||||
|
} " ";
|
||||||
|
listsAsDuplicateKeys =
|
||||||
|
true; # Allowing duplications because we need to deal with multiple entries with the same key.
|
||||||
|
} cfg.settings);
|
||||||
|
in {
|
||||||
|
options.services.smartdns = {
|
||||||
|
enable = mkEnableOption "SmartDNS DNS server";
|
||||||
|
|
||||||
|
bindPort = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 53;
|
||||||
|
description = "DNS listening port number.";
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type =
|
||||||
|
let atom = oneOf [ str int bool ];
|
||||||
|
in attrsOf (coercedTo atom toList (listOf atom));
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
bind = ":5353 -no-rule -group example";
|
||||||
|
cache-size = 4096;
|
||||||
|
server-tls = [ "8.8.8.8:853" "1.1.1.1:853" ];
|
||||||
|
server-https = "https://cloudflare-dns.com/dns-query -exclude-default-group";
|
||||||
|
prefetch-domain = true;
|
||||||
|
speed-check-mode = "ping,tcp:80";
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
A set that will be generated into configuration file, see the <link xlink:href="https://github.com/pymumu/smartdns/blob/master/ReadMe_en.md#configuration-parameter">SmartDNS README</link> for details of configuration parameters.
|
||||||
|
You could override the options here like <option>services.smartdns.bindPort</option> by writing <literal>settings.bind = ":5353 -no-rule -group example";</literal>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.smartdns.settings.bind = mkDefault ":${toString cfg.bindPort}";
|
||||||
|
|
||||||
|
systemd.packages = [ pkgs.smartdns ];
|
||||||
|
systemd.services.smartdns.wantedBy = [ "multi-user.target" ];
|
||||||
|
environment.etc."smartdns/smartdns.conf".source = confFile;
|
||||||
|
environment.etc."default/smartdns".source =
|
||||||
|
"${pkgs.smartdns}/etc/default/smartdns";
|
||||||
|
};
|
||||||
|
}
|
@ -17,7 +17,7 @@ let
|
|||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
ssh-keygen -f mock-hostkey -N ""
|
ssh-keygen -q -f mock-hostkey -N ""
|
||||||
sshd -t -f $out -h mock-hostkey
|
sshd -t -f $out -h mock-hostkey
|
||||||
'';
|
'';
|
||||||
|
|
||||||
@ -238,6 +238,26 @@ in
|
|||||||
description = "Files from which authorized keys are read.";
|
description = "Files from which authorized keys are read.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
authorizedKeysCommand = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "none";
|
||||||
|
description = ''
|
||||||
|
Specifies a program to be used to look up the user's public
|
||||||
|
keys. The program must be owned by root, not writable by group
|
||||||
|
or others and specified by an absolute path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
authorizedKeysCommandUser = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "nobody";
|
||||||
|
description = ''
|
||||||
|
Specifies the user under whose account the AuthorizedKeysCommand
|
||||||
|
is run. It is recommended to use a dedicated user that has no
|
||||||
|
other role on the host than running authorized keys commands.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
kexAlgorithms = mkOption {
|
kexAlgorithms = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [
|
default = [
|
||||||
@ -485,6 +505,10 @@ in
|
|||||||
PrintMotd no # handled by pam_motd
|
PrintMotd no # handled by pam_motd
|
||||||
|
|
||||||
AuthorizedKeysFile ${toString cfg.authorizedKeysFiles}
|
AuthorizedKeysFile ${toString cfg.authorizedKeysFiles}
|
||||||
|
${optionalString (cfg.authorizedKeysCommand != "none") ''
|
||||||
|
AuthorizedKeysCommand ${cfg.authorizedKeysCommand}
|
||||||
|
AuthorizedKeysCommandUser ${cfg.authorizedKeysCommandUser}
|
||||||
|
''}
|
||||||
|
|
||||||
${flip concatMapStrings cfg.hostKeys (k: ''
|
${flip concatMapStrings cfg.hostKeys (k: ''
|
||||||
HostKey ${k.path}
|
HostKey ${k.path}
|
||||||
|
@ -205,6 +205,7 @@ in
|
|||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
Type = "notify";
|
||||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||||
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
|
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
|
||||||
ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}";
|
ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}";
|
||||||
|
@ -3,32 +3,35 @@
|
|||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
cfg = config.services.supybot;
|
cfg = config.services.supybot;
|
||||||
|
isStateDirHome = hasPrefix "/home/" cfg.stateDir;
|
||||||
|
isStateDirVar = cfg.stateDir == "/var/lib/supybot";
|
||||||
|
pyEnv = pkgs.python3.withPackages (p: [ p.limnoria ] ++ (cfg.extraPackages p));
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
services.supybot = {
|
services.supybot = {
|
||||||
|
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Enable Supybot, an IRC bot";
|
description = "Enable Supybot, an IRC bot (also known as Limnoria).";
|
||||||
};
|
};
|
||||||
|
|
||||||
stateDir = mkOption {
|
stateDir = mkOption {
|
||||||
# Setting this to /var/lib/supybot caused useradd to fail
|
type = types.path;
|
||||||
default = "/home/supybot";
|
default = if versionAtLeast config.system.stateVersion "20.09"
|
||||||
|
then "/var/lib/supybot"
|
||||||
|
else "/home/supybot";
|
||||||
|
defaultText = "/var/lib/supybot";
|
||||||
description = "The root directory, logs and plugins are stored here";
|
description = "The root directory, logs and plugins are stored here";
|
||||||
};
|
};
|
||||||
|
|
||||||
configFile = mkOption {
|
configFile = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
description = ''
|
description = ''
|
||||||
Path to a supybot config file. This can be generated by
|
Path to initial supybot config file. This can be generated by
|
||||||
running supybot-wizard.
|
running supybot-wizard.
|
||||||
|
|
||||||
Note: all paths should include the full path to the stateDir
|
Note: all paths should include the full path to the stateDir
|
||||||
@ -36,21 +39,54 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
plugins = mkOption {
|
||||||
|
type = types.attrsOf types.path;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Attribute set of additional plugins that will be symlinked to the
|
||||||
|
<filename>plugin</filename> subdirectory.
|
||||||
|
|
||||||
|
Please note that you still need to add the plugins to the config
|
||||||
|
file (or with <literal>!load</literal>) using their attribute name.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
let
|
||||||
|
plugins = pkgs.fetchzip {
|
||||||
|
url = "https://github.com/ProgVal/Supybot-plugins/archive/57c2450c.zip";
|
||||||
|
sha256 = "077snf84ibnva3sbpzdfpfma6hcdw7dflwnhg6pw7mgnf0nd84qd";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
Wikipedia = "''${plugins}/Wikipedia";
|
||||||
|
Decide = ./supy-decide;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraPackages = mkOption {
|
||||||
|
default = p: [];
|
||||||
|
description = ''
|
||||||
|
Extra Python packages available to supybot plugins. The
|
||||||
|
value must be a function which receives the attrset defined
|
||||||
|
in <varname>python3Packages</varname> as the sole argument.
|
||||||
|
'';
|
||||||
|
example = literalExample ''p: [ p.lxml p.requests ]'';
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.pythonPackages.limnoria ];
|
environment.systemPackages = [ pkgs.python3Packages.limnoria ];
|
||||||
|
|
||||||
users.users.supybot = {
|
users.users.supybot = {
|
||||||
uid = config.ids.uids.supybot;
|
uid = config.ids.uids.supybot;
|
||||||
group = "supybot";
|
group = "supybot";
|
||||||
description = "Supybot IRC bot user";
|
description = "Supybot IRC bot user";
|
||||||
home = cfg.stateDir;
|
home = cfg.stateDir;
|
||||||
createHome = true;
|
isSystemUser = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups.supybot = {
|
users.groups.supybot = {
|
||||||
@ -59,19 +95,16 @@ in
|
|||||||
|
|
||||||
systemd.services.supybot = {
|
systemd.services.supybot = {
|
||||||
description = "Supybot, an IRC bot";
|
description = "Supybot, an IRC bot";
|
||||||
|
documentation = [ "https://limnoria.readthedocs.io/" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
path = [ pkgs.pythonPackages.limnoria ];
|
|
||||||
preStart = ''
|
preStart = ''
|
||||||
cd ${cfg.stateDir}
|
|
||||||
mkdir -p backup conf data plugins logs/plugins tmp web
|
|
||||||
ln -sf ${cfg.configFile} supybot.cfg
|
|
||||||
# This needs to be created afresh every time
|
# This needs to be created afresh every time
|
||||||
rm -f supybot.cfg.bak
|
rm -f '${cfg.stateDir}/supybot.cfg.bak'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.pythonPackages.limnoria}/bin/supybot ${cfg.stateDir}/supybot.cfg";
|
ExecStart = "${pyEnv}/bin/supybot ${cfg.stateDir}/supybot.cfg";
|
||||||
PIDFile = "/run/supybot.pid";
|
PIDFile = "/run/supybot.pid";
|
||||||
User = "supybot";
|
User = "supybot";
|
||||||
Group = "supybot";
|
Group = "supybot";
|
||||||
@ -79,8 +112,50 @@ in
|
|||||||
Restart = "on-abort";
|
Restart = "on-abort";
|
||||||
StartLimitInterval = "5m";
|
StartLimitInterval = "5m";
|
||||||
StartLimitBurst = "1";
|
StartLimitBurst = "1";
|
||||||
|
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateMounts = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
LockPersonality = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
RemoveIPC = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
CapabilityBoundingSet = "";
|
||||||
|
ProtectSystem = "full";
|
||||||
|
}
|
||||||
|
// optionalAttrs isStateDirVar {
|
||||||
|
StateDirectory = "supybot";
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
}
|
||||||
|
// optionalAttrs (!isStateDirHome) {
|
||||||
|
ProtectHome = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d '${cfg.stateDir}' 0700 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/backup' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/conf' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/data' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/plugins' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/logs' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/logs/plugins' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/tmp' 0750 supybot supybot - -"
|
||||||
|
"d '${cfg.stateDir}/web' 0750 supybot supybot - -"
|
||||||
|
"L '${cfg.stateDir}/supybot.cfg' - - - - ${cfg.configFile}"
|
||||||
|
]
|
||||||
|
++ (flip mapAttrsToList cfg.plugins (name: dest:
|
||||||
|
"L+ '${cfg.stateDir}/plugins/${name}' - - - - ${dest}"
|
||||||
|
));
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
46
nixos/modules/services/networking/tailscale.nix
Normal file
46
nixos/modules/services/networking/tailscale.nix
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let cfg = config.services.tailscale;
|
||||||
|
in {
|
||||||
|
meta.maintainers = with maintainers; [ danderson mbaillie ];
|
||||||
|
|
||||||
|
options.services.tailscale = {
|
||||||
|
enable = mkEnableOption "Tailscale client daemon";
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.port;
|
||||||
|
default = 41641;
|
||||||
|
description = "The port to listen on for tunnel traffic (0=autoselect).";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.tailscale = {
|
||||||
|
description = "Tailscale client daemon";
|
||||||
|
|
||||||
|
after = [ "network-pre.target" ];
|
||||||
|
wants = [ "network-pre.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
unitConfig = {
|
||||||
|
StartLimitIntervalSec = 0;
|
||||||
|
StartLimitBurst = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart =
|
||||||
|
"${pkgs.tailscale}/bin/tailscaled --port ${toString cfg.port}";
|
||||||
|
|
||||||
|
RuntimeDirectory = "tailscale";
|
||||||
|
RuntimeDirectoryMode = 755;
|
||||||
|
|
||||||
|
StateDirectory = "tailscale";
|
||||||
|
StateDirectoryMode = 700;
|
||||||
|
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -133,8 +133,8 @@ let
|
|||||||
${optionalString cfg.enableVirtualUsers ''
|
${optionalString cfg.enableVirtualUsers ''
|
||||||
guest_enable=YES
|
guest_enable=YES
|
||||||
guest_username=vsftpd
|
guest_username=vsftpd
|
||||||
pam_service_name=vsftpd
|
|
||||||
''}
|
''}
|
||||||
|
pam_service_name=vsftpd
|
||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -428,7 +428,7 @@ in
|
|||||||
++ (attrValues (
|
++ (attrValues (
|
||||||
mapAttrs (name: value: {
|
mapAttrs (name: value: {
|
||||||
assertion = value.generatePrivateKeyFile -> (value.privateKey == null);
|
assertion = value.generatePrivateKeyFile -> (value.privateKey == null);
|
||||||
message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
|
message = "networking.wireguard.interfaces.${name}.generatePrivateKeyFile must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
|
||||||
}) cfg.interfaces))
|
}) cfg.interfaces))
|
||||||
++ map ({ interfaceName, peer, ... }: {
|
++ map ({ interfaceName, peer, ... }: {
|
||||||
assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null);
|
assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null);
|
||||||
|
@ -69,13 +69,14 @@ in
|
|||||||
environment.systemPackages = [ cfg.package ];
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
|
||||||
# Prevent systemd from potentially changing the MAC address
|
# Prevent systemd from potentially changing the MAC address
|
||||||
environment.etc."systemd/network/50-zerotier.link".text = ''
|
systemd.network.links."50-zerotier" = {
|
||||||
[Match]
|
matchConfig = {
|
||||||
OriginalName=zt*
|
OriginalName = "zt*";
|
||||||
|
};
|
||||||
[Link]
|
linkConfig = {
|
||||||
AutoNegotiation=false
|
AutoNegotiation = false;
|
||||||
MACAddressPolicy=none
|
MACAddressPolicy = "none";
|
||||||
'';
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
99
nixos/modules/services/wayland/cage.nix
Normal file
99
nixos/modules/services/wayland/cage.nix
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.cage;
|
||||||
|
in {
|
||||||
|
options.services.cage.enable = mkEnableOption "cage kiosk service";
|
||||||
|
|
||||||
|
options.services.cage.user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "demo";
|
||||||
|
description = ''
|
||||||
|
User to log-in as.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
options.services.cage.extraArguments = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
defaultText = "[]";
|
||||||
|
description = "Additional command line arguments to pass to Cage.";
|
||||||
|
example = ["-d"];
|
||||||
|
};
|
||||||
|
|
||||||
|
options.services.cage.program = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "${pkgs.xterm}/bin/xterm";
|
||||||
|
description = ''
|
||||||
|
Program to run in cage.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
# The service is partially based off of the one provided in the
|
||||||
|
# cage wiki at
|
||||||
|
# https://github.com/Hjdskes/cage/wiki/Starting-Cage-on-boot-with-systemd.
|
||||||
|
systemd.services."cage-tty1" = {
|
||||||
|
enable = true;
|
||||||
|
after = [
|
||||||
|
"systemd-user-sessions.service"
|
||||||
|
"plymouth-start.service"
|
||||||
|
"plymouth-quit.service"
|
||||||
|
"systemd-logind.service"
|
||||||
|
"getty@tty1.service"
|
||||||
|
];
|
||||||
|
before = [ "graphical.target" ];
|
||||||
|
wants = [ "dbus.socket" "systemd-logind.service" "plymouth-quit.service"];
|
||||||
|
wantedBy = [ "graphical.target" ];
|
||||||
|
conflicts = [ "getty@tty1.service" ];
|
||||||
|
|
||||||
|
restartIfChanged = false;
|
||||||
|
unitConfig.ConditionPathExists = "/dev/tty1";
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = ''
|
||||||
|
${pkgs.cage}/bin/cage \
|
||||||
|
${escapeShellArgs cfg.extraArguments} \
|
||||||
|
-- ${cfg.program}
|
||||||
|
'';
|
||||||
|
User = cfg.user;
|
||||||
|
|
||||||
|
IgnoreSIGPIPE = "no";
|
||||||
|
|
||||||
|
# Log this user with utmp, letting it show up with commands 'w' and
|
||||||
|
# 'who'. This is needed since we replace (a)getty.
|
||||||
|
UtmpIdentifier = "%n";
|
||||||
|
UtmpMode = "user";
|
||||||
|
# A virtual terminal is needed.
|
||||||
|
TTYPath = "/dev/tty1";
|
||||||
|
TTYReset = "yes";
|
||||||
|
TTYVHangup = "yes";
|
||||||
|
TTYVTDisallocate = "yes";
|
||||||
|
# Fail to start if not controlling the virtual terminal.
|
||||||
|
StandardInput = "tty-fail";
|
||||||
|
StandardOutput = "syslog";
|
||||||
|
StandardError = "syslog";
|
||||||
|
# Set up a full (custom) user session for the user, required by Cage.
|
||||||
|
PAMName = "cage";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
security.pam.services.cage.text = ''
|
||||||
|
auth required pam_unix.so nullok
|
||||||
|
account required pam_unix.so
|
||||||
|
session required pam_unix.so
|
||||||
|
session required ${pkgs.systemd}/lib/security/pam_systemd.so
|
||||||
|
'';
|
||||||
|
|
||||||
|
hardware.opengl.enable = mkDefault true;
|
||||||
|
|
||||||
|
systemd.targets.graphical.wants = [ "cage-tty1.service" ];
|
||||||
|
|
||||||
|
systemd.defaultUnit = "graphical.target";
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with lib.maintainers; [ matthewbauer flokli ];
|
||||||
|
|
||||||
|
}
|
@ -87,10 +87,17 @@ let
|
|||||||
${optionalString (cfg.sslDhparam != null) "ssl_dhparam ${cfg.sslDhparam};"}
|
${optionalString (cfg.sslDhparam != null) "ssl_dhparam ${cfg.sslDhparam};"}
|
||||||
|
|
||||||
${optionalString (cfg.recommendedTlsSettings) ''
|
${optionalString (cfg.recommendedTlsSettings) ''
|
||||||
ssl_session_cache shared:SSL:42m;
|
# Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
|
||||||
ssl_session_timeout 23m;
|
|
||||||
ssl_ecdh_curve secp384r1;
|
ssl_session_timeout 1d;
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
# Breaks forward secrecy: https://github.com/mozilla/server-side-tls/issues/135
|
||||||
|
ssl_session_tickets off;
|
||||||
|
# We don't enable insecure ciphers by default, so this allows
|
||||||
|
# clients to pick the most performant, per https://github.com/mozilla/server-side-tls/issues/260
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
|
||||||
|
# OCSP stapling
|
||||||
ssl_stapling on;
|
ssl_stapling on;
|
||||||
ssl_stapling_verify on;
|
ssl_stapling_verify on;
|
||||||
''}
|
''}
|
||||||
@ -487,8 +494,9 @@ in
|
|||||||
|
|
||||||
sslCiphers = mkOption {
|
sslCiphers = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL";
|
# Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
|
||||||
description = "Ciphers to choose from when negotiating tls handshakes.";
|
default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
|
||||||
|
description = "Ciphers to choose from when negotiating TLS handshakes.";
|
||||||
};
|
};
|
||||||
|
|
||||||
sslProtocols = mkOption {
|
sslProtocols = mkOption {
|
||||||
|
@ -32,7 +32,7 @@ let
|
|||||||
inherit plugins;
|
inherit plugins;
|
||||||
} // removeAttrs c [ "type" "pythonPackages" ]
|
} // removeAttrs c [ "type" "pythonPackages" ]
|
||||||
// optionalAttrs (python != null) {
|
// optionalAttrs (python != null) {
|
||||||
pythonpath = "${pythonEnv}/${python.sitePackages}";
|
pyhome = "${pythonEnv}";
|
||||||
env =
|
env =
|
||||||
# Argh, uwsgi expects list of key-values there instead of a dictionary.
|
# Argh, uwsgi expects list of key-values there instead of a dictionary.
|
||||||
let env' = c.env or [];
|
let env' = c.env or [];
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
dmcfg = config.services.xserver.displayManager;
|
||||||
|
ldmcfg = dmcfg.lightdm;
|
||||||
|
cfg = ldmcfg.greeters.tiny;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.xserver.displayManager.lightdm.greeters.tiny = {
|
||||||
|
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to enable lightdm-tiny-greeter as the lightdm greeter.
|
||||||
|
|
||||||
|
Note that this greeter starts only the default X session.
|
||||||
|
You can configure the default X session using
|
||||||
|
<xref linkend="opt-services.xserver.displayManager.defaultSession"/>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
label = {
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Username";
|
||||||
|
description = ''
|
||||||
|
The string to represent the user_text label.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
pass = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Password";
|
||||||
|
description = ''
|
||||||
|
The string to represent the pass_text label.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Section to describe style and ui.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (ldmcfg.enable && cfg.enable) {
|
||||||
|
|
||||||
|
services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
|
||||||
|
|
||||||
|
nixpkgs.config.lightdm-tiny-greeter.conf =
|
||||||
|
let
|
||||||
|
configHeader = ''
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
static const char *user_text = "${cfg.label.user}";
|
||||||
|
static const char *pass_text = "${cfg.label.pass}";
|
||||||
|
static const char *session = "${dmcfg.defaultSession}";
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
optionalString (cfg.extraConfig != "")
|
||||||
|
(configHeader + cfg.extraConfig);
|
||||||
|
|
||||||
|
services.xserver.displayManager.lightdm.greeter =
|
||||||
|
mkDefault {
|
||||||
|
package = pkgs.lightdm-tiny-greeter.xgreeters;
|
||||||
|
name = "lightdm-tiny-greeter";
|
||||||
|
};
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = dmcfg.defaultSession != null;
|
||||||
|
message = ''
|
||||||
|
Please set: services.xserver.displayManager.defaultSession
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
@ -77,6 +77,7 @@ in
|
|||||||
./lightdm-greeters/mini.nix
|
./lightdm-greeters/mini.nix
|
||||||
./lightdm-greeters/enso-os.nix
|
./lightdm-greeters/enso-os.nix
|
||||||
./lightdm-greeters/pantheon.nix
|
./lightdm-greeters/pantheon.nix
|
||||||
|
./lightdm-greeters/tiny.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
@ -183,7 +183,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
|
|||||||
# active after the system has resumed, which probably
|
# active after the system has resumed, which probably
|
||||||
# should not be the case. Just ignore it.
|
# should not be the case. Just ignore it.
|
||||||
if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") {
|
if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") {
|
||||||
unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no")) {
|
unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
|
||||||
$unitsToStart{$unit} = 1;
|
$unitsToStart{$unit} = 1;
|
||||||
recordUnit($startListFile, $unit);
|
recordUnit($startListFile, $unit);
|
||||||
# Don't spam the user with target units that always get started.
|
# Don't spam the user with target units that always get started.
|
||||||
@ -222,7 +222,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
|
|||||||
$unitsToReload{$unit} = 1;
|
$unitsToReload{$unit} = 1;
|
||||||
recordUnit($reloadListFile, $unit);
|
recordUnit($reloadListFile, $unit);
|
||||||
}
|
}
|
||||||
elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) {
|
elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
|
||||||
$unitsToSkip{$unit} = 1;
|
$unitsToSkip{$unit} = 1;
|
||||||
} else {
|
} else {
|
||||||
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
|
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
|
||||||
|
@ -15,6 +15,7 @@ let
|
|||||||
map (childConfig:
|
map (childConfig:
|
||||||
(import ../../../lib/eval-config.nix {
|
(import ../../../lib/eval-config.nix {
|
||||||
inherit baseModules;
|
inherit baseModules;
|
||||||
|
system = config.nixpkgs.initialSystem;
|
||||||
modules =
|
modules =
|
||||||
(optionals inheritParent modules)
|
(optionals inheritParent modules)
|
||||||
++ [ ./no-clone.nix ]
|
++ [ ./no-clone.nix ]
|
||||||
|
@ -6,7 +6,11 @@ let
|
|||||||
|
|
||||||
cfg = config.boot.initrd.network;
|
cfg = config.boot.initrd.network;
|
||||||
|
|
||||||
dhcpinterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
|
dhcpInterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
|
||||||
|
doDhcp = config.networking.useDHCP || dhcpInterfaces != [];
|
||||||
|
dhcpIfShellExpr = if config.networking.useDHCP
|
||||||
|
then "$(ls /sys/class/net/ | grep -v ^lo$)"
|
||||||
|
else lib.concatMapStringsSep " " lib.escapeShellArg dhcpInterfaces;
|
||||||
|
|
||||||
udhcpcScript = pkgs.writeScript "udhcp-script"
|
udhcpcScript = pkgs.writeScript "udhcp-script"
|
||||||
''
|
''
|
||||||
@ -62,6 +66,16 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boot.initrd.network.flushBeforeStage2 = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to clear the configuration of the interfaces that were set up in
|
||||||
|
the initrd right before stage 2 takes over. Stage 2 will do the regular network
|
||||||
|
configuration based on the NixOS networking options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
boot.initrd.network.udhcpc.extraArgs = mkOption {
|
boot.initrd.network.udhcpc.extraArgs = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
@ -89,49 +103,45 @@ in
|
|||||||
boot.initrd.kernelModules = [ "af_packet" ];
|
boot.initrd.kernelModules = [ "af_packet" ];
|
||||||
|
|
||||||
boot.initrd.extraUtilsCommands = ''
|
boot.initrd.extraUtilsCommands = ''
|
||||||
copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig
|
copy_bin_and_libs ${pkgs.klibc}/lib/klibc/bin.static/ipconfig
|
||||||
'';
|
'';
|
||||||
|
|
||||||
boot.initrd.preLVMCommands = mkBefore (
|
boot.initrd.preLVMCommands = mkBefore (
|
||||||
# Search for interface definitions in command line.
|
# Search for interface definitions in command line.
|
||||||
''
|
''
|
||||||
|
ifaces=""
|
||||||
for o in $(cat /proc/cmdline); do
|
for o in $(cat /proc/cmdline); do
|
||||||
case $o in
|
case $o in
|
||||||
ip=*)
|
ip=*)
|
||||||
ipconfig $o && hasNetwork=1
|
ipconfig $o && ifaces="$ifaces $(echo $o | cut -d: -f6)"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
''
|
''
|
||||||
|
|
||||||
# Otherwise, use DHCP.
|
# Otherwise, use DHCP.
|
||||||
+ optionalString (config.networking.useDHCP || dhcpinterfaces != []) ''
|
+ optionalString doDhcp ''
|
||||||
if [ -z "$hasNetwork" ]; then
|
# Bring up all interfaces.
|
||||||
|
for iface in ${dhcpIfShellExpr}; do
|
||||||
|
echo "bringing up network interface $iface..."
|
||||||
|
ip link set "$iface" up && ifaces="$ifaces $iface"
|
||||||
|
done
|
||||||
|
|
||||||
# Bring up all interfaces.
|
# Acquire DHCP leases.
|
||||||
for iface in $(ls /sys/class/net/); do
|
for iface in ${dhcpIfShellExpr}; do
|
||||||
echo "bringing up network interface $iface..."
|
echo "acquiring IP address via DHCP on $iface..."
|
||||||
ip link set "$iface" up
|
udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs}
|
||||||
done
|
done
|
||||||
|
|
||||||
# Acquire DHCP leases.
|
|
||||||
for iface in ${ if config.networking.useDHCP then
|
|
||||||
"$(ls /sys/class/net/ | grep -v ^lo$)"
|
|
||||||
else
|
|
||||||
lib.concatMapStringsSep " " lib.escapeShellArg dhcpinterfaces
|
|
||||||
}; do
|
|
||||||
echo "acquiring IP address via DHCP on $iface..."
|
|
||||||
udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
''
|
''
|
||||||
|
|
||||||
+ ''
|
+ cfg.postCommands);
|
||||||
if [ -n "$hasNetwork" ]; then
|
|
||||||
echo "networking is up!"
|
boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
|
||||||
${cfg.postCommands}
|
for iface in $ifaces; do
|
||||||
fi
|
ip address flush "$iface"
|
||||||
'');
|
ip link down "$iface"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,139 +192,144 @@ in
|
|||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
|
|
||||||
config = mkIf (!config.boot.isContainer) {
|
config = mkMerge
|
||||||
|
[ (mkIf config.boot.initrd.enable {
|
||||||
|
boot.initrd.availableKernelModules =
|
||||||
|
[ # Note: most of these (especially the SATA/PATA modules)
|
||||||
|
# shouldn't be included by default since nixos-generate-config
|
||||||
|
# detects them, but I'm keeping them for now for backwards
|
||||||
|
# compatibility.
|
||||||
|
|
||||||
system.build = { inherit kernel; };
|
# Some SATA/PATA stuff.
|
||||||
|
"ahci"
|
||||||
|
"sata_nv"
|
||||||
|
"sata_via"
|
||||||
|
"sata_sis"
|
||||||
|
"sata_uli"
|
||||||
|
"ata_piix"
|
||||||
|
"pata_marvell"
|
||||||
|
|
||||||
system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
|
# Standard SCSI stuff.
|
||||||
|
"sd_mod"
|
||||||
|
"sr_mod"
|
||||||
|
|
||||||
# Implement consoleLogLevel both in early boot and using sysctl
|
# SD cards and internal eMMC drives.
|
||||||
# (so you don't need to reboot to have changes take effect).
|
"mmc_block"
|
||||||
boot.kernelParams =
|
|
||||||
[ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
|
|
||||||
optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
|
|
||||||
|
|
||||||
boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
|
# Support USB keyboards, in case the boot fails and we only have
|
||||||
|
# a USB keyboard, or for LUKS passphrase prompt.
|
||||||
|
"uhci_hcd"
|
||||||
|
"ehci_hcd"
|
||||||
|
"ehci_pci"
|
||||||
|
"ohci_hcd"
|
||||||
|
"ohci_pci"
|
||||||
|
"xhci_hcd"
|
||||||
|
"xhci_pci"
|
||||||
|
"usbhid"
|
||||||
|
"hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
|
||||||
|
"hid_logitech_hidpp" "hid_logitech_dj"
|
||||||
|
|
||||||
boot.kernelModules = [ "loop" "atkbd" ];
|
] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
|
||||||
|
# Misc. x86 keyboard stuff.
|
||||||
|
"pcips2" "atkbd" "i8042"
|
||||||
|
|
||||||
boot.initrd.availableKernelModules =
|
# x86 RTC needed by the stage 2 init script.
|
||||||
[ # Note: most of these (especially the SATA/PATA modules)
|
"rtc_cmos"
|
||||||
# shouldn't be included by default since nixos-generate-config
|
];
|
||||||
# detects them, but I'm keeping them for now for backwards
|
|
||||||
# compatibility.
|
|
||||||
|
|
||||||
# Some SATA/PATA stuff.
|
boot.initrd.kernelModules =
|
||||||
"ahci"
|
[ # For LVM.
|
||||||
"sata_nv"
|
"dm_mod"
|
||||||
"sata_via"
|
];
|
||||||
"sata_sis"
|
})
|
||||||
"sata_uli"
|
|
||||||
"ata_piix"
|
|
||||||
"pata_marvell"
|
|
||||||
|
|
||||||
# Standard SCSI stuff.
|
(mkIf (!config.boot.isContainer) {
|
||||||
"sd_mod"
|
system.build = { inherit kernel; };
|
||||||
"sr_mod"
|
|
||||||
|
|
||||||
# SD cards and internal eMMC drives.
|
system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
|
||||||
"mmc_block"
|
|
||||||
|
|
||||||
# Support USB keyboards, in case the boot fails and we only have
|
# Implement consoleLogLevel both in early boot and using sysctl
|
||||||
# a USB keyboard, or for LUKS passphrase prompt.
|
# (so you don't need to reboot to have changes take effect).
|
||||||
"uhci_hcd"
|
boot.kernelParams =
|
||||||
"ehci_hcd"
|
[ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
|
||||||
"ehci_pci"
|
optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
|
||||||
"ohci_hcd"
|
|
||||||
"ohci_pci"
|
|
||||||
"xhci_hcd"
|
|
||||||
"xhci_pci"
|
|
||||||
"usbhid"
|
|
||||||
"hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
|
|
||||||
"hid_logitech_hidpp" "hid_logitech_dj"
|
|
||||||
|
|
||||||
] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
|
boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
|
||||||
# Misc. x86 keyboard stuff.
|
|
||||||
"pcips2" "atkbd" "i8042"
|
|
||||||
|
|
||||||
# x86 RTC needed by the stage 2 init script.
|
boot.kernelModules = [ "loop" "atkbd" ];
|
||||||
"rtc_cmos"
|
|
||||||
];
|
|
||||||
|
|
||||||
boot.initrd.kernelModules =
|
# The Linux kernel >= 2.6.27 provides firmware.
|
||||||
[ # For LVM.
|
hardware.firmware = [ kernel ];
|
||||||
"dm_mod"
|
|
||||||
];
|
|
||||||
|
|
||||||
# The Linux kernel >= 2.6.27 provides firmware.
|
# Create /etc/modules-load.d/nixos.conf, which is read by
|
||||||
hardware.firmware = [ kernel ];
|
# systemd-modules-load.service to load required kernel modules.
|
||||||
|
environment.etc =
|
||||||
# Create /etc/modules-load.d/nixos.conf, which is read by
|
{ "modules-load.d/nixos.conf".source = kernelModulesConf;
|
||||||
# systemd-modules-load.service to load required kernel modules.
|
|
||||||
environment.etc =
|
|
||||||
{ "modules-load.d/nixos.conf".source = kernelModulesConf;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.systemd-modules-load =
|
|
||||||
{ wantedBy = [ "multi-user.target" ];
|
|
||||||
restartTriggers = [ kernelModulesConf ];
|
|
||||||
serviceConfig =
|
|
||||||
{ # Ignore failed module loads. Typically some of the
|
|
||||||
# modules in ‘boot.kernelModules’ are "nice to have but
|
|
||||||
# not required" (e.g. acpi-cpufreq), so we don't want to
|
|
||||||
# barf on those.
|
|
||||||
SuccessExitStatus = "0 1";
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
lib.kernelConfig = {
|
systemd.services.systemd-modules-load =
|
||||||
isYes = option: {
|
{ wantedBy = [ "multi-user.target" ];
|
||||||
assertion = config: config.isYes option;
|
restartTriggers = [ kernelModulesConf ];
|
||||||
message = "CONFIG_${option} is not yes!";
|
serviceConfig =
|
||||||
configLine = "CONFIG_${option}=y";
|
{ # Ignore failed module loads. Typically some of the
|
||||||
};
|
# modules in ‘boot.kernelModules’ are "nice to have but
|
||||||
|
# not required" (e.g. acpi-cpufreq), so we don't want to
|
||||||
|
# barf on those.
|
||||||
|
SuccessExitStatus = "0 1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
isNo = option: {
|
lib.kernelConfig = {
|
||||||
assertion = config: config.isNo option;
|
isYes = option: {
|
||||||
message = "CONFIG_${option} is not no!";
|
assertion = config: config.isYes option;
|
||||||
configLine = "CONFIG_${option}=n";
|
message = "CONFIG_${option} is not yes!";
|
||||||
};
|
configLine = "CONFIG_${option}=y";
|
||||||
|
};
|
||||||
|
|
||||||
isModule = option: {
|
isNo = option: {
|
||||||
assertion = config: config.isModule option;
|
assertion = config: config.isNo option;
|
||||||
message = "CONFIG_${option} is not built as a module!";
|
message = "CONFIG_${option} is not no!";
|
||||||
configLine = "CONFIG_${option}=m";
|
configLine = "CONFIG_${option}=n";
|
||||||
};
|
};
|
||||||
|
|
||||||
### Usually you will just want to use these two
|
isModule = option: {
|
||||||
# True if yes or module
|
assertion = config: config.isModule option;
|
||||||
isEnabled = option: {
|
message = "CONFIG_${option} is not built as a module!";
|
||||||
assertion = config: config.isEnabled option;
|
configLine = "CONFIG_${option}=m";
|
||||||
message = "CONFIG_${option} is not enabled!";
|
};
|
||||||
configLine = "CONFIG_${option}=y";
|
|
||||||
};
|
|
||||||
|
|
||||||
# True if no or omitted
|
### Usually you will just want to use these two
|
||||||
isDisabled = option: {
|
# True if yes or module
|
||||||
assertion = config: config.isDisabled option;
|
isEnabled = option: {
|
||||||
message = "CONFIG_${option} is not disabled!";
|
assertion = config: config.isEnabled option;
|
||||||
configLine = "CONFIG_${option}=n";
|
message = "CONFIG_${option} is not enabled!";
|
||||||
};
|
configLine = "CONFIG_${option}=y";
|
||||||
};
|
};
|
||||||
|
|
||||||
# The config options that all modules can depend upon
|
# True if no or omitted
|
||||||
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
isDisabled = option: {
|
||||||
# !!! Should this really be needed?
|
assertion = config: config.isDisabled option;
|
||||||
(isYes "MODULES")
|
message = "CONFIG_${option} is not disabled!";
|
||||||
(isYes "BINFMT_ELF")
|
configLine = "CONFIG_${option}=n";
|
||||||
] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# nixpkgs kernels are assumed to have all required features
|
# The config options that all modules can depend upon
|
||||||
assertions = if config.boot.kernelPackages.kernel ? features then [] else
|
system.requiredKernelConfig = with config.lib.kernelConfig;
|
||||||
let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
|
[
|
||||||
{ assertion = attrs.assertion cfg; inherit (attrs) message; }
|
# !!! Should this really be needed?
|
||||||
) config.system.requiredKernelConfig;
|
(isYes "MODULES")
|
||||||
|
(isYes "BINFMT_ELF")
|
||||||
|
] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
|
||||||
|
|
||||||
};
|
# nixpkgs kernels are assumed to have all required features
|
||||||
|
assertions = if config.boot.kernelPackages.kernel ? features then [] else
|
||||||
|
let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
|
||||||
|
{ assertion = attrs.assertion cfg; inherit (attrs) message; }
|
||||||
|
) config.system.requiredKernelConfig;
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,12 @@ let
|
|||||||
(assertOnlyFields [
|
(assertOnlyFields [
|
||||||
"PrivateKeyFile" "ListenPort" "FwMark"
|
"PrivateKeyFile" "ListenPort" "FwMark"
|
||||||
])
|
])
|
||||||
(assertRange "FwMark" 1 4294967295)
|
# The following check won't work on nix <= 2.2
|
||||||
|
# see https://github.com/NixOS/nix/pull/2378
|
||||||
|
#
|
||||||
|
# Add this again when we'll have drop the
|
||||||
|
# nix < 2.2 support.
|
||||||
|
# (assertRange "FwMark" 1 4294967295)
|
||||||
];
|
];
|
||||||
|
|
||||||
# NOTE The PresharedKey directive is missing on purpose here, please
|
# NOTE The PresharedKey directive is missing on purpose here, please
|
||||||
@ -181,7 +186,12 @@ let
|
|||||||
(assertOnlyFields [
|
(assertOnlyFields [
|
||||||
"InterfaceId" "Independent"
|
"InterfaceId" "Independent"
|
||||||
])
|
])
|
||||||
(assertRange "InterfaceId" 1 4294967295)
|
# The following check won't work on nix <= 2.2
|
||||||
|
# see https://github.com/NixOS/nix/pull/2378
|
||||||
|
#
|
||||||
|
# Add this again when we'll have drop the
|
||||||
|
# nix < 2.2 support.
|
||||||
|
# (assertRange "InterfaceId" 1 4294967295)
|
||||||
(assertValueOneOf "Independent" boolValues)
|
(assertValueOneOf "Independent" boolValues)
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -235,6 +245,26 @@ let
|
|||||||
(assertValueOneOf "AutoJoin" boolValues)
|
(assertValueOneOf "AutoJoin" boolValues)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
checkRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
|
||||||
|
(assertOnlyFields [
|
||||||
|
"TypeOfService" "From" "To" "FirewallMark" "Table" "Priority"
|
||||||
|
"IncomingInterface" "OutgoingInterface" "SourcePort" "DestinationPort"
|
||||||
|
"IPProtocol" "InvertRule" "Family"
|
||||||
|
])
|
||||||
|
(assertRange "TypeOfService" 0 255)
|
||||||
|
# The following check won't work on nix <= 2.2
|
||||||
|
# see https://github.com/NixOS/nix/pull/2378
|
||||||
|
#
|
||||||
|
# Add this again when we'll have drop the
|
||||||
|
# nix < 2.2 support.
|
||||||
|
# (assertRange "FirewallMark" 1 4294967295)
|
||||||
|
(assertInt "Priority")
|
||||||
|
(assertPort "SourcePort")
|
||||||
|
(assertPort "DestinationPort")
|
||||||
|
(assertValueOneOf "InvertRule" boolValues)
|
||||||
|
(assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
|
||||||
|
];
|
||||||
|
|
||||||
checkRoute = checkUnitConfig "Route" [
|
checkRoute = checkUnitConfig "Route" [
|
||||||
(assertOnlyFields [
|
(assertOnlyFields [
|
||||||
"Gateway" "GatewayOnLink" "Destination" "Source" "Metric"
|
"Gateway" "GatewayOnLink" "Destination" "Source" "Metric"
|
||||||
@ -325,6 +355,14 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
linkOptions = commonNetworkOptions // {
|
linkOptions = commonNetworkOptions // {
|
||||||
|
# overwrite enable option from above
|
||||||
|
enable = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
linkConfig = mkOption {
|
linkConfig = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
@ -535,6 +573,22 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
routingPolicyRulesOptions = {
|
||||||
|
options = {
|
||||||
|
routingPolicyRuleConfig = mkOption {
|
||||||
|
default = { };
|
||||||
|
example = { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ;};
|
||||||
|
type = types.addCheck (types.attrsOf unitOption) checkRoutingPolicyRule;
|
||||||
|
description = ''
|
||||||
|
Each attribute in this set specifies an option in the
|
||||||
|
<literal>[RoutingPolicyRule]</literal> section of the unit. See
|
||||||
|
<citerefentry><refentrytitle>systemd.network</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum></citerefentry> for details.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
routeOptions = {
|
routeOptions = {
|
||||||
options = {
|
options = {
|
||||||
routeConfig = mkOption {
|
routeConfig = mkOption {
|
||||||
@ -772,6 +826,16 @@ let
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
routingPolicyRules = mkOption {
|
||||||
|
default = [ ];
|
||||||
|
type = with types; listOf (submodule routingPolicyRulesOptions);
|
||||||
|
description = ''
|
||||||
|
A list of routing policy rules sections to be added to the unit. See
|
||||||
|
<citerefentry><refentrytitle>systemd.network</refentrytitle>
|
||||||
|
<manvolnum>5</manvolnum></citerefentry> for details.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
routes = mkOption {
|
routes = mkOption {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
type = with types; listOf (submodule routeOptions);
|
type = with types; listOf (submodule routeOptions);
|
||||||
@ -928,6 +992,11 @@ let
|
|||||||
[Route]
|
[Route]
|
||||||
${attrsToSection x.routeConfig}
|
${attrsToSection x.routeConfig}
|
||||||
|
|
||||||
|
'')}
|
||||||
|
${flip concatMapStrings def.routingPolicyRules (x: ''
|
||||||
|
[RoutingPolicyRule]
|
||||||
|
${attrsToSection x.routingPolicyRuleConfig}
|
||||||
|
|
||||||
'')}
|
'')}
|
||||||
${def.extraConfig}
|
${def.extraConfig}
|
||||||
'';
|
'';
|
||||||
@ -984,44 +1053,49 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf config.systemd.network.enable {
|
config = mkMerge [
|
||||||
|
# .link units are honored by udev, no matter if systemd-networkd is enabled or not.
|
||||||
|
{
|
||||||
|
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
|
||||||
|
environment.etc = unitFiles;
|
||||||
|
}
|
||||||
|
|
||||||
users.users.systemd-network.group = "systemd-network";
|
(mkIf config.systemd.network.enable {
|
||||||
|
|
||||||
systemd.additionalUpstreamSystemUnits = [
|
users.users.systemd-network.group = "systemd-network";
|
||||||
"systemd-networkd.service" "systemd-networkd-wait-online.service"
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
|
systemd.additionalUpstreamSystemUnits = [
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
|
"systemd-networkd.service" "systemd-networkd-wait-online.service"
|
||||||
// mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
|
];
|
||||||
|
|
||||||
environment.etc = unitFiles;
|
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
|
||||||
|
// mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
|
||||||
|
|
||||||
systemd.services.systemd-networkd = {
|
systemd.services.systemd-networkd = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
restartTriggers = attrNames unitFiles;
|
restartTriggers = attrNames unitFiles;
|
||||||
# prevent race condition with interface renaming (#39069)
|
# prevent race condition with interface renaming (#39069)
|
||||||
requires = [ "systemd-udev-settle.service" ];
|
requires = [ "systemd-udev-settle.service" ];
|
||||||
after = [ "systemd-udev-settle.service" ];
|
after = [ "systemd-udev-settle.service" ];
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.systemd-networkd-wait-online = {
|
|
||||||
wantedBy = [ "network-online.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services."systemd-network-wait-online@" = {
|
|
||||||
description = "Wait for Network Interface %I to be Configured";
|
|
||||||
conflicts = [ "shutdown.target" ];
|
|
||||||
requisite = [ "systemd-networkd.service" ];
|
|
||||||
after = [ "systemd-networkd.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
services.resolved.enable = mkDefault true;
|
systemd.services.systemd-networkd-wait-online = {
|
||||||
};
|
wantedBy = [ "network-online.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."systemd-network-wait-online@" = {
|
||||||
|
description = "Wait for Network Interface %I to be Configured";
|
||||||
|
conflicts = [ "shutdown.target" ];
|
||||||
|
requisite = [ "systemd-networkd.service" ];
|
||||||
|
after = [ "systemd-networkd.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.resolved.enable = mkDefault true;
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,8 @@ done
|
|||||||
# Create device nodes in /dev.
|
# Create device nodes in /dev.
|
||||||
@preDeviceCommands@
|
@preDeviceCommands@
|
||||||
echo "running udev..."
|
echo "running udev..."
|
||||||
|
mkdir -p /etc/systemd
|
||||||
|
ln -sfn @linkUnits@ /etc/systemd/network
|
||||||
mkdir -p /etc/udev
|
mkdir -p /etc/udev
|
||||||
ln -sfn @udevRules@ /etc/udev/rules.d
|
ln -sfn @udevRules@ /etc/udev/rules.d
|
||||||
mkdir -p /dev/.mdadm
|
mkdir -p /dev/.mdadm
|
||||||
@ -266,7 +268,7 @@ checkFS() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Device might be already mounted manually
|
# Device might be already mounted manually
|
||||||
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
|
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
|
||||||
if mount | grep -q "^$device on "; then
|
if mount | grep -q "^$device on "; then
|
||||||
echo "skip checking already mounted $device"
|
echo "skip checking already mounted $device"
|
||||||
@ -351,7 +353,7 @@ mountFS() {
|
|||||||
elif [ "$fsType" = f2fs ]; then
|
elif [ "$fsType" = f2fs ]; then
|
||||||
echo "resizing $device..."
|
echo "resizing $device..."
|
||||||
fsck.f2fs -fp "$device"
|
fsck.f2fs -fp "$device"
|
||||||
resize.f2fs "$device"
|
resize.f2fs "$device"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -120,6 +120,7 @@ let
|
|||||||
|
|
||||||
# Copy udev.
|
# Copy udev.
|
||||||
copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
|
copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
|
||||||
|
copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
|
||||||
copy_bin_and_libs ${udev}/bin/udevadm
|
copy_bin_and_libs ${udev}/bin/udevadm
|
||||||
for BIN in ${udev}/lib/udev/*_id; do
|
for BIN in ${udev}/lib/udev/*_id; do
|
||||||
copy_bin_and_libs $BIN
|
copy_bin_and_libs $BIN
|
||||||
@ -198,6 +199,14 @@ let
|
|||||||
''; # */
|
''; # */
|
||||||
|
|
||||||
|
|
||||||
|
linkUnits = pkgs.runCommand "link-units" {
|
||||||
|
allowedReferences = [ extraUtils ];
|
||||||
|
preferLocalBuild = true;
|
||||||
|
} ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp -v ${udev}/lib/systemd/network/*.link $out/
|
||||||
|
'';
|
||||||
|
|
||||||
udevRules = pkgs.runCommand "udev-rules" {
|
udevRules = pkgs.runCommand "udev-rules" {
|
||||||
allowedReferences = [ extraUtils ];
|
allowedReferences = [ extraUtils ];
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
@ -208,7 +217,9 @@ let
|
|||||||
|
|
||||||
cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
|
cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
|
||||||
cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
|
cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
|
||||||
|
cp -v ${udev}/lib/udev/rules.d/75-net-description.rules $out/
|
||||||
cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
|
cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
|
||||||
|
cp -v ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/
|
||||||
cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
|
cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
|
||||||
${config.boot.initrd.extraUdevRulesCommands}
|
${config.boot.initrd.extraUdevRulesCommands}
|
||||||
|
|
||||||
@ -222,7 +233,7 @@ let
|
|||||||
--replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
|
--replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
|
||||||
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
|
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
|
||||||
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
|
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
|
||||||
--replace ${udev}/bin/udevadm ${extraUtils}/bin/udevadm
|
--replace ${udev} ${extraUtils}
|
||||||
done
|
done
|
||||||
|
|
||||||
# Work around a bug in QEMU, which doesn't implement the "READ
|
# Work around a bug in QEMU, which doesn't implement the "READ
|
||||||
@ -257,7 +268,7 @@ let
|
|||||||
${pkgs.buildPackages.busybox}/bin/ash -n $target
|
${pkgs.buildPackages.busybox}/bin/ash -n $target
|
||||||
'';
|
'';
|
||||||
|
|
||||||
inherit udevRules extraUtils modulesClosure;
|
inherit linkUnits udevRules extraUtils modulesClosure;
|
||||||
|
|
||||||
inherit (config.boot) resumeDevice;
|
inherit (config.boot) resumeDevice;
|
||||||
|
|
||||||
@ -379,6 +390,17 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boot.initrd.enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = !config.boot.isContainer;
|
||||||
|
defaultText = "!config.boot.isContainer";
|
||||||
|
description = ''
|
||||||
|
Whether to enable the NixOS initial RAM disk (initrd). This may be
|
||||||
|
needed to perform some initialisation tasks (like mounting
|
||||||
|
network/encrypted file systems) before continuing the boot process.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
boot.initrd.prepend = mkOption {
|
boot.initrd.prepend = mkOption {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
@ -544,7 +566,7 @@ in
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf (!config.boot.isContainer) {
|
config = mkIf config.boot.initrd.enable {
|
||||||
assertions = [
|
assertions = [
|
||||||
{ assertion = any (fs: fs.mountPoint == "/") fileSystems;
|
{ assertion = any (fs: fs.mountPoint == "/") fileSystems;
|
||||||
message = "The ‘fileSystems’ option does not specify your root file system.";
|
message = "The ‘fileSystems’ option does not specify your root file system.";
|
||||||
|
@ -59,6 +59,11 @@ in rec {
|
|||||||
optional (attr ? ${name} && ! isMacAddress attr.${name})
|
optional (attr ? ${name} && ! isMacAddress attr.${name})
|
||||||
"Systemd ${group} field `${name}' must be a valid mac address.";
|
"Systemd ${group} field `${name}' must be a valid mac address.";
|
||||||
|
|
||||||
|
isPort = i: i >= 0 && i <= 65535;
|
||||||
|
|
||||||
|
assertPort = name: group: attr:
|
||||||
|
optional (attr ? ${name} && ! isPort attr.${name})
|
||||||
|
"Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number.";
|
||||||
|
|
||||||
assertValueOneOf = name: values: group: attr:
|
assertValueOneOf = name: values: group: attr:
|
||||||
optional (attr ? ${name} && !elem attr.${name} values)
|
optional (attr ? ${name} && !elem attr.${name} values)
|
||||||
|
@ -94,7 +94,7 @@ in
|
|||||||
default = 0;
|
default = 0;
|
||||||
type = types.int;
|
type = types.int;
|
||||||
description = ''
|
description = ''
|
||||||
UID of created file. Only takes affect when the file is
|
UID of created file. Only takes effect when the file is
|
||||||
copied (that is, the mode is not 'symlink').
|
copied (that is, the mode is not 'symlink').
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -103,7 +103,7 @@ in
|
|||||||
default = 0;
|
default = 0;
|
||||||
type = types.int;
|
type = types.int;
|
||||||
description = ''
|
description = ''
|
||||||
GID of created file. Only takes affect when the file is
|
GID of created file. Only takes effect when the file is
|
||||||
copied (that is, the mode is not 'symlink').
|
copied (that is, the mode is not 'symlink').
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -113,7 +113,7 @@ in
|
|||||||
type = types.str;
|
type = types.str;
|
||||||
description = ''
|
description = ''
|
||||||
User name of created file.
|
User name of created file.
|
||||||
Only takes affect when the file is copied (that is, the mode is not 'symlink').
|
Only takes effect when the file is copied (that is, the mode is not 'symlink').
|
||||||
Changing this option takes precedence over <literal>uid</literal>.
|
Changing this option takes precedence over <literal>uid</literal>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -123,7 +123,7 @@ in
|
|||||||
type = types.str;
|
type = types.str;
|
||||||
description = ''
|
description = ''
|
||||||
Group name of created file.
|
Group name of created file.
|
||||||
Only takes affect when the file is copied (that is, the mode is not 'symlink').
|
Only takes effect when the file is copied (that is, the mode is not 'symlink').
|
||||||
Changing this option takes precedence over <literal>gid</literal>.
|
Changing this option takes precedence over <literal>gid</literal>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user