Merge branch 'staging-next' into staging
This commit is contained in:
commit
9c497bb8d6
631 changed files with 5661 additions and 3449 deletions
13
.mailmap
13
.mailmap
|
@ -1,3 +1,14 @@
|
|||
ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com>
|
||||
Anderson Torres <torres.anderson.85@protonmail.com>
|
||||
Daniel Løvbrøtte Olsen <me@dandellion.xyz> <daniel.olsen99@gmail.com>
|
||||
Fabian Affolter <mail@fabian-affolter.ch> <fabian@affolter-engineering.ch>
|
||||
Janne Heß <janne@hess.ooo> <dasJ@users.noreply.github.com>
|
||||
Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com>
|
||||
Martin Weinelt <hexa@darmstadt.ccc.de> <mweinelt@users.noreply.github.com>
|
||||
R. RyanTM <ryantm-bot@ryantm.com>
|
||||
Sandro <sandro.jaeckel@gmail.com>
|
||||
Robert Hensing <robert@roberthensing.nl> <roberth@users.noreply.github.com>
|
||||
Sandro Jäckel <sandro.jaeckel@gmail.com>
|
||||
Sandro Jäckel <sandro.jaeckel@gmail.com> <sandro.jaeckel@sap.com>
|
||||
superherointj <5861043+superherointj@users.noreply.github.com>
|
||||
Vladimír Čunát <v@cunat.cz> <vcunat@gmail.com>
|
||||
Vladimír Čunát <v@cunat.cz> <vladimir.cunat@nic.cz>
|
||||
|
|
|
@ -62,6 +62,8 @@ The above example will build a Docker image `redis/latest` from the given base i
|
|||
|
||||
- `config` is used to specify the configuration of the containers that will be started off the built image in Docker. The available options are listed in the [Docker Image Specification v1.2.0](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions).
|
||||
|
||||
- `architecture` is _optional_ and used to specify the image architecture, this is useful for multi-architecture builds that don't need cross compiling. If not specified it will default to `hostPlatform`.
|
||||
|
||||
- `diskSize` is used to specify the disk size of the VM used to build the image in megabytes. By default it's 1024 MiB.
|
||||
|
||||
- `buildVMMemorySize` is used to specify the memory size of the VM to build the image in megabytes. By default it's 512 MiB.
|
||||
|
@ -141,6 +143,8 @@ Create a Docker image with many of the store paths being on their own layer to i
|
|||
|
||||
`config` _optional_
|
||||
|
||||
`architecture` is _optional_ and used to specify the image architecture, this is useful for multi-architecture builds that don't need cross compiling. If not specified it will default to `hostPlatform`.
|
||||
|
||||
: Run-time configuration of the container. A full list of the options are available at in the [Docker Image Specification v1.2.0](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions).
|
||||
|
||||
*Default:* `{}`
|
||||
|
|
93
doc/languages-frameworks/cuelang.section.md
Normal file
93
doc/languages-frameworks/cuelang.section.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Cue (Cuelang) {#cuelang}
|
||||
|
||||
[Cuelang](https://cuelang.org/) is a language to:
|
||||
|
||||
- describe schemas and validate backward-compatibility
|
||||
- generate code and schemas in various formats (e.g. JSON Schema, OpenAPI)
|
||||
- do configuration akin to [Dhall Lang](https://dhall-lang.org/)
|
||||
- perform data validation
|
||||
|
||||
## Cuelang schema quick start
|
||||
|
||||
Cuelang schemas are similar to JSON, here is a quick cheatsheet:
|
||||
|
||||
- Default types includes: `null`, `string`, `bool`, `bytes`, `number`, `int`, `float`, lists as `[...T]` where `T` is a type.
|
||||
- All structures, defined by: `myStructName: { <fields> }` are **open** -- they accept fields which are not specified.
|
||||
- Closed structures can be built by doing `myStructName: close({ <fields> })` -- they are strict in what they accept.
|
||||
- `#X` are **definitions**, referenced definitions are **recursively closed**, i.e. all its children structures are **closed**.
|
||||
- `&` operator is the [unification operator](https://cuelang.org/docs/references/spec/#unification) (similar to a type-level merging operator), `|` is the [disjunction operator](https://cuelang.org/docs/references/spec/#disjunction) (similar to a type-level union operator).
|
||||
- Values **are** types, i.e. `myStruct: { a: 3 }` is a valid type definition that only allows `3` as value.
|
||||
|
||||
- Read <https://cuelang.org/docs/concepts/logic/> to learn more about the semantics.
|
||||
- Read <https://cuelang.org/docs/references/spec/> to learn about the language specification.
|
||||
|
||||
## `writeCueValidator`
|
||||
|
||||
Nixpkgs provides a `pkgs.writeCueValidator` helper, which will write a validation script based on the provided Cuelang schema.
|
||||
|
||||
Here is an example:
|
||||
```
|
||||
pkgs.writeCueValidator
|
||||
(pkgs.writeText "schema.cue" ''
|
||||
#Def1: {
|
||||
field1: string
|
||||
}
|
||||
'')
|
||||
{ document = "#Def1"; }
|
||||
```
|
||||
|
||||
- The first parameter is the Cue schema file.
|
||||
- The second paramter is an options parameter, currently, only: `document` can be passed.
|
||||
|
||||
`document` : match your input data against this fragment of structure or definition, e.g. you may use the same schema file but differents documents based on the data you are validating.
|
||||
|
||||
Another example, given the following `validator.nix` :
|
||||
```
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
genericValidator = version:
|
||||
pkgs.writeCueValidator
|
||||
(pkgs.writeText "schema.cue" ''
|
||||
#Version1: {
|
||||
field1: string
|
||||
}
|
||||
#Version2: #Version1 & {
|
||||
field1: "unused"
|
||||
}''
|
||||
)
|
||||
{ document = "#Version${toString version}"; };
|
||||
in
|
||||
{
|
||||
validateV1 = genericValidator 1;
|
||||
validateV2 = genericValidator 2;
|
||||
}
|
||||
```
|
||||
|
||||
The result is a script that will validate the file you pass as the first argument against the schema you provided `writeCueValidator`.
|
||||
|
||||
It can be any format that `cue vet` supports, i.e. YAML or JSON for example.
|
||||
|
||||
Here is an example, named `example.json`, given the following JSON:
|
||||
```
|
||||
{ "field1": "abc" }
|
||||
```
|
||||
|
||||
You can run the result script (named `validate`) as the following:
|
||||
|
||||
```console
|
||||
$ nix-build validator.nix
|
||||
$ ./result example.json
|
||||
$ ./result-2 example.json
|
||||
field1: conflicting values "unused" and "abc":
|
||||
./example.json:1:13
|
||||
../../../../../../nix/store/v64dzx3vr3glpk0cq4hzmh450lrwh6sg-schema.cue:5:11
|
||||
$ sed -i 's/"abc"/3/' example.json
|
||||
$ ./result example.json
|
||||
field1: conflicting values 3 and string (mismatched types int and string):
|
||||
./example.json:1:13
|
||||
../../../../../../nix/store/v64dzx3vr3glpk0cq4hzmh450lrwh6sg-schema.cue:5:11
|
||||
```
|
||||
|
||||
**Known limitations**
|
||||
|
||||
* The script will enforce **concrete** values and will not accept lossy transformations (strictness). You can add these options if you need them.
|
|
@ -11,7 +11,13 @@ The function `buildGoModule` builds Go programs managed with Go modules. It buil
|
|||
|
||||
In the following is an example expression using `buildGoModule`, the following arguments are of special significance to the function:
|
||||
|
||||
- `vendorHash`: is the hash of the output of the intermediate fetcher derivation. `vendorHash` can also take `null` as an input. When `null` is used as a value, rather than fetching the dependencies and vendoring them, we use the vendoring included within the source repo. If you'd like to not have to update this field on dependency changes, run `go mod vendor` in your source repo and set `vendorHash = null;`
|
||||
- `vendorHash`: is the hash of the output of the intermediate fetcher derivation.
|
||||
|
||||
`vendorHash` can also be set to `null`.
|
||||
In that case, rather than fetching the dependencies and vendoring them, the dependencies vendored in the source repo will be used.
|
||||
|
||||
To avoid updating this field when dependencies change, run `go mod vendor` in your source repo and set `vendorHash = null;`
|
||||
To obtain the actual hash, set `vendorHash = lib.fakeSha256;` and run the build ([more details here](#sec-source-hashes)).
|
||||
- `proxyVendor`: Fetches (go mod download) and proxies the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build or if any dependency has case-insensitive conflicts which will produce platform dependant `vendorHash` checksums.
|
||||
|
||||
```nix
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<xi:include href="coq.section.xml" />
|
||||
<xi:include href="crystal.section.xml" />
|
||||
<xi:include href="cuda.section.xml" />
|
||||
<xi:include href="cuelang.section.xml" />
|
||||
<xi:include href="dhall.section.xml" />
|
||||
<xi:include href="dotnet.section.xml" />
|
||||
<xi:include href="emscripten.section.xml" />
|
||||
|
|
|
@ -101,6 +101,7 @@ let
|
|||
upperChars toLower toUpper addContextFrom splitString
|
||||
removePrefix removeSuffix versionOlder versionAtLeast
|
||||
getName getVersion
|
||||
mesonOption mesonBool mesonEnable
|
||||
nameFromURL enableFeature enableFeatureAs withFeature
|
||||
withFeatureAs fixedWidthString fixedWidthNumber isStorePath
|
||||
toInt toIntBase10 readPathsFromFile fileContents;
|
||||
|
|
|
@ -278,8 +278,11 @@ rec {
|
|||
mapAny 0;
|
||||
|
||||
/* Pretty print a value, akin to `builtins.trace`.
|
||||
* Should probably be a builtin as well.
|
||||
*/
|
||||
* Should probably be a builtin as well.
|
||||
* The pretty-printed string should be suitable for rendering default values
|
||||
* in the NixOS manual. In particular, it should be as close to a valid Nix expression
|
||||
* as possible.
|
||||
*/
|
||||
toPretty = {
|
||||
/* If this option is true, attrsets like { __pretty = fn; val = …; }
|
||||
will use fn to convert val to a pretty printed representation.
|
||||
|
@ -294,20 +297,25 @@ rec {
|
|||
introSpace = if multiline then "\n${indent} " else " ";
|
||||
outroSpace = if multiline then "\n${indent}" else " ";
|
||||
in if isInt v then toString v
|
||||
else if isFloat v then "~${toString v}"
|
||||
# toString loses precision on floats, so we use toJSON instead. This isn't perfect
|
||||
# as the resulting string may not parse back as a float (e.g. 42, 1e-06), but for
|
||||
# pretty-printing purposes this is acceptable.
|
||||
else if isFloat v then builtins.toJSON v
|
||||
else if isString v then
|
||||
let
|
||||
# Separate a string into its lines
|
||||
newlineSplits = filter (v: ! isList v) (builtins.split "\n" v);
|
||||
# For a '' string terminated by a \n, which happens when the closing '' is on a new line
|
||||
multilineResult = "''" + introSpace + concatStringsSep introSpace (lib.init newlineSplits) + outroSpace + "''";
|
||||
# For a '' string not terminated by a \n, which happens when the closing '' is not on a new line
|
||||
multilineResult' = "''" + introSpace + concatStringsSep introSpace newlineSplits + "''";
|
||||
# For single lines, replace all newlines with their escaped representation
|
||||
singlelineResult = "\"" + libStr.escape [ "\"" ] (concatStringsSep "\\n" newlineSplits) + "\"";
|
||||
in if multiline && length newlineSplits > 1 then
|
||||
if lib.last newlineSplits == "" then multilineResult else multilineResult'
|
||||
else singlelineResult
|
||||
lines = filter (v: ! isList v) (builtins.split "\n" v);
|
||||
escapeSingleline = libStr.escape [ "\\" "\"" "\${" ];
|
||||
escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [ "''\${" "'''" ];
|
||||
singlelineResult = "\"" + concatStringsSep "\\n" (map escapeSingleline lines) + "\"";
|
||||
multilineResult = let
|
||||
escapedLines = map escapeMultiline lines;
|
||||
# The last line gets a special treatment: if it's empty, '' is on its own line at the "outer"
|
||||
# indentation level. Otherwise, '' is appended to the last line.
|
||||
lastLine = lib.last escapedLines;
|
||||
in "''" + introSpace + concatStringsSep introSpace (lib.init escapedLines)
|
||||
+ (if lastLine == "" then outroSpace else introSpace + lastLine) + "''";
|
||||
in
|
||||
if multiline && length lines > 1 then multilineResult else singlelineResult
|
||||
else if true == v then "true"
|
||||
else if false == v then "false"
|
||||
else if null == v then "null"
|
||||
|
@ -326,11 +334,11 @@ rec {
|
|||
else "<function, args: {${showFnas}}>"
|
||||
else if isAttrs v then
|
||||
# apply pretty values if allowed
|
||||
if attrNames v == [ "__pretty" "val" ] && allowPrettyValues
|
||||
if allowPrettyValues && v ? __pretty && v ? val
|
||||
then v.__pretty v.val
|
||||
else if v == {} then "{ }"
|
||||
else if v ? type && v.type == "derivation" then
|
||||
"<derivation ${v.drvPath or "???"}>"
|
||||
"<derivation ${v.name or "???"}>"
|
||||
else "{" + introSpace
|
||||
+ libStr.concatStringsSep introSpace (libAttr.mapAttrsToList
|
||||
(name: value:
|
||||
|
|
|
@ -218,7 +218,7 @@ rec {
|
|||
# the set generated with filterOptionSets.
|
||||
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
||||
|
||||
optionAttrSetToDocList' = prefix: options:
|
||||
optionAttrSetToDocList' = _: options:
|
||||
concatMap (opt:
|
||||
let
|
||||
docOption = rec {
|
||||
|
@ -234,9 +234,8 @@ rec {
|
|||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.description or "unspecified";
|
||||
}
|
||||
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
|
||||
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
|
||||
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; }
|
||||
// optionalAttrs (opt ? example) { example = renderOptionValue opt.example; }
|
||||
// optionalAttrs (opt ? default) { default = renderOptionValue (opt.defaultText or opt.default); }
|
||||
// optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) { inherit (opt) relatedPackages; };
|
||||
|
||||
subOptions =
|
||||
|
@ -256,6 +255,9 @@ rec {
|
|||
efficient: the XML representation of derivations is very large
|
||||
(on the order of megabytes) and is not actually used by the
|
||||
manual generator.
|
||||
|
||||
This function was made obsolete by renderOptionValue and is kept for
|
||||
compatibility with out-of-tree code.
|
||||
*/
|
||||
scrubOptionValue = x:
|
||||
if isDerivation x then
|
||||
|
@ -265,6 +267,17 @@ rec {
|
|||
else x;
|
||||
|
||||
|
||||
/* Ensures that the given option value (default or example) is a `_type`d string
|
||||
by rendering Nix values to `literalExpression`s.
|
||||
*/
|
||||
renderOptionValue = v:
|
||||
if v ? _type && v ? text then v
|
||||
else literalExpression (lib.generators.toPretty {
|
||||
multiline = true;
|
||||
allowPrettyValues = true;
|
||||
} v);
|
||||
|
||||
|
||||
/* For use in the `defaultText` and `example` option attributes. Causes the
|
||||
given string to be rendered verbatim in the documentation as Nix code. This
|
||||
is necessary for complex values, e.g. functions, or values that depend on
|
||||
|
|
|
@ -510,7 +510,7 @@ rec {
|
|||
toUpper = replaceChars lowerChars upperChars;
|
||||
|
||||
/* Appends string context from another string. This is an implementation
|
||||
detail of Nix.
|
||||
detail of Nix and should be used carefully.
|
||||
|
||||
Strings in Nix carry an invisible `context` which is a list of strings
|
||||
representing store paths. If the string is later used in a derivation
|
||||
|
@ -533,13 +533,11 @@ rec {
|
|||
splitString "/" "/usr/local/bin"
|
||||
=> [ "" "usr" "local" "bin" ]
|
||||
*/
|
||||
splitString = _sep: _s:
|
||||
splitString = sep: s:
|
||||
let
|
||||
sep = builtins.unsafeDiscardStringContext _sep;
|
||||
s = builtins.unsafeDiscardStringContext _s;
|
||||
splits = builtins.filter builtins.isString (builtins.split (escapeRegex sep) s);
|
||||
splits = builtins.filter builtins.isString (builtins.split (escapeRegex (toString sep)) (toString s));
|
||||
in
|
||||
map (v: addContextFrom _sep (addContextFrom _s v)) splits;
|
||||
map (addContextFrom s) splits;
|
||||
|
||||
/* Return a string without the specified prefix, if the prefix matches.
|
||||
|
||||
|
@ -661,6 +659,61 @@ rec {
|
|||
name = head (splitString sep filename);
|
||||
in assert name != filename; name;
|
||||
|
||||
/* Create a -D<feature>=<value> string that can be passed to typical Meson
|
||||
invocations.
|
||||
|
||||
Type: mesonOption :: string -> string -> string
|
||||
|
||||
@param feature The feature to be set
|
||||
@param value The desired value
|
||||
|
||||
Example:
|
||||
mesonOption "engine" "opengl"
|
||||
=> "-Dengine=opengl"
|
||||
*/
|
||||
mesonOption = feature: value:
|
||||
assert (lib.isString feature);
|
||||
assert (lib.isString value);
|
||||
"-D${feature}=${value}";
|
||||
|
||||
/* Create a -D<condition>={true,false} string that can be passed to typical
|
||||
Meson invocations.
|
||||
|
||||
Type: mesonBool :: string -> bool -> string
|
||||
|
||||
@param condition The condition to be made true or false
|
||||
@param flag The controlling flag of the condition
|
||||
|
||||
Example:
|
||||
mesonBool "hardened" true
|
||||
=> "-Dhardened=true"
|
||||
mesonBool "static" false
|
||||
=> "-Dstatic=false"
|
||||
*/
|
||||
mesonBool = condition: flag:
|
||||
assert (lib.isString condition);
|
||||
assert (lib.isBool flag);
|
||||
mesonOption condition (lib.boolToString flag);
|
||||
|
||||
/* Create a -D<feature>={enabled,disabled} string that can be passed to
|
||||
typical Meson invocations.
|
||||
|
||||
Type: mesonEnable :: string -> bool -> string
|
||||
|
||||
@param feature The feature to be enabled or disabled
|
||||
@param flag The controlling flag
|
||||
|
||||
Example:
|
||||
mesonEnable "docs" true
|
||||
=> "-Ddocs=enabled"
|
||||
mesonEnable "savage" false
|
||||
=> "-Dsavage=disabled"
|
||||
*/
|
||||
mesonEnable = feature: flag:
|
||||
assert (lib.isString feature);
|
||||
assert (lib.isBool flag);
|
||||
mesonOption feature (if flag then "enabled" else "disabled");
|
||||
|
||||
/* Create an --{enable,disable}-<feat> string that can be passed to
|
||||
standard GNU Autoconf scripts.
|
||||
|
||||
|
|
|
@ -727,7 +727,7 @@ runTests {
|
|||
float = 0.1337;
|
||||
bool = true;
|
||||
emptystring = "";
|
||||
string = ''fno"rd'';
|
||||
string = "fn\${o}\"r\\d";
|
||||
newlinestring = "\n";
|
||||
path = /. + "/foo";
|
||||
null_ = null;
|
||||
|
@ -735,16 +735,16 @@ runTests {
|
|||
functionArgs = { arg ? 4, foo }: arg;
|
||||
list = [ 3 4 function [ false ] ];
|
||||
emptylist = [];
|
||||
attrs = { foo = null; "foo bar" = "baz"; };
|
||||
attrs = { foo = null; "foo b/ar" = "baz"; };
|
||||
emptyattrs = {};
|
||||
drv = deriv;
|
||||
};
|
||||
expected = rec {
|
||||
int = "42";
|
||||
float = "~0.133700";
|
||||
float = "0.1337";
|
||||
bool = "true";
|
||||
emptystring = ''""'';
|
||||
string = ''"fno\"rd"'';
|
||||
string = ''"fn\''${o}\"r\\d"'';
|
||||
newlinestring = "\"\\n\"";
|
||||
path = "/foo";
|
||||
null_ = "null";
|
||||
|
@ -752,9 +752,9 @@ runTests {
|
|||
functionArgs = "<function, args: {arg?, foo}>";
|
||||
list = "[ 3 4 ${function} [ false ] ]";
|
||||
emptylist = "[ ]";
|
||||
attrs = "{ foo = null; \"foo bar\" = \"baz\"; }";
|
||||
attrs = "{ foo = null; \"foo b/ar\" = \"baz\"; }";
|
||||
emptyattrs = "{ }";
|
||||
drv = "<derivation ${deriv.drvPath}>";
|
||||
drv = "<derivation ${deriv.name}>";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -799,8 +799,8 @@ runTests {
|
|||
newlinestring = "\n";
|
||||
multilinestring = ''
|
||||
hello
|
||||
there
|
||||
test
|
||||
''${there}
|
||||
te'''st
|
||||
'';
|
||||
multilinestring' = ''
|
||||
hello
|
||||
|
@ -827,8 +827,8 @@ runTests {
|
|||
multilinestring = ''
|
||||
'''
|
||||
hello
|
||||
there
|
||||
test
|
||||
'''''${there}
|
||||
te''''st
|
||||
''''';
|
||||
multilinestring' = ''
|
||||
'''
|
||||
|
|
|
@ -14127,6 +14127,12 @@
|
|||
githubId = 8794235;
|
||||
name = "Tom Siewert";
|
||||
};
|
||||
tonyshkurenko = {
|
||||
email = "support@twingate.com";
|
||||
github = "tonyshkurenko";
|
||||
githubId = 8597964;
|
||||
name = "Anton Shkurenko";
|
||||
};
|
||||
toonn = {
|
||||
email = "nixpkgs@toonn.io";
|
||||
matrix = "@toonn:matrix.org";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
}:
|
||||
with nixpkgs;
|
||||
let
|
||||
pyEnv = python3.withPackages(ps: [ ps.GitPython ]);
|
||||
pyEnv = python3.withPackages(ps: [ ps.gitpython ]);
|
||||
in
|
||||
mkShell {
|
||||
packages = [
|
||||
|
|
|
@ -506,6 +506,18 @@ with lib.maintainers; {
|
|||
enableFeatureFreezePing = true;
|
||||
};
|
||||
|
||||
node = {
|
||||
members = [
|
||||
lilyinstarlight
|
||||
marsam
|
||||
winter
|
||||
yuka
|
||||
];
|
||||
scope = "Maintain Node.js runtimes and build tooling.";
|
||||
shortName = "Node.js";
|
||||
enableFeatureFreezePing = true;
|
||||
};
|
||||
|
||||
numtide = {
|
||||
members = [
|
||||
mic92
|
||||
|
|
|
@ -561,6 +561,14 @@
|
|||
<link xlink:href="options.html#opt-services.prometheus.exporters.smartctl.enable">services.prometheus.exporters.smartctl</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://docs.twingate.com/docs/linux">twingate</link>,
|
||||
a high performance, easy to use zero trust solution that
|
||||
enables access to private resources from any device with
|
||||
better security than a VPN.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-21.11-incompatibilities">
|
||||
|
|
|
@ -22,7 +22,14 @@
|
|||
</section>
|
||||
<section xml:id="sec-release-23.05-new-services">
|
||||
<title>New Services</title>
|
||||
<itemizedlist spacing="compact">
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/akinomyoga/ble.sh">blesh</link>,
|
||||
a line editor written in pure bash. Available as
|
||||
<link linkend="opt-programs.bash.blesh.enable">programs.bash.blesh</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/junegunn/fzf">fzf</link>,
|
||||
|
@ -168,6 +175,15 @@
|
|||
sudo and sources the environment variables.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>dnsmasq</literal> service now takes configuration
|
||||
via the <literal>services.dnsmasq.settings</literal> attribute
|
||||
set. The option
|
||||
<literal>services.dnsmasq.extraConfig</literal> will be
|
||||
deprecated when NixOS 22.11 reaches end of life.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A new <literal>virtualisation.rosetta</literal> module was
|
||||
|
|
|
@ -164,6 +164,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [smartctl_exporter](https://github.com/prometheus-community/smartctl_exporter), a Prometheus exporter for [S.M.A.R.T.](https://en.wikipedia.org/wiki/S.M.A.R.T.) data. Available as [services.prometheus.exporters.smartctl](options.html#opt-services.prometheus.exporters.smartctl.enable).
|
||||
|
||||
- [twingate](https://docs.twingate.com/docs/linux), a high performance, easy to use zero trust solution that enables access to private resources from any device with better security than a VPN.
|
||||
|
||||
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
|
||||
|
||||
- The NixOS VM test framework, `pkgs.nixosTest`/`make-test-python.nix` (`pkgs.testers.nixosTest` since 22.05), now requires detaching commands such as `succeed("foo &")` and `succeed("foo | xclip -i")` to close stdout.
|
||||
|
|
|
@ -14,6 +14,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- [blesh](https://github.com/akinomyoga/ble.sh), a line editor written in pure bash. Available as [programs.bash.blesh](#opt-programs.bash.blesh.enable).
|
||||
|
||||
- [fzf](https://github.com/junegunn/fzf), a command line fuzzyfinder. Available as [programs.fzf](#opt-programs.fzf.fuzzyCompletion).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-23.05-incompatibilities}
|
||||
|
@ -51,6 +53,11 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- `services.mastodon` gained a tootctl wrapped named `mastodon-tootctl` similar to `nextcloud-occ` which can be executed from any user and switches to the configured mastodon user with sudo and sources the environment variables.
|
||||
|
||||
- The `dnsmasq` service now takes configuration via the
|
||||
`services.dnsmasq.settings` attribute set. The option
|
||||
`services.dnsmasq.extraConfig` will be deprecated when NixOS 22.11 reaches
|
||||
end of life.
|
||||
|
||||
- A new `virtualisation.rosetta` module was added to allow running `x86_64` binaries through [Rosetta](https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment) inside virtualised NixOS guests on Apple silicon. This feature works by default with the [UTM](https://docs.getutm.app/) virtualisation [package](https://search.nixos.org/packages?channel=unstable&show=utm&from=0&size=1&sort=relevance&type=packages&query=utm).
|
||||
|
||||
- Resilio sync secret keys can now be provided using a secrets file at runtime, preventing these secrets from ending up in the Nix store.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
# If you include more than one option list into a document, you need to
|
||||
# provide different ids.
|
||||
, variablelistId ? "configuration-variable-list"
|
||||
# Strig to prefix to the option XML/HTML id attributes.
|
||||
# String to prefix to the option XML/HTML id attributes.
|
||||
, optionIdPrefix ? "opt-"
|
||||
, revision ? "" # Specify revision for the options
|
||||
# a set of options the docs we are generating will be merged into, as if by recursiveUpdate.
|
||||
|
@ -45,28 +45,11 @@
|
|||
}:
|
||||
|
||||
let
|
||||
# Make a value safe for JSON. Functions are replaced by the string "<function>",
|
||||
# derivations are replaced with an attrset
|
||||
# { _type = "derivation"; name = <name of that derivation>; }.
|
||||
# We need to handle derivations specially because consumers want to know about them,
|
||||
# but we can't easily use the type,name subset of keys (since type is often used as
|
||||
# a module option and might cause confusion). Use _type,name instead to the same
|
||||
# effect, since _type is already used by the module system.
|
||||
substSpecial = x:
|
||||
if lib.isDerivation x then { _type = "derivation"; name = x.name; }
|
||||
else if builtins.isAttrs x then lib.mapAttrs (name: substSpecial) x
|
||||
else if builtins.isList x then map substSpecial x
|
||||
else if lib.isFunction x then "<function>"
|
||||
else x;
|
||||
|
||||
rawOpts = lib.optionAttrSetToDocList options;
|
||||
transformedOpts = map transformOptions rawOpts;
|
||||
filteredOpts = lib.filter (opt: opt.visible && !opt.internal) transformedOpts;
|
||||
optionsList = lib.flip map filteredOpts
|
||||
(opt: opt
|
||||
// lib.optionalAttrs (opt ? example) { example = substSpecial opt.example; }
|
||||
// lib.optionalAttrs (opt ? default) { default = substSpecial opt.default; }
|
||||
// lib.optionalAttrs (opt ? type) { type = substSpecial opt.type; }
|
||||
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
|
||||
);
|
||||
|
||||
|
@ -111,14 +94,16 @@ in rec {
|
|||
inherit optionsNix;
|
||||
|
||||
optionsAsciiDoc = pkgs.runCommand "options.adoc" {} ''
|
||||
${pkgs.python3Minimal}/bin/python ${./generateAsciiDoc.py} \
|
||||
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||
${pkgs.python3Minimal}/bin/python ${./generateDoc.py} \
|
||||
--format asciidoc \
|
||||
${optionsJSON}/share/doc/nixos/options.json \
|
||||
> $out
|
||||
'';
|
||||
|
||||
optionsCommonMark = pkgs.runCommand "options.md" {} ''
|
||||
${pkgs.python3Minimal}/bin/python ${./generateCommonMark.py} \
|
||||
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||
${pkgs.python3Minimal}/bin/python ${./generateDoc.py} \
|
||||
--format commonmark \
|
||||
${optionsJSON}/share/doc/nixos/options.json \
|
||||
> $out
|
||||
'';
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import json
|
||||
import sys
|
||||
|
||||
options = json.load(sys.stdin)
|
||||
# TODO: declarations: link to github
|
||||
for (name, value) in options.items():
|
||||
print(f'== {name}')
|
||||
print()
|
||||
print(value['description'])
|
||||
print()
|
||||
print('[discrete]')
|
||||
print('=== details')
|
||||
print()
|
||||
print(f'Type:: {value["type"]}')
|
||||
if 'default' in value:
|
||||
print('Default::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Default:: {blank}')
|
||||
if value['readOnly']:
|
||||
print('Read Only:: {blank}')
|
||||
else:
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('Example::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Example:: {blank}')
|
||||
print()
|
|
@ -1,27 +0,0 @@
|
|||
import json
|
||||
import sys
|
||||
|
||||
options = json.load(sys.stdin)
|
||||
for (name, value) in options.items():
|
||||
print('##', name.replace('<', '<').replace('>', '>'))
|
||||
print(value['description'])
|
||||
print()
|
||||
if 'type' in value:
|
||||
print('*_Type_*:')
|
||||
print(value['type'])
|
||||
print()
|
||||
print()
|
||||
if 'default' in value:
|
||||
print('*_Default_*')
|
||||
print('```')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('*_Example_*')
|
||||
print('```')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
108
nixos/lib/make-options-doc/generateDoc.py
Normal file
108
nixos/lib/make-options-doc/generateDoc.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
formats = ['commonmark', 'asciidoc']
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description = 'Generate documentation for a set of JSON-formatted NixOS options'
|
||||
)
|
||||
parser.add_argument(
|
||||
'nix_options_path',
|
||||
help = 'a path to a JSON file containing the NixOS options'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-f',
|
||||
'--format',
|
||||
choices = formats,
|
||||
required = True,
|
||||
help = f'the documentation format to generate'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Pretty-print certain Nix types, like literal expressions.
|
||||
def render_types(obj):
|
||||
if '_type' not in obj: return obj
|
||||
|
||||
_type = obj['_type']
|
||||
if _type == 'literalExpression' or _type == 'literalDocBook':
|
||||
return obj['text']
|
||||
|
||||
if _type == 'derivation':
|
||||
return obj['name']
|
||||
|
||||
raise Exception(f'Unexpected type `{_type}` in {json.dumps(obj)}')
|
||||
|
||||
def generate_commonmark(options):
|
||||
for (name, value) in options.items():
|
||||
print('##', name.replace('<', '<').replace('>', '>'))
|
||||
print(value['description'])
|
||||
print()
|
||||
if 'type' in value:
|
||||
print('*_Type_*')
|
||||
print ('```')
|
||||
print(value['type'])
|
||||
print ('```')
|
||||
print()
|
||||
print()
|
||||
if 'default' in value:
|
||||
print('*_Default_*')
|
||||
print('```')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('*_Example_*')
|
||||
print('```')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
||||
|
||||
# TODO: declarations: link to github
|
||||
def generate_asciidoc(options):
|
||||
for (name, value) in options.items():
|
||||
print(f'== {name}')
|
||||
print()
|
||||
print(value['description'])
|
||||
print()
|
||||
print('[discrete]')
|
||||
print('=== details')
|
||||
print()
|
||||
print(f'Type:: {value["type"]}')
|
||||
if 'default' in value:
|
||||
print('Default::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Default:: {blank}')
|
||||
if value['readOnly']:
|
||||
print('Read Only:: {blank}')
|
||||
else:
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('Example::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Example:: {blank}')
|
||||
print()
|
||||
|
||||
with open(args.nix_options_path) as nix_options_json:
|
||||
options = json.load(nix_options_json, object_hook=render_types)
|
||||
|
||||
if args.format == 'commonmark':
|
||||
generate_commonmark(options)
|
||||
elif args.format == 'asciidoc':
|
||||
generate_asciidoc(options)
|
||||
else:
|
||||
raise Exception(f'Unsupported documentation format `--format {args.format}`')
|
||||
|
|
@ -138,82 +138,6 @@
|
|||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="string[contains(@value, '
')]" mode="top">
|
||||
<programlisting>
|
||||
<xsl:text>''
</xsl:text>
|
||||
<xsl:value-of select='str:replace(str:replace(@value, "''", "'''"), "${", "''${")' />
|
||||
<xsl:text>''</xsl:text>
|
||||
</programlisting>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="*" mode="top">
|
||||
<literal><xsl:apply-templates select="." /></literal>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="null">
|
||||
<xsl:text>null</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="string">
|
||||
<xsl:choose>
|
||||
<xsl:when test="(contains(@value, '"') or contains(@value, '\')) and not(contains(@value, '
'))">
|
||||
<xsl:text>''</xsl:text><xsl:value-of select='str:replace(str:replace(@value, "''", "'''"), "${", "''${")' /><xsl:text>''</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:text>"</xsl:text><xsl:value-of select="str:replace(str:replace(str:replace(str:replace(@value, '\', '\\'), '"', '\"'), '
', '\n'), '${', '\${')" /><xsl:text>"</xsl:text>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="int">
|
||||
<xsl:value-of select="@value" />
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="bool[@value = 'true']">
|
||||
<xsl:text>true</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="bool[@value = 'false']">
|
||||
<xsl:text>false</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="list">
|
||||
[
|
||||
<xsl:for-each select="*">
|
||||
<xsl:apply-templates select="." />
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:for-each>
|
||||
]
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'literalExpression']]]">
|
||||
<xsl:value-of select="attr[@name = 'text']/string/@value" />
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="attrs">
|
||||
{
|
||||
<xsl:for-each select="attr">
|
||||
<xsl:value-of select="@name" />
|
||||
<xsl:text> = </xsl:text>
|
||||
<xsl:apply-templates select="*" /><xsl:text>; </xsl:text>
|
||||
</xsl:for-each>
|
||||
}
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'derivation']]]">
|
||||
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="attr[@name = 'declarations' or @name = 'definitions']">
|
||||
<simplelist>
|
||||
<!--
|
||||
|
@ -275,10 +199,4 @@
|
|||
</simplelist>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="function">
|
||||
<xsl:text>λ</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
|
@ -82,8 +82,8 @@ in {
|
|||
|
||||
kerberos = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.krb5Full;
|
||||
defaultText = literalExpression "pkgs.krb5Full";
|
||||
default = pkgs.krb5;
|
||||
defaultText = literalExpression "pkgs.krb5";
|
||||
example = literalExpression "pkgs.heimdal";
|
||||
description = lib.mdDoc ''
|
||||
The Kerberos implementation that will be present in
|
||||
|
|
|
@ -43,6 +43,7 @@ with lib;
|
|||
networkmanager-openvpn = super.networkmanager-openvpn.override { withGnome = false; };
|
||||
networkmanager-sstp = super.networkmanager-vpnc.override { withGnome = false; };
|
||||
networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
|
||||
pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; };
|
||||
qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; };
|
||||
qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; });
|
||||
zbar = super.zbar.override { enableVideo = false; withXorg = false; };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
x86_64-linux = "/nix/store/xdlpraypxdimjyfrr4k06narrv8nmfgh-nix-2.11.1";
|
||||
i686-linux = "/nix/store/acghbpn3aaj2q64mz3ljipsgf9d9qxlp-nix-2.11.1";
|
||||
aarch64-linux = "/nix/store/0lrf6danhdqjsrhala134ak8vn0b9ghj-nix-2.11.1";
|
||||
x86_64-darwin = "/nix/store/60sx4c6xflgqk11gvijwzlsczbxgxgwh-nix-2.11.1";
|
||||
aarch64-darwin = "/nix/store/dmk5m3nlqp1awaqrp1f06qhhkh3l102n-nix-2.11.1";
|
||||
x86_64-linux = "/nix/store/h88w1442c7hzkbw8sgpcsbqp4lhz6l5p-nix-2.12.0";
|
||||
i686-linux = "/nix/store/j23527l1c3hfx17nssc0v53sq6c741zs-nix-2.12.0";
|
||||
aarch64-linux = "/nix/store/zgzmdymyh934y3r4vqh8z337ba4cwsjb-nix-2.12.0";
|
||||
x86_64-darwin = "/nix/store/wnlrzllazdyg1nrw9na497p4w0m7i7mm-nix-2.12.0";
|
||||
aarch64-darwin = "/nix/store/7n5yamgzg5dpp5vb6ipdqgfh6cf30wmn-nix-2.12.0";
|
||||
}
|
||||
|
|
|
@ -48,10 +48,15 @@ let
|
|||
};
|
||||
scrubDerivations = namePrefix: pkgSet: mapAttrs
|
||||
(name: value:
|
||||
let wholeName = "${namePrefix}.${name}"; in
|
||||
if isAttrs value then
|
||||
let
|
||||
wholeName = "${namePrefix}.${name}";
|
||||
guard = lib.warn "Attempt to evaluate package ${wholeName} in option documentation; this is not supported and will eventually be an error. Use `mkPackageOption` or `literalExpression` instead.";
|
||||
in if isAttrs value then
|
||||
scrubDerivations wholeName value
|
||||
// (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; })
|
||||
// optionalAttrs (isDerivation value) {
|
||||
outPath = guard "\${${wholeName}}";
|
||||
drvPath = guard drvPath;
|
||||
}
|
||||
else value
|
||||
)
|
||||
pkgSet;
|
||||
|
|
|
@ -135,6 +135,7 @@
|
|||
./programs/bandwhich.nix
|
||||
./programs/bash/bash.nix
|
||||
./programs/bash/bash-completion.nix
|
||||
./programs/bash/blesh.nix
|
||||
./programs/bash/ls-colors.nix
|
||||
./programs/bash/undistract-me.nix
|
||||
./programs/bash-my-aws.nix
|
||||
|
@ -988,6 +989,7 @@
|
|||
./services/networking/tox-node.nix
|
||||
./services/networking/toxvpn.nix
|
||||
./services/networking/tvheadend.nix
|
||||
./services/networking/twingate.nix
|
||||
./services/networking/ucarp.nix
|
||||
./services/networking/unbound.nix
|
||||
./services/networking/unifi.nix
|
||||
|
@ -1015,6 +1017,7 @@
|
|||
./services/networking/zerotierone.nix
|
||||
./services/networking/znc/default.nix
|
||||
./services/printing/cupsd.nix
|
||||
./services/printing/ipp-usb.nix
|
||||
./services/scheduling/atd.nix
|
||||
./services/scheduling/cron.nix
|
||||
./services/scheduling/fcron.nix
|
||||
|
@ -1139,6 +1142,7 @@
|
|||
./services/web-apps/onlyoffice.nix
|
||||
./services/web-apps/pict-rs.nix
|
||||
./services/web-apps/peertube.nix
|
||||
./services/web-apps/peering-manager.nix
|
||||
./services/web-apps/plantuml-server.nix
|
||||
./services/web-apps/plausible.nix
|
||||
./services/web-apps/pgpkeyserver-lite.nix
|
||||
|
|
16
nixos/modules/programs/bash/blesh.nix
Normal file
16
nixos/modules/programs/bash/blesh.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.programs.bash.blesh;
|
||||
in {
|
||||
options = {
|
||||
programs.bash.blesh.enable = mkEnableOption (mdDoc "blesh");
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.bash.interactiveShellInit = mkBefore ''
|
||||
source ${pkgs.blesh}/share/blesh/ble.sh
|
||||
'';
|
||||
};
|
||||
meta.maintainers = with maintainers; [ laalsaas ];
|
||||
}
|
|
@ -20,7 +20,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.htop;
|
||||
defaultText = "pkgs.htop";
|
||||
defaultText = lib.literalExpression "pkgs.htop";
|
||||
description = lib.mdDoc ''
|
||||
The htop package that should be used.
|
||||
'';
|
||||
|
|
|
@ -29,7 +29,7 @@ in
|
|||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.weylus;
|
||||
defaultText = "pkgs.weylus";
|
||||
defaultText = lib.literalExpression "pkgs.weylus";
|
||||
description = lib.mdDoc "Weylus package to install.";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -74,7 +74,7 @@ in {
|
|||
|
||||
listen = {
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc "TCP port that will be used to accept client connections.";
|
||||
default = 8000;
|
||||
};
|
||||
|
|
|
@ -38,11 +38,13 @@ in
|
|||
|
||||
default = {};
|
||||
|
||||
example = {
|
||||
myStream1 = "/etc/liquidsoap/myStream1.liq";
|
||||
myStream2 = literalExpression "./myStream2.liq";
|
||||
myStream3 = "out(playlist(\"/srv/music/\"))";
|
||||
};
|
||||
example = literalExpression ''
|
||||
{
|
||||
myStream1 = "/etc/liquidsoap/myStream1.liq";
|
||||
myStream2 = ./myStream2.liq;
|
||||
myStream3 = "out(playlist(\"/srv/music/\"))";
|
||||
}
|
||||
'';
|
||||
|
||||
type = types.attrsOf (types.either types.path types.str);
|
||||
};
|
||||
|
|
|
@ -142,7 +142,7 @@ in {
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 6600;
|
||||
description = lib.mdDoc ''
|
||||
This setting is the TCP port that is desired for the daemon to get assigned
|
||||
|
|
|
@ -179,7 +179,7 @@ sudo borg init --encryption=repokey-blake2 \
|
|||
mode = "repokey-blake2";
|
||||
passCommand = "cat /run/keys/borgbackup_passphrase";
|
||||
};
|
||||
BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase";
|
||||
environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; };
|
||||
compression = "auto,lzma";
|
||||
startAt = "daily";
|
||||
};
|
||||
|
|
|
@ -171,7 +171,7 @@ in
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Kubernetes kubelet healthz port.";
|
||||
default = 10248;
|
||||
type = int;
|
||||
type = port;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -204,7 +204,7 @@ in
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Kubernetes kubelet info server listening port.";
|
||||
default = 10250;
|
||||
type = int;
|
||||
type = port;
|
||||
};
|
||||
|
||||
seedDockerImages = mkOption {
|
||||
|
|
|
@ -43,7 +43,7 @@ in
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Kubernetes scheduler listening port.";
|
||||
default = 10251;
|
||||
type = int;
|
||||
type = port;
|
||||
};
|
||||
|
||||
verbosity = mkOption {
|
||||
|
|
|
@ -206,7 +206,7 @@ in {
|
|||
|
||||
port = mkOption {
|
||||
default = 8010;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc "Specifies port number on which the buildbot HTTP interface listens.";
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ let
|
|||
|
||||
cfg = config.services.cassandra;
|
||||
|
||||
atLeast3 = versionAtLeast cfg.package.version "3";
|
||||
atLeast3_11 = versionAtLeast cfg.package.version "3.11";
|
||||
atLeast4 = versionAtLeast cfg.package.version "4";
|
||||
|
||||
defaultUser = "cassandra";
|
||||
|
||||
cassandraConfig = flip recursiveUpdate cfg.extraConfig (
|
||||
|
@ -39,7 +43,7 @@ let
|
|||
parameters = [{ seeds = concatStringsSep "," cfg.seedAddresses; }];
|
||||
}
|
||||
];
|
||||
} // optionalAttrs (versionAtLeast cfg.package.version "3") {
|
||||
} // optionalAttrs atLeast3 {
|
||||
hints_directory = "${cfg.homeDir}/hints";
|
||||
}
|
||||
);
|
||||
|
@ -62,7 +66,7 @@ let
|
|||
cassandraLogbackConfig = pkgs.writeText "logback.xml" cfg.logbackConfig;
|
||||
|
||||
passAsFile = [ "extraEnvSh" ];
|
||||
inherit (cfg) extraEnvSh;
|
||||
inherit (cfg) extraEnvSh package;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p "$out"
|
||||
|
@ -80,6 +84,10 @@ let
|
|||
|
||||
# Delete default password file
|
||||
sed -i '/-Dcom.sun.management.jmxremote.password.file=\/etc\/cassandra\/jmxremote.password/d' "$out/cassandra-env.sh"
|
||||
|
||||
${lib.optionalString atLeast4 ''
|
||||
cp $package/conf/jvm*.options $out/
|
||||
''}
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -95,8 +103,20 @@ let
|
|||
"-Dcom.sun.management.jmxremote.password.file=${cfg.jmxRolesFile}"
|
||||
] ++ optionals cfg.remoteJmx [
|
||||
"-Djava.rmi.server.hostname=${cfg.rpcAddress}"
|
||||
] ++ optionals atLeast4 [
|
||||
# Historically, we don't use a log dir, whereas the upstream scripts do
|
||||
# expect this. We override those by providing our own -Xlog:gc flag.
|
||||
"-Xlog:gc=warning,heap*=warning,age*=warning,safepoint=warning,promotion*=warning"
|
||||
];
|
||||
|
||||
commonEnv = {
|
||||
# Sufficient for cassandra 2.x, 3.x
|
||||
CASSANDRA_CONF = "${cassandraEtc}";
|
||||
|
||||
# Required since cassandra 4
|
||||
CASSANDRA_LOGBACK_CONF = "${cassandraEtc}/logback.xml";
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options.services.cassandra = {
|
||||
|
@ -435,7 +455,7 @@ in
|
|||
jmxRolesFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default =
|
||||
if versionAtLeast cfg.package.version "3.11"
|
||||
if atLeast3_11
|
||||
then pkgs.writeText "jmx-roles-file" defaultJmxRolesFile
|
||||
else null;
|
||||
defaultText = literalMD ''generated configuration file if version is at least 3.11, otherwise `null`'';
|
||||
|
@ -486,8 +506,7 @@ in
|
|||
systemd.services.cassandra = {
|
||||
description = "Apache Cassandra service";
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
CASSANDRA_CONF = "${cassandraEtc}";
|
||||
environment = commonEnv // {
|
||||
JVM_OPTS = builtins.concatStringsSep " " fullJvmOptions;
|
||||
MAX_HEAP_SIZE = toString cfg.maxHeapSize;
|
||||
HEAP_NEWSIZE = toString cfg.heapNewSize;
|
||||
|
@ -508,6 +527,7 @@ in
|
|||
description = "Perform a full repair on this Cassandra node";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
environment = commonEnv;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
@ -536,6 +556,7 @@ in
|
|||
description = "Perform an incremental repair on this cassandra node.";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
environment = commonEnv;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
|
|
@ -16,7 +16,7 @@ with lib;
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.clickhouse;
|
||||
defaultText = "pkgs.clickhouse";
|
||||
defaultText = lib.literalExpression "pkgs.clickhouse";
|
||||
description = lib.mdDoc ''
|
||||
ClickHouse package to use.
|
||||
'';
|
||||
|
|
|
@ -160,10 +160,12 @@ in
|
|||
List of database names and their initial schemas that should be used to create databases on the first startup
|
||||
of MySQL. The schema attribute is optional: If not specified, an empty database is created.
|
||||
'';
|
||||
example = [
|
||||
{ name = "foodatabase"; schema = literalExpression "./foodatabase.sql"; }
|
||||
{ name = "bardatabase"; }
|
||||
];
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ name = "foodatabase"; schema = ./foodatabase.sql; }
|
||||
{ name = "bardatabase"; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
initialScript = mkOption {
|
||||
|
|
|
@ -16,7 +16,7 @@ let
|
|||
# systemd/systemd#19604
|
||||
description = ''
|
||||
LDAP value - either a string, or an attrset containing
|
||||
<literal>path</literal> or <literal>base64</literal> for included
|
||||
`path` or `base64` for included
|
||||
values or base-64 encoded values respectively.
|
||||
'';
|
||||
check = x: lib.isString x || (lib.isAttrs x && (x ? path || x ? base64));
|
||||
|
|
|
@ -57,7 +57,7 @@ in {
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 8888;
|
||||
description = lib.mdDoc ''
|
||||
Port number Jupyter will be listening on.
|
||||
|
|
|
@ -43,12 +43,14 @@ in
|
|||
web-ui = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
enable = mkEnableOption
|
||||
(lib.mdDoc "Wheter to start the web-ui. This is the preferred way of configuring things such as the steam guard token");
|
||||
enable = mkEnableOption "" // {
|
||||
description = lib.mdDoc "Whether to start the web-ui. This is the preferred way of configuring things such as the steam guard token.";
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.ArchiSteamFarm.ui;
|
||||
defaultText = lib.literalExpression "pkgs.ArchiSteamFarm.ui";
|
||||
description =
|
||||
lib.mdDoc "Web-UI package to use. Contents must be in lib/dist.";
|
||||
};
|
||||
|
@ -56,7 +58,6 @@ in
|
|||
};
|
||||
default = {
|
||||
enable = true;
|
||||
package = pkgs.ArchiSteamFarm.ui;
|
||||
};
|
||||
example = {
|
||||
enable = false;
|
||||
|
@ -67,6 +68,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.ArchiSteamFarm;
|
||||
defaultText = lib.literalExpression "pkgs.ArchiSteamFarm";
|
||||
description =
|
||||
lib.mdDoc "Package to use. Should always be the latest version, for security reasons, since this module uses very new features and to not get out of sync with the Steam API.";
|
||||
};
|
||||
|
|
|
@ -116,7 +116,7 @@ in
|
|||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc "Wheter to open ports in the firewall";
|
||||
description = lib.mdDoc "Whether to open ports in the firewall";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
|
|
|
@ -9,7 +9,7 @@ in
|
|||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.argononed;
|
||||
defaultText = "pkgs.argononed";
|
||||
defaultText = lib.literalExpression "pkgs.argononed";
|
||||
description = lib.mdDoc ''
|
||||
The package implementing the Argon One driver
|
||||
'';
|
||||
|
|
|
@ -50,14 +50,8 @@ in
|
|||
type = types.package;
|
||||
default = pkgs.bluez;
|
||||
defaultText = literalExpression "pkgs.bluez";
|
||||
example = literalExpression "pkgs.bluezFull";
|
||||
description = lib.mdDoc ''
|
||||
Which BlueZ package to use.
|
||||
|
||||
::: {.note}
|
||||
Use the `pkgs.bluezFull` package to enable all
|
||||
bluez plugins.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ with lib;
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.joycond;
|
||||
defaultText = "pkgs.joycond";
|
||||
defaultText = lib.literalExpression "pkgs.joycond";
|
||||
description = lib.mdDoc ''
|
||||
The joycond package to use.
|
||||
'';
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let
|
||||
cfg = config.services.supergfxd;
|
||||
ini = pkgs.formats.ini { };
|
||||
json = pkgs.formats.json { };
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
@ -10,7 +10,7 @@ in
|
|||
enable = lib.mkEnableOption (lib.mdDoc "Enable the supergfxd service");
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.nullOr ini.type;
|
||||
type = lib.types.nullOr json.type;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
The content of /etc/supergfxd.conf.
|
||||
|
@ -23,7 +23,7 @@ in
|
|||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.supergfxctl ];
|
||||
|
||||
environment.etc."supergfxd.conf" = lib.mkIf (cfg.settings != null) (ini.generate "supergfxd.conf" cfg.settings);
|
||||
environment.etc."supergfxd.conf".source = lib.mkIf (cfg.settings != null) (json.generate "supergfxd.conf" cfg.settings);
|
||||
|
||||
services.dbus.enable = true;
|
||||
|
||||
|
|
|
@ -435,6 +435,7 @@ in {
|
|||
"august"
|
||||
"august_ble"
|
||||
"airthings_ble"
|
||||
"aranet"
|
||||
"bluemaestro"
|
||||
"bluetooth"
|
||||
"bluetooth_le_tracker"
|
||||
|
@ -453,8 +454,11 @@ in {
|
|||
"moat"
|
||||
"oralb"
|
||||
"qingping"
|
||||
"ruuvitag_ble"
|
||||
"sensirion_ble"
|
||||
"sensorpro"
|
||||
"sensorpush"
|
||||
"shelly"
|
||||
"snooz"
|
||||
"switchbot"
|
||||
"thermobeacon"
|
||||
|
|
|
@ -23,8 +23,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.matrix-conduit;
|
||||
defaultText = "pkgs.matrix-conduit";
|
||||
example = "pkgs.matrix-conduit";
|
||||
defaultText = lib.literalExpression "pkgs.matrix-conduit";
|
||||
description = lib.mdDoc ''
|
||||
Package of the conduit matrix server to use.
|
||||
'';
|
||||
|
|
|
@ -286,6 +286,7 @@ in {
|
|||
log_config = mkOption {
|
||||
type = types.path;
|
||||
default = ./synapse-log_config.yaml;
|
||||
defaultText = lib.literalExpression "nixos/modules/services/matrix/synapse-log_config.yaml";
|
||||
description = lib.mdDoc ''
|
||||
The file that holds the logging configuration.
|
||||
'';
|
||||
|
|
|
@ -258,7 +258,7 @@ in {
|
|||
type = hooksModule;
|
||||
description = lib.mdDoc "Global hook scripts";
|
||||
default = { };
|
||||
example = ''
|
||||
example = literalExpression ''
|
||||
{
|
||||
postswitch = {
|
||||
"notify-i3" = "''${pkgs.i3}/bin/i3-msg restart";
|
||||
|
@ -279,7 +279,7 @@ in {
|
|||
exit 1
|
||||
esac
|
||||
echo "Xft.dpi: $DPI" | ''${pkgs.xorg.xrdb}/bin/xrdb -merge
|
||||
'''
|
||||
''';
|
||||
};
|
||||
}
|
||||
'';
|
||||
|
|
|
@ -560,7 +560,7 @@ in {
|
|||
description = lib.mdDoc "GitLab container registry host name.";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 4567;
|
||||
description = lib.mdDoc "GitLab container registry port.";
|
||||
};
|
||||
|
@ -613,7 +613,7 @@ in {
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 25;
|
||||
description = lib.mdDoc "Port of the SMTP server for GitLab.";
|
||||
};
|
||||
|
|
|
@ -28,8 +28,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.heisenbridge;
|
||||
defaultText = "pkgs.heisenbridge";
|
||||
example = "pkgs.heisenbridge.override { … = …; }";
|
||||
defaultText = lib.literalExpression "pkgs.heisenbridge";
|
||||
description = lib.mdDoc ''
|
||||
Package of the application to run, exposed for overriding purposes.
|
||||
'';
|
||||
|
|
|
@ -15,6 +15,13 @@ in
|
|||
services.libreddit = {
|
||||
enable = mkEnableOption (lib.mdDoc "Private front-end for Reddit");
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.libreddit;
|
||||
defaultText = literalExpression "pkgs.libreddit";
|
||||
description = lib.mdDoc "Libreddit package to use.";
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
default = "0.0.0.0";
|
||||
example = "127.0.0.1";
|
||||
|
@ -45,7 +52,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = "${pkgs.libreddit}/bin/libreddit ${args}";
|
||||
ExecStart = "${cfg.package}/bin/libreddit ${args}";
|
||||
AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
||||
Restart = "on-failure";
|
||||
RestartSec = "2s";
|
||||
|
|
|
@ -29,7 +29,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.portunus;
|
||||
defaultText = "pkgs.portunus";
|
||||
defaultText = lib.literalExpression "pkgs.portunus";
|
||||
description = lib.mdDoc "The Portunus package to use.";
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.openldap;
|
||||
defaultText = "pkgs.openldap";
|
||||
defaultText = lib.literalExpression "pkgs.openldap";
|
||||
description = lib.mdDoc "The OpenLDAP package to use.";
|
||||
};
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ in {
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Ripple data api port";
|
||||
default = 5993;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
};
|
||||
|
||||
importMode = mkOption {
|
||||
|
@ -77,7 +77,7 @@ in {
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Ripple data api redis port.";
|
||||
default = 5984;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ in {
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Ripple data api couchdb port.";
|
||||
default = 5984;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
};
|
||||
|
||||
db = mkOption {
|
||||
|
|
|
@ -505,7 +505,7 @@ in
|
|||
description = lib.mdDoc "Origin URL for API, 100 more than web.";
|
||||
type = types.str;
|
||||
default = "http://${cfg.listenAddress}:${toString (cfg.meta.port + 100)}";
|
||||
defaultText = ''http://<xref linkend="opt-services.sourcehut.listenAddress"/>:''${toString (<xref linkend="opt-services.sourcehut.meta.port"/> + 100)}'';
|
||||
defaultText = lib.literalMD ''`"http://''${`[](#opt-services.sourcehut.listenAddress)`}:''${toString (`[](#opt-services.sourcehut.meta.port)` + 100)}"`'';
|
||||
};
|
||||
webhooks = mkOption {
|
||||
description = lib.mdDoc "The Redis connection used for the webhooks worker.";
|
||||
|
|
|
@ -16,7 +16,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.grafana-agent;
|
||||
defaultText = "pkgs.grafana-agent";
|
||||
defaultText = lib.literalExpression "pkgs.grafana-agent";
|
||||
description = lib.mdDoc "The grafana-agent package to use.";
|
||||
};
|
||||
|
||||
|
@ -49,17 +49,19 @@ in
|
|||
};
|
||||
|
||||
default = { };
|
||||
defaultText = ''
|
||||
metrics = {
|
||||
wal_directory = "\''${STATE_DIRECTORY}";
|
||||
global.scrape_interval = "5s";
|
||||
};
|
||||
integrations = {
|
||||
agent.enabled = true;
|
||||
agent.scrape_integration = true;
|
||||
node_exporter.enabled = true;
|
||||
replace_instance_label = true;
|
||||
};
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
metrics = {
|
||||
wal_directory = "\''${STATE_DIRECTORY}";
|
||||
global.scrape_interval = "5s";
|
||||
};
|
||||
integrations = {
|
||||
agent.enabled = true;
|
||||
agent.scrape_integration = true;
|
||||
node_exporter.enabled = true;
|
||||
replace_instance_label = true;
|
||||
};
|
||||
}
|
||||
'';
|
||||
example = {
|
||||
metrics.global.remote_write = [{
|
||||
|
|
|
@ -225,7 +225,7 @@ in {
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Seyren listening port.";
|
||||
default = 8081;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
};
|
||||
|
||||
seyrenUrl = mkOption {
|
||||
|
|
|
@ -66,7 +66,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 9092;
|
||||
description = lib.mdDoc "Port of Kapacitor";
|
||||
};
|
||||
|
|
|
@ -107,7 +107,7 @@ in {
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 9093;
|
||||
description = lib.mdDoc ''
|
||||
Port to listen on for the web interface and API.
|
||||
|
|
|
@ -4,16 +4,12 @@ with lib;
|
|||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.smartctl;
|
||||
format = pkgs.formats.yaml {};
|
||||
configFile = format.generate "smartctl-exporter.yml" {
|
||||
smartctl_exporter = {
|
||||
bind_to = "${cfg.listenAddress}:${toString cfg.port}";
|
||||
url_path = "/metrics";
|
||||
smartctl_location = "${pkgs.smartmontools}/bin/smartctl";
|
||||
collect_not_more_than_period = cfg.maxInterval;
|
||||
devices = cfg.devices;
|
||||
};
|
||||
};
|
||||
args = concatStrings [
|
||||
"--web.listen-address=\"${cfg.listenAddress}:${toString cfg.port}\" "
|
||||
"--smartctl.path=\"${pkgs.smartmontools}/bin/smartctl\" "
|
||||
"--smartctl.interval=\"${cfg.maxInterval}\" "
|
||||
"${concatMapStringsSep " " (device: "--smartctl.device=${device}") cfg.devices}"
|
||||
];
|
||||
in {
|
||||
port = 9633;
|
||||
|
||||
|
@ -50,17 +46,13 @@ in {
|
|||
"CAP_SYS_ADMIN"
|
||||
];
|
||||
DevicePolicy = "closed";
|
||||
DeviceAllow = lib.mkOverride 50 (
|
||||
if cfg.devices != [] then
|
||||
cfg.devices
|
||||
else [
|
||||
"block-blkext rw"
|
||||
"block-sd rw"
|
||||
"char-nvme rw"
|
||||
]
|
||||
);
|
||||
DeviceAllow = lib.mkOverride 50 [
|
||||
"block-blkext rw"
|
||||
"block-sd rw"
|
||||
"char-nvme rw"
|
||||
];
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-smartctl-exporter}/bin/smartctl_exporter -config ${configFile}
|
||||
${pkgs.prometheus-smartctl-exporter}/bin/smartctl_exporter ${args}
|
||||
'';
|
||||
PrivateDevices = lib.mkForce false;
|
||||
ProtectProc = "invisible";
|
||||
|
|
|
@ -13,9 +13,8 @@ in
|
|||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
example = literalExpression "pkgs.uptime-kuma";
|
||||
default = pkgs.uptime-kuma;
|
||||
defaultText = "pkgs.uptime-kuma";
|
||||
defaultText = literalExpression "pkgs.uptime-kuma";
|
||||
description = lib.mdDoc "Uptime Kuma package to use.";
|
||||
};
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = if cfg.database.type == "mysql" then mysql.port else pgsql.port;
|
||||
defaultText = literalExpression ''
|
||||
if config.${opt.database.type} == "mysql"
|
||||
|
|
|
@ -18,7 +18,7 @@ in
|
|||
};
|
||||
tub.port = mkOption {
|
||||
default = 3458;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc ''
|
||||
The port on which the introducer will listen.
|
||||
'';
|
||||
|
@ -58,7 +58,7 @@ in
|
|||
};
|
||||
tub.port = mkOption {
|
||||
default = 3457;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc ''
|
||||
The port on which the tub will listen.
|
||||
|
||||
|
@ -80,7 +80,7 @@ in
|
|||
};
|
||||
web.port = mkOption {
|
||||
default = 3456;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc ''
|
||||
The port on which the Web server will listen.
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ with lib;
|
|||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.ddclient;
|
||||
defaultText = "pkgs.ddclient";
|
||||
defaultText = lib.literalExpression "pkgs.ddclient";
|
||||
description = lib.mdDoc ''
|
||||
The ddclient executable package run by the service.
|
||||
'';
|
||||
|
|
|
@ -7,15 +7,27 @@ let
|
|||
dnsmasq = pkgs.dnsmasq;
|
||||
stateDir = "/var/lib/dnsmasq";
|
||||
|
||||
# True values are just put as `name` instead of `name=true`, and false values
|
||||
# are turned to comments (false values are expected to be overrides e.g.
|
||||
# mkForce)
|
||||
formatKeyValue =
|
||||
name: value:
|
||||
if value == true
|
||||
then name
|
||||
else if value == false
|
||||
then "# setting `${name}` explicitly set to false"
|
||||
else generators.mkKeyValueDefault { } "=" name value;
|
||||
|
||||
settingsFormat = pkgs.formats.keyValue {
|
||||
mkKeyValue = formatKeyValue;
|
||||
listsAsDuplicateKeys = true;
|
||||
};
|
||||
|
||||
# Because formats.generate is outputting a file, we use of conf-file. Once
|
||||
# `extraConfig` is deprecated we can just use
|
||||
# `dnsmasqConf = format.generate "dnsmasq.conf" cfg.settings`
|
||||
dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
|
||||
dhcp-leasefile=${stateDir}/dnsmasq.leases
|
||||
${optionalString cfg.resolveLocalQueries ''
|
||||
conf-file=/etc/dnsmasq-conf.conf
|
||||
resolv-file=/etc/dnsmasq-resolv.conf
|
||||
''}
|
||||
${flip concatMapStrings cfg.servers (server: ''
|
||||
server=${server}
|
||||
'')}
|
||||
conf-file=${settingsFormat.generate "dnsmasq.conf" cfg.settings}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
|
@ -23,6 +35,10 @@ in
|
|||
|
||||
{
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "dnsmasq" "servers" ] [ "services" "dnsmasq" "settings" "server" ])
|
||||
];
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
@ -46,15 +62,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
servers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "8.8.8.8" "8.8.4.4" ];
|
||||
description = lib.mdDoc ''
|
||||
The DNS servers which dnsmasq should query.
|
||||
'';
|
||||
};
|
||||
|
||||
alwaysKeepRunning = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -63,12 +70,49 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.server = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "8.8.8.8" "8.8.4.4" ];
|
||||
description = lib.mdDoc ''
|
||||
The DNS servers which dnsmasq should query.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
default = { };
|
||||
description = lib.mdDoc ''
|
||||
Configuration of dnsmasq. Lists get added one value per line (empty
|
||||
lists and false values don't get added, though false values get
|
||||
turned to comments). Gets merged with
|
||||
|
||||
{
|
||||
dhcp-leasefile = "${stateDir}/dnsmasq.leases";
|
||||
conf-file = optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf";
|
||||
resolv-file = optional cfg.resolveLocalQueries "/etc/dnsmasq-resolv.conf";
|
||||
}
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
domain-needed = true;
|
||||
dhcp-range = [ "192.168.0.2,192.168.0.254" ];
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = lib.mdDoc ''
|
||||
Extra configuration directives that should be added to
|
||||
`dnsmasq.conf`.
|
||||
|
||||
This option is deprecated, please use {option}`settings` instead.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -81,6 +125,14 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
warnings = lib.optional (cfg.extraConfig != "") "Text based config is deprecated, dnsmasq now supports `services.dnsmasq.settings` for an attribute-set based config";
|
||||
|
||||
services.dnsmasq.settings = {
|
||||
dhcp-leasefile = mkDefault "${stateDir}/dnsmasq.leases";
|
||||
conf-file = mkDefault (optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf");
|
||||
resolv-file = mkDefault (optional cfg.resolveLocalQueries "/etc/dnsmasq-resolv.conf");
|
||||
};
|
||||
|
||||
networking.nameservers =
|
||||
optional cfg.resolveLocalQueries "127.0.0.1";
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ in {
|
|||
configFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = (pkgs.formats.yaml {}).generate "ergo.conf" cfg.settings;
|
||||
defaultText = "generated config file from <literal>.settings</literal>";
|
||||
defaultText = lib.literalMD "generated config file from `settings`";
|
||||
description = lib.mdDoc ''
|
||||
Path to configuration file.
|
||||
Setting this will skip any configuration done via `.settings`
|
||||
Setting this will skip any configuration done via `settings`
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 3000;
|
||||
description = lib.mdDoc "Listing port";
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@ in {
|
|||
type = package;
|
||||
description = lib.mdDoc "multipath-tools package to use";
|
||||
default = pkgs.multipath-tools;
|
||||
defaultText = "pkgs.multipath-tools";
|
||||
defaultText = lib.literalExpression "pkgs.multipath-tools";
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
|
|
|
@ -67,7 +67,7 @@ in
|
|||
Additional plugins dir used to configure nomad.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[ "<pluginDir>" "pkgs.<plugins-name>"]
|
||||
[ "<pluginDir>" pkgs.<plugins-name> ]
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -588,7 +588,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 53;
|
||||
description = lib.mdDoc ''
|
||||
Port the service should bind do.
|
||||
|
@ -825,7 +825,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 8952;
|
||||
description = lib.mdDoc ''
|
||||
Port number for remote control operations (uses TLS over TCP).
|
||||
|
|
|
@ -81,7 +81,7 @@ let
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 1080;
|
||||
description = lib.mdDoc ''
|
||||
What port to listen for client requests, default is 1080.
|
||||
|
|
|
@ -38,7 +38,7 @@ in {
|
|||
};
|
||||
|
||||
dns.port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 53;
|
||||
description = lib.mdDoc ''
|
||||
Port number Recursor DNS server will bind to.
|
||||
|
@ -67,7 +67,7 @@ in {
|
|||
};
|
||||
|
||||
api.port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 8082;
|
||||
description = lib.mdDoc ''
|
||||
Port number Recursor REST API server will bind to.
|
||||
|
|
|
@ -81,7 +81,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 12345;
|
||||
description = lib.mdDoc "Port on which redsocks should listen.";
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.sabnzbd;
|
||||
defaultText = "pkgs.sabnzbd";
|
||||
defaultText = lib.literalExpression "pkgs.sabnzbd";
|
||||
description = lib.mdDoc "The sabnzbd executable package run by the service.";
|
||||
};
|
||||
|
||||
|
|
28
nixos/modules/services/networking/twingate.nix
Normal file
28
nixos/modules/services/networking/twingate.nix
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.twingate;
|
||||
|
||||
in {
|
||||
|
||||
options.services.twingate = {
|
||||
enable = mkEnableOption (lib.mdDoc "Twingate Client daemon");
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
networking.firewall.checkReversePath = lib.mkDefault false;
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
environment.systemPackages = [ pkgs.twingate ]; # for the CLI
|
||||
systemd.packages = [ pkgs.twingate ];
|
||||
|
||||
systemd.services.twingate.preStart = ''
|
||||
cp -r -n ${pkgs.twingate}/etc/twingate/. /etc/twingate/
|
||||
'';
|
||||
|
||||
systemd.services.twingate.wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
|
@ -18,7 +18,7 @@ let
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.ints.u16;
|
||||
type = types.port;
|
||||
default = 6697;
|
||||
description = lib.mdDoc ''
|
||||
IRC server port.
|
||||
|
@ -188,7 +188,7 @@ in
|
|||
|
||||
port = mkOption {
|
||||
default = 5000;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc ''
|
||||
Specifies the port on which to listen.
|
||||
'';
|
||||
|
|
63
nixos/modules/services/printing/ipp-usb.nix
Normal file
63
nixos/modules/services/printing/ipp-usb.nix
Normal file
|
@ -0,0 +1,63 @@
|
|||
{ config, lib, pkgs, ... }: {
|
||||
options = {
|
||||
services.ipp-usb = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "ipp-usb, a daemon to turn an USB printer/scanner supporting IPP everywhere (aka AirPrint, WSD, AirScan) into a locally accessible network printer/scanner");
|
||||
};
|
||||
};
|
||||
config = lib.mkIf config.services.ipp-usb.enable {
|
||||
systemd.services.ipp-usb = {
|
||||
description = "Daemon for IPP over USB printer support";
|
||||
after = [ "cups.service" "avahi-deamon.service" ];
|
||||
wants = [ "avahi-daemon.service" ];
|
||||
serviceConfig = {
|
||||
ExecStart = [ "${pkgs.ipp-usb}/bin/ipp-usb" ];
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
StateDirectory = "ipp-usb";
|
||||
LogsDirectory = "ipp-usb";
|
||||
|
||||
# hardening.
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectControlGroups = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
# breaks the daemon, presumably because it messes with DeviceAllow
|
||||
ProtectClock = false;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectSystem = "strict";
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
PrivateMounts = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelModules = true;
|
||||
RemoveIPC = true;
|
||||
RestrictNamespaces = true;
|
||||
AmbientCapabilities = "";
|
||||
CapabilityBoundingSet = "";
|
||||
NoNewPrivileges = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_NETLINK" "AF_INET" "AF_INET6" ];
|
||||
ProtectProc = "noaccess";
|
||||
};
|
||||
};
|
||||
|
||||
# starts the systemd service
|
||||
services.udev.packages = [ pkgs.ipp-usb ];
|
||||
services.avahi = {
|
||||
enable = true;
|
||||
publish = {
|
||||
enable = true;
|
||||
userServices = true;
|
||||
};
|
||||
};
|
||||
# enable printing and scanning by default, but not required.
|
||||
services.printing.enable = lib.mkDefault true;
|
||||
hardware.sane.enable = lib.mkDefault true;
|
||||
# so that sane discovers scanners
|
||||
hardware.sane.extraBackends = [ pkgs.sane-airscan ];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ in {
|
|||
};
|
||||
port = mkOption {
|
||||
description = lib.mdDoc "the port that elasticsearch is listening on";
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 9200;
|
||||
};
|
||||
actionYAML = mkOption {
|
||||
|
|
|
@ -66,7 +66,7 @@ in
|
|||
port = mkOption {
|
||||
description = lib.mdDoc "Elasticsearch port to listen for HTTP traffic.";
|
||||
default = 9200;
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
};
|
||||
|
||||
tcp_port = mkOption {
|
||||
|
|
|
@ -21,7 +21,7 @@ in
|
|||
package = mkOption {
|
||||
description = lib.mdDoc "The package to use for meilisearch. Use this if you require specific features to be enabled. The default package has no features.";
|
||||
default = pkgs.meilisearch;
|
||||
defaultText = "pkgs.meilisearch";
|
||||
defaultText = lib.literalExpression "pkgs.meilisearch";
|
||||
type = types.package;
|
||||
};
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ in {
|
|||
InterceptUnknown = mkOption {
|
||||
type = types.bool;
|
||||
description = mdDoc ''
|
||||
Wheter to intercept spare connections.
|
||||
Whether to intercept spare connections.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ let
|
|||
in
|
||||
|
||||
{
|
||||
config = mkIf (cfg.enable && kerberos == pkgs.krb5Full) {
|
||||
config = mkIf (cfg.enable && kerberos == pkgs.krb5) {
|
||||
systemd.services.kadmind = {
|
||||
description = "Kerberos Administration Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
|
|
@ -15,7 +15,7 @@ in {
|
|||
|
||||
package = mkOption {
|
||||
default = pkgs.code-server;
|
||||
defaultText = "pkgs.code-server";
|
||||
defaultText = lib.literalExpression "pkgs.code-server";
|
||||
description = lib.mdDoc "Which code-server derivation to use.";
|
||||
type = types.package;
|
||||
};
|
||||
|
|
|
@ -449,7 +449,7 @@ in
|
|||
'';
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = 9000;
|
||||
description = lib.mdDoc ''
|
||||
Minio listen port.
|
||||
|
|
|
@ -151,7 +151,7 @@ in
|
|||
package = lib.mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.invidious;
|
||||
defaultText = "pkgs.invidious";
|
||||
defaultText = lib.literalExpression "pkgs.invidious";
|
||||
description = lib.mdDoc "The Invidious package to use.";
|
||||
};
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default = if cfg.database.type == "pgsql" then 5442 else 3306;
|
||||
defaultText = literalExpression "3306";
|
||||
description = lib.mdDoc "Database host port.";
|
||||
|
|
|
@ -546,7 +546,7 @@ in {
|
|||
environment = env;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
EnvironmentFile = [ "/var/lib/mastodon/.secrets_env" ];
|
||||
WorkingDirectory = cfg.package;
|
||||
# System Call Filtering
|
||||
SystemCallFilter = [ ("~" + lib.concatStringsSep " " (systemCallsList ++ [ "@resources" ])) "@chown" "pipe" "pipe2" ];
|
||||
|
@ -574,7 +574,7 @@ in {
|
|||
ExecStart = "${cfg.package}/run-streaming.sh";
|
||||
Restart = "always";
|
||||
RestartSec = 20;
|
||||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
EnvironmentFile = [ "/var/lib/mastodon/.secrets_env" ];
|
||||
WorkingDirectory = cfg.package;
|
||||
# Runtime directory and mode
|
||||
RuntimeDirectory = "mastodon-streaming";
|
||||
|
@ -601,7 +601,7 @@ in {
|
|||
ExecStart = "${cfg.package}/bin/puma -C config/puma.rb";
|
||||
Restart = "always";
|
||||
RestartSec = 20;
|
||||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
EnvironmentFile = [ "/var/lib/mastodon/.secrets_env" ];
|
||||
WorkingDirectory = cfg.package;
|
||||
# Runtime directory and mode
|
||||
RuntimeDirectory = "mastodon-web";
|
||||
|
@ -629,7 +629,7 @@ in {
|
|||
ExecStart = "${cfg.package}/bin/sidekiq -c ${toString cfg.sidekiqThreads} -r ${cfg.package}";
|
||||
Restart = "always";
|
||||
RestartSec = 20;
|
||||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
EnvironmentFile = [ "/var/lib/mastodon/.secrets_env" ];
|
||||
WorkingDirectory = cfg.package;
|
||||
# System Call Filtering
|
||||
SystemCallFilter = [ ("~" + lib.concatStringsSep " " systemCallsList) "@chown" "pipe" "pipe2" ];
|
||||
|
@ -642,7 +642,7 @@ in {
|
|||
environment = env;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
EnvironmentFile = [ "/var/lib/mastodon/.secrets_env" ];
|
||||
} // cfgService;
|
||||
script = let
|
||||
olderThanDays = toString cfg.mediaAutoRemove.olderThanDays;
|
||||
|
|
|
@ -106,7 +106,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.mattermost;
|
||||
defaultText = "pkgs.mattermost";
|
||||
defaultText = lib.literalExpression "pkgs.mattermost";
|
||||
description = lib.mdDoc "Mattermost derivation to use.";
|
||||
};
|
||||
|
||||
|
@ -238,7 +238,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.matterircd;
|
||||
defaultText = "pkgs.matterircd";
|
||||
defaultText = lib.literalExpression "pkgs.matterircd";
|
||||
description = lib.mdDoc "matterircd derivation to use.";
|
||||
};
|
||||
parameters = mkOption {
|
||||
|
|
|
@ -96,7 +96,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc "Database host port.";
|
||||
default = {
|
||||
mysql = 3306;
|
||||
|
|
|
@ -29,7 +29,7 @@ in
|
|||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.onlyoffice-documentserver;
|
||||
defaultText = "pkgs.onlyoffice-documentserver";
|
||||
defaultText = lib.literalExpression "pkgs.onlyoffice-documentserver";
|
||||
description = lib.mdDoc "Which package to use for the OnlyOffice instance.";
|
||||
};
|
||||
|
||||
|
|
265
nixos/modules/services/web-apps/peering-manager.nix
Normal file
265
nixos/modules/services/web-apps/peering-manager.nix
Normal file
|
@ -0,0 +1,265 @@
|
|||
{ config, lib, pkgs, buildEnv, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.peering-manager;
|
||||
configFile = pkgs.writeTextFile {
|
||||
name = "configuration.py";
|
||||
text = ''
|
||||
ALLOWED_HOSTS = ['*']
|
||||
DATABASE = {
|
||||
'NAME': 'peering-manager',
|
||||
'USER': 'peering-manager',
|
||||
'HOST': '/run/postgresql',
|
||||
}
|
||||
|
||||
# Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
|
||||
# configuration exists for each. Full connection details are required in both sections, and it is strongly recommended
|
||||
# to use two separate database IDs.
|
||||
REDIS = {
|
||||
'tasks': {
|
||||
'UNIX_SOCKET_PATH': '${config.services.redis.servers.peering-manager.unixSocket}',
|
||||
'DATABASE': 0,
|
||||
},
|
||||
'caching': {
|
||||
'UNIX_SOCKET_PATH': '${config.services.redis.servers.peering-manager.unixSocket}',
|
||||
'DATABASE': 1,
|
||||
}
|
||||
}
|
||||
|
||||
with open("${cfg.secretKeyFile}", "r") as file:
|
||||
SECRET_KEY = file.readline()
|
||||
'' + lib.optionalString (cfg.peeringdbApiKeyFile != null) ''
|
||||
with open("${cfg.peeringdbApiKeyFile}", "r") as file:
|
||||
PEERINGDB_API_KEY = file.readline()
|
||||
'' + ''
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
};
|
||||
pkg = (pkgs.peering-manager.overrideAttrs (old: {
|
||||
postInstall = ''
|
||||
ln -s ${configFile} $out/opt/peering-manager/peering_manager/configuration.py
|
||||
'' + optionalString cfg.enableLdap ''
|
||||
ln -s ${cfg.ldapConfigPath} $out/opt/peering-manager/peering_manager/ldap_config.py
|
||||
'';
|
||||
})).override {
|
||||
inherit (cfg) plugins;
|
||||
};
|
||||
peeringManagerManageScript = with pkgs; (writeScriptBin "peering-manager-manage" ''
|
||||
#!${stdenv.shell}
|
||||
export PYTHONPATH=${pkg.pythonPath}
|
||||
sudo -u peering-manager ${pkg}/bin/peering-manager "$@"
|
||||
'');
|
||||
|
||||
in {
|
||||
options.services.peering-manager = {
|
||||
enable = mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Enable Peering Manager.
|
||||
|
||||
This module requires a reverse proxy that serves `/static` separately.
|
||||
See this [example](https://github.com/peering-manager-community/peering-manager/blob/develop/contrib/nginx.conf/) on how to configure this.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "[::1]";
|
||||
description = lib.mdDoc ''
|
||||
Address the server will listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8001;
|
||||
description = lib.mdDoc ''
|
||||
Port the server will listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
type = types.functionTo (types.listOf types.package);
|
||||
default = _: [];
|
||||
defaultText = literalExpression ''
|
||||
python3Packages: with python3Packages; [];
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
List of plugin packages to install.
|
||||
'';
|
||||
};
|
||||
|
||||
secretKeyFile = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
Path to a file containing the secret key.
|
||||
'';
|
||||
};
|
||||
|
||||
peeringdbApiKeyFile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Path to a file containing the PeeringDB API key.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = lib.mdDoc ''
|
||||
Additional lines of configuration appended to the `configuration.py`.
|
||||
See the [documentation](https://peering-manager.readthedocs.io/en/stable/configuration/optional-settings/) for more possible options.
|
||||
'';
|
||||
};
|
||||
|
||||
enableLdap = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Enable LDAP-Authentication for Peering Manager.
|
||||
|
||||
This requires a configuration file being pass through `ldapConfigPath`.
|
||||
'';
|
||||
};
|
||||
|
||||
ldapConfigPath = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
Path to the Configuration-File for LDAP-Authentification, will be loaded as `ldap_config.py`.
|
||||
See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6-ldap/#configuration) for possible options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.peering-manager.plugins = mkIf cfg.enableLdap (ps: [ ps.django-auth-ldap ]);
|
||||
|
||||
system.build.peeringManagerPkg = pkg;
|
||||
|
||||
services.redis.servers.peering-manager.enable = true;
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "peering-manager" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "peering-manager";
|
||||
ensurePermissions = {
|
||||
"DATABASE \"peering-manager\"" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = [ peeringManagerManageScript ];
|
||||
|
||||
systemd.targets.peering-manager = {
|
||||
description = "Target for all Peering Manager services";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" "redis-peering-manager.service" ];
|
||||
};
|
||||
|
||||
systemd.services = let
|
||||
defaultServiceConfig = {
|
||||
WorkingDirectory = "/var/lib/peering-manager";
|
||||
User = "peering-manager";
|
||||
Group = "peering-manager";
|
||||
StateDirectory = "peering-manager";
|
||||
StateDirectoryMode = "0750";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
in {
|
||||
peering-manager-migration = {
|
||||
description = "Peering Manager migrations";
|
||||
wantedBy = [ "peering-manager.target" ];
|
||||
|
||||
environment = {
|
||||
PYTHONPATH = pkg.pythonPath;
|
||||
};
|
||||
|
||||
serviceConfig = defaultServiceConfig // {
|
||||
Type = "oneshot";
|
||||
ExecStart = ''
|
||||
${pkg}/bin/peering-manager migrate
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
peering-manager = {
|
||||
description = "Peering Manager WSGI Service";
|
||||
wantedBy = [ "peering-manager.target" ];
|
||||
after = [ "peering-manager-migration.service" ];
|
||||
|
||||
preStart = ''
|
||||
${pkg}/bin/peering-manager remove_stale_contenttypes --no-input
|
||||
'';
|
||||
|
||||
environment = {
|
||||
PYTHONPATH = pkg.pythonPath;
|
||||
};
|
||||
|
||||
serviceConfig = defaultServiceConfig // {
|
||||
ExecStart = ''
|
||||
${pkg.python.pkgs.gunicorn}/bin/gunicorn peering_manager.wsgi \
|
||||
--bind ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--pythonpath ${pkg}/opt/peering-manager
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
peering-manager-rq = {
|
||||
description = "Peering Manager Request Queue Worker";
|
||||
wantedBy = [ "peering-manager.target" ];
|
||||
after = [ "peering-manager.service" ];
|
||||
|
||||
environment = {
|
||||
PYTHONPATH = pkg.pythonPath;
|
||||
};
|
||||
|
||||
serviceConfig = defaultServiceConfig // {
|
||||
ExecStart = ''
|
||||
${pkg}/bin/peering-manager rqworker high default low
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
peering-manager-housekeeping = {
|
||||
description = "Peering Manager housekeeping job";
|
||||
after = [ "peering-manager.service" ];
|
||||
|
||||
environment = {
|
||||
PYTHONPATH = pkg.pythonPath;
|
||||
};
|
||||
|
||||
serviceConfig = defaultServiceConfig // {
|
||||
Type = "oneshot";
|
||||
ExecStart = ''
|
||||
${pkg}/bin/peering-manager housekeeping
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.peering-manager-housekeeping = {
|
||||
description = "Run Peering Manager housekeeping job";
|
||||
wantedBy = [ "timers.target" ];
|
||||
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
};
|
||||
};
|
||||
|
||||
users.users.peering-manager = {
|
||||
home = "/var/lib/peering-manager";
|
||||
isSystemUser = true;
|
||||
group = "peering-manager";
|
||||
};
|
||||
users.groups.peering-manager = {};
|
||||
users.groups."${config.services.redis.servers.peering-manager.user}".members = [ "peering-manager" ];
|
||||
};
|
||||
}
|
|
@ -51,7 +51,7 @@ in
|
|||
|
||||
server = {
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
description = lib.mdDoc "The port of the Zabbix server to connect to.";
|
||||
default = 10051;
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ in
|
|||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
type = types.port;
|
||||
default =
|
||||
if cfg.database.type == "mysql" then config.services.mysql.port
|
||||
else if cfg.database.type == "pgsql" then config.services.postgresql.port
|
||||
|
|
|
@ -137,7 +137,7 @@ in
|
|||
|
||||
package = mkOption {
|
||||
default = pkgs.lighttpd;
|
||||
defaultText = "pkgs.lighttpd";
|
||||
defaultText = lib.literalExpression "pkgs.lighttpd";
|
||||
type = types.package;
|
||||
description = lib.mdDoc ''
|
||||
lighttpd package to use.
|
||||
|
|
|
@ -29,7 +29,7 @@ with lib;
|
|||
listen = mkOption {
|
||||
type = with types; listOf (submodule { options = {
|
||||
addr = mkOption { type = str; description = lib.mdDoc "IP address."; };
|
||||
port = mkOption { type = int; description = lib.mdDoc "Port number."; default = 80; };
|
||||
port = mkOption { type = port; description = lib.mdDoc "Port number."; default = 80; };
|
||||
ssl = mkOption { type = bool; description = lib.mdDoc "Enable SSL."; default = false; };
|
||||
extraParameters = mkOption { type = listOf str; description = lib.mdDoc "Extra parameters of this listen directive."; default = []; example = [ "backlog=1024" "deferred" ]; };
|
||||
}; });
|
||||
|
|
|
@ -67,11 +67,11 @@ in
|
|||
|
||||
# Taken from mint-artwork.gschema.override
|
||||
theme = mkIf (notExcluded pkgs.cinnamon.mint-themes) {
|
||||
name = mkDefault "Mint-X";
|
||||
name = mkDefault "Mint-Y-Aqua";
|
||||
package = mkDefault pkgs.cinnamon.mint-themes;
|
||||
};
|
||||
iconTheme = mkIf (notExcluded pkgs.cinnamon.mint-x-icons) {
|
||||
name = mkDefault "Mint-X-Dark";
|
||||
name = mkDefault "Mint-Y-Aqua";
|
||||
package = mkDefault pkgs.cinnamon.mint-x-icons;
|
||||
};
|
||||
cursorTheme = mkIf (notExcluded pkgs.cinnamon.mint-cursor-themes) {
|
||||
|
|
27
nixos/modules/system/activation/test.nix
Normal file
27
nixos/modules/system/activation/test.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ lib
|
||||
, nixos
|
||||
, expect
|
||||
, testers
|
||||
}:
|
||||
let
|
||||
node-forbiddenDependencies-fail = nixos ({ ... }: {
|
||||
system.forbiddenDependenciesRegex = "-dev$";
|
||||
environment.etc."dev-dependency" = {
|
||||
text = "${expect.dev}";
|
||||
};
|
||||
documentation.enable = false;
|
||||
fileSystems."/".device = "ignore-root-device";
|
||||
boot.loader.grub.enable = false;
|
||||
});
|
||||
node-forbiddenDependencies-succeed = nixos ({ ... }: {
|
||||
system.forbiddenDependenciesRegex = "-dev$";
|
||||
system.extraDependencies = [ expect.dev ];
|
||||
documentation.enable = false;
|
||||
fileSystems."/".device = "ignore-root-device";
|
||||
boot.loader.grub.enable = false;
|
||||
});
|
||||
in
|
||||
lib.recurseIntoAttrs {
|
||||
test-forbiddenDependencies-fail = testers.testBuildFailure node-forbiddenDependencies-fail.config.system.build.toplevel;
|
||||
test-forbiddenDependencies-succeed = node-forbiddenDependencies-succeed.config.system.build.toplevel;
|
||||
}
|
|
@ -77,7 +77,7 @@ let
|
|||
|
||||
${config.system.systemBuilderCommands}
|
||||
|
||||
echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies
|
||||
echo -n "$extraDependencies" > $out/extra-dependencies
|
||||
|
||||
${config.system.extraSystemBuilderCmds}
|
||||
'';
|
||||
|
@ -105,6 +105,8 @@ let
|
|||
dryActivationScript = config.system.dryActivationScript;
|
||||
nixosLabel = config.system.nixos.label;
|
||||
|
||||
inherit (config.system) extraDependencies;
|
||||
|
||||
# Needed by switch-to-configuration.
|
||||
perl = pkgs.perl.withPackages (p: with p; [ ConfigIniFiles FileSlurp ]);
|
||||
} // config.system.systemBuilderArgs);
|
||||
|
@ -223,6 +225,16 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
system.forbiddenDependenciesRegex = mkOption {
|
||||
default = "";
|
||||
example = "-dev$";
|
||||
type = types.str;
|
||||
description = lib.mdDoc ''
|
||||
A POSIX Extended Regular Expression that matches store paths that
|
||||
should not appear in the system closure, with the exception of {option}`system.extraDependencies`, which is not checked.
|
||||
'';
|
||||
};
|
||||
|
||||
system.extraSystemBuilderCmds = mkOption {
|
||||
type = types.lines;
|
||||
internal = true;
|
||||
|
@ -298,8 +310,26 @@ in
|
|||
config.system.copySystemConfiguration
|
||||
''ln -s '${import ../../../lib/from-env.nix "NIXOS_CONFIG" <nixos-config>}' \
|
||||
"$out/configuration.nix"
|
||||
'' +
|
||||
optionalString
|
||||
(config.system.forbiddenDependenciesRegex != "")
|
||||
''
|
||||
if [[ $forbiddenDependenciesRegex != "" && -n $closureInfo ]]; then
|
||||
if forbiddenPaths="$(grep -E -- "$forbiddenDependenciesRegex" $closureInfo/store-paths)"; then
|
||||
echo -e "System closure $out contains the following disallowed paths:\n$forbiddenPaths"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
'';
|
||||
|
||||
system.systemBuilderArgs = lib.optionalAttrs (config.system.forbiddenDependenciesRegex != "") {
|
||||
inherit (config.system) forbiddenDependenciesRegex;
|
||||
closureInfo = pkgs.closureInfo { rootPaths = [
|
||||
# override to avoid infinite recursion (and to allow using extraDependencies to add forbidden dependencies)
|
||||
(config.system.build.toplevel.overrideAttrs (_: { extraDependencies = []; closureInfo = null; }))
|
||||
]; };
|
||||
};
|
||||
|
||||
system.build.toplevel = system;
|
||||
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue