Merge remote-tracking branch 'channels/nixpkgs-unstable' into tbs

This commit is contained in:
Christian Kögler 2018-04-29 19:02:46 +02:00
commit 56b1a13ea9
1814 changed files with 37928 additions and 21430 deletions

View File

@ -26,3 +26,7 @@ indent_size = 4
# Match diffs, avoid to trim trailing whitespace
[*.{diff,patch}]
trim_trailing_whitespace = false
# https://github.com/NixOS/nixpkgs/pull/39336#discussion_r183387754
[.version]
insert_final_newline = false

1
.github/CODEOWNERS vendored
View File

@ -14,6 +14,7 @@
/lib @edolstra @nbp
/lib/systems @nbp @ericson2314
/lib/generators.nix @edolstra @nbp @Profpatsch
/lib/debug.nix @edolstra @nbp @Profpatsch
# Nixpkgs Internals
/default.nix @nbp

View File

@ -1 +1 @@
18.09
18.09

View File

@ -14,6 +14,8 @@ true:</para>
its <literal>meta.broken</literal> set to
<literal>true</literal>.</para></listitem>
<listitem><para>The package isn't intended to run on the given system, as none of its <literal>meta.platforms</literal> match the given system.</para></listitem>
<listitem><para>The package's <literal>meta.license</literal> is set
to a license which is considered to be unfree.</para></listitem>
@ -88,6 +90,42 @@ distributing the software.</para>
</itemizedlist>
</section>
<section xml:id="sec-allow-unsupported-system">
<title>Installing packages on unsupported systems</title>
<para>
There are also two ways to try compiling a package which has been marked as unsuported for the given system.
</para>
<itemizedlist>
<listitem><para>
For allowing the build of a broken package once, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1</programlisting>
</para></listitem>
<listitem>
<para>
For permanently allowing broken packages to be built, you may add <literal>allowUnsupportedSystem = true;</literal> to your user's configuration file, like this:
<programlisting>
{
allowUnsupportedSystem = true;
}
</programlisting>
</para>
</listitem>
</itemizedlist>
<para>
The difference between an a package being unsupported on some system and being broken is admittedly a bit fuzzy.
If a program <emphasis>ought</emphasis> to work on a certain platform, but doesn't, the platform should be included in <literal>meta.platforms</literal>, but marked as broken with e.g. <literal>meta.broken = !hostPlatform.isWindows</literal>.
Of course, this begs the question of what "ought" means exactly.
That is left to the package maintainer.
</para>
</section>
<section xml:id="sec-allow-unfree">
<title>Installing unfree packages</title>
@ -397,7 +435,7 @@ fi
</para>
</section>
<section xml:id="sec-gnu-info-setup">
<title>GNU info setup</title>

View File

@ -75,7 +75,7 @@
An example of such a tool is LLVM.
</para>
<para>
Although the existance of a "target platfom" is arguably a historical mistake, it is a common one: examples of tools that suffer from it are GCC, Binutils, GHC and Autoconf.
Although the existence of a "target platfom" is arguably a historical mistake, it is a common one: examples of tools that suffer from it are GCC, Binutils, GHC and Autoconf.
Nixpkgs tries to avoid sharing in the mistake where possible.
Still, because the concept of a target platform is so ingrained, it is best to support it as is.
</para>

View File

@ -294,6 +294,22 @@ merge:"diff3"
</section>
<section xml:id="sec-debug">
<title>Debugging Nix Expressions</title>
<para>Nix is a unityped, dynamic language, this means every value can
potentially appear anywhere. Since it is also non-strict, evaluation order
and what ultimately is evaluated might surprise you. Therefore it is important
to be able to debug nix expressions.</para>
<para>In the <literal>lib/debug.nix</literal> file you will find a number of
functions that help (pretty-)printing values while evaluation is runnnig. You
can even specify how deep these values should be printed recursively, and
transform them on the fly. Please consult the docstrings in
<literal>lib/debug.nix</literal> for usage information.</para>
</section>
<section xml:id="sec-fhs-environments">
<title>buildFHSUserEnv</title>

View File

@ -666,6 +666,56 @@ prefer one built with GHC 7.8.x in the first place. However, for users who
cannot use GHC 7.10.x at all for some reason, the approach of downgrading to an
older version might be useful.
### How to override packages in all compiler-specific package sets
In the previous section we learned how to override a package in a single
compiler-specific package set. You may have some overrides defined that you want
to use across multiple package sets. To accomplish this you could use the
technique that we learned in the previous section by repeating the overrides for
all the compiler-specific package sets. For example:
```nix
{
packageOverrides = super: let self = super.pkgs; in
{
haskell = super.haskell // {
packages = super.haskell.packages // {
ghc784 = super.haskell.packages.ghc784.override {
overrides = self: super: {
my-package = ...;
my-other-package = ...;
};
};
ghc822 = super.haskell.packages.ghc784.override {
overrides = self: super: {
my-package = ...;
my-other-package = ...;
};
};
...
};
};
};
}
```
However there's a more convenient way to override all compiler-specific package
sets at once:
```nix
{
packageOverrides = super: let self = super.pkgs; in
{
haskell = super.haskell // {
packageOverrides = self: super: {
my-package = ...;
my-other-package = ...;
};
};
};
}
```
### How to recover from GHC's infamous non-deterministic library ID bug
GHC and distributed build farms don't get along well:

View File

@ -374,7 +374,7 @@ and `CFLAGS`.
description = "A pythonic wrapper around FFTW, the FFT library, presenting a unified interface for all the supported transforms";
homepage = http://hgomersall.github.com/pyFFTW/;
license = with licenses; [ bsd2 bsd3 ];
maintainer = with maintainers; [ fridh ];
maintainers = with maintainers; [ fridh ];
};
};
}

View File

@ -36,10 +36,16 @@
<para>Here you find how to write a derivation that produces multiple outputs.</para>
<para>In nixpkgs there is a framework supporting multiple-output derivations. It tries to cover most cases by default behavior. You can find the source separated in &lt;<filename>nixpkgs/pkgs/build-support/setup-hooks/multiple-outputs.sh</filename>&gt;; it's relatively well-readable. The whole machinery is triggered by defining the <varname>outputs</varname> attribute to contain the list of desired output names (strings).</para>
<programlisting>outputs = [ "bin" "dev" "out" "doc" ];</programlisting>
<para>Often such a single line is enough. For each output an equally named environment variable is passed to the builder and contains the path in nix store for that output. By convention, the first output should contain the executable programs provided by the package as that output is used by Nix in string conversions, allowing references to binaries like <literal>${pkgs.perl}/bin/perl</literal> to always work. Typically you also want to have the main <varname>out</varname> output, as it catches any files that didn't get elsewhere.</para>
<para>Often such a single line is enough. For each output an equally named environment variable is passed to the builder and contains the path in nix store for that output. Typically you also want to have the main <varname>out</varname> output, as it catches any files that didn't get elsewhere.</para>
<note><para>There is a special handling of the <varname>debug</varname> output, described at <xref linkend="stdenv-separateDebugInfo" />.</para></note>
<section xml:id="multiple-output-file-binaries-first-convention">
<title><quote>Binaries first</quote></title>
<para>A commonly adopted convention in <literal>nixpkgs</literal> is that executables provided by the package are contained within its first output. This convention allows the dependent packages to reference the executables provided by packages in a uniform manner. For instance, provided with the knowledge that the <literal>perl</literal> package contains a <literal>perl</literal> executable it can be referenced as <literal>${pkgs.perl}/bin/perl</literal> within a Nix derivation that needs to execute a Perl script.</para>
<para>The <literal>glibc</literal> package is a deliberate single exception to the <quote>binaries first</quote> convention. The <literal>glibc</literal> has <literal>libs</literal> as its first output allowing the libraries provided by <literal>glibc</literal> to be referenced directly (e.g. <literal>${stdenv.glibc}/lib/ld-linux-x86-64.so.2</literal>). The executables provided by <literal>glibc</literal> can be accessed via its <literal>bin</literal> attribute (e.g. <literal>${stdenv.glibc.bin}/bin/ldd</literal>).</para>
<para>The reason for why <literal>glibc</literal> deviates from the convention is because referencing a library provided by <literal>glibc</literal> is a very common operation among Nix packages. For instance, third-party executables packaged by Nix are typically patched and relinked with the relevant version of <literal>glibc</literal> libraries from Nix packages (please see the documentation on <link xlink:href="https://nixos.org/patchelf.html">patchelf</link> for more details).</para>
</section>
<section xml:id="multiple-output-file-type-groups">
<title>File type groups</title>
<para>The support code currently recognizes some particular kinds of outputs and either instructs the build system of the package to put files into their desired outputs or it moves the files during the fixup phase. Each group of file types has an <varname>outputFoo</varname> variable specifying the output name where they should go. If that variable isn't defined by the derivation writer, it is guessed &ndash; a default output name is defined, falling back to other possibilities if the output isn't defined.</para>

View File

@ -23,7 +23,9 @@
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc">most
recently</link> and the <link
xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-asc">least
recently</link> updated pull-requests.</para>
recently</link> updated pull-requests.
We highly encourage looking at <link xlink:href="https://github.com/NixOS/nixpkgs/pulls?q=is%3Apr+is%3Aopen+review%3Anone+status%3Asuccess+-label%3A%222.status%3A+work-in-progress%22+no%3Aproject+no%3Aassignee+no%3Amilestone">
this list of ready to merge, unreviewed pull requests</link>.</para>
<para>When reviewing a pull request, please always be nice and polite.
Controversial changes can lead to controversial opinions, but it is important

View File

@ -1,34 +1,67 @@
/* Collection of functions useful for debugging
broken nix expressions.
* `trace`-like functions take two values, print
the first to stderr and return the second.
* `traceVal`-like functions take one argument
which both printed and returned.
* `traceSeq`-like functions fully evaluate their
traced value before printing (not just to weak
head normal form like trace does by default).
* Functions that end in `-Fn` take an additional
function as their first argument, which is applied
to the traced value before it is printed.
*/
{ lib }:
let
inherit (builtins) trace attrNamesToStr isAttrs isList isInt
isString isBool head substring attrNames;
inherit (lib) all id mapAttrsFlatten elem isFunction;
inherit (builtins) trace isAttrs isList isInt
head substring attrNames;
inherit (lib) id elem isFunction;
in
rec {
inherit (builtins) addErrorContext;
# -- TRACING --
addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v);
/* Trace msg, but only if pred is true.
traceIf = p: msg: x: if p then trace msg x else x;
Example:
traceIf true "hello" 3
trace: hello
=> 3
*/
traceIf = pred: msg: x: if pred then trace msg x else x;
traceVal = x: trace x x;
traceXMLVal = x: trace (builtins.toXML x) x;
traceXMLValMarked = str: x: trace (str + builtins.toXML x) x;
/* Trace the value and also return it.
# strict trace functions (traced structure is fully evaluated and printed)
Example:
traceValFn (v: "mystring ${v}") "foo"
trace: mystring foo
=> "foo"
*/
traceValFn = f: x: trace (f x) x;
traceVal = traceValFn id;
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first. */
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
Example:
trace { a.b.c = 3; } null
trace: { a = <CODE>; }
=> null
traceSeq { a.b.c = 3; } null
trace: { a = { b = { c = 3; }; }; }
=> null
*/
traceSeq = x: y: trace (builtins.deepSeq x x) y;
/* Like `traceSeq`, but only down to depth n.
* This is very useful because lots of `traceSeq` usages
* lead to an infinite recursion.
/* Like `traceSeq`, but only evaluate down to depth n.
This is very useful because lots of `traceSeq` usages
lead to an infinite recursion.
Example:
traceSeqN 2 { a.b.c = 3; } null
trace: { a = { b = {}; }; }
=> null
*/
traceSeqN = depth: x: y: with lib;
let snip = v: if isList v then noQuotes "[]" v
@ -43,39 +76,16 @@ rec {
in trace (generators.toPretty { allowPrettyValues = true; }
(modify depth snip x)) y;
/* `traceSeq`, but the same value is traced and returned */
traceValSeq = v: traceVal (builtins.deepSeq v v);
/* `traceValSeq` but with fixed depth */
traceValSeqN = depth: v: traceSeqN depth v v;
/* A combination of `traceVal` and `traceSeq` */
traceValSeqFn = f: v: traceVal f (builtins.deepSeq v v);
traceValSeq = traceValSeqFn id;
/* A combination of `traceVal` and `traceSeqN`. */
traceValSeqNFn = f: depth: v: traceSeqN depth (f v) v;
traceValSeqN = traceValSeqNFn id;
# this can help debug your code as well - designed to not produce thousands of lines
traceShowVal = x: trace (showVal x) x;
traceShowValMarked = str: x: trace (str + showVal x) x;
attrNamesToStr = a: lib.concatStringsSep "; " (map (x: "${x}=") (attrNames a));
showVal = x:
if isAttrs x then
if x ? outPath then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }"
else "x is attr set { ${attrNamesToStr x} }"
else if isFunction x then "x is a function"
else if x == [] then "x is an empty list"
else if isList x then "x is a list, first element is: ${showVal (head x)}"
else if x == true then "x is boolean true"
else if x == false then "x is boolean false"
else if x == null then "x is null"
else if isInt x then "x is an integer `${toString x}'"
else if isString x then "x is a string `${substring 0 50 x}...'"
else "x is probably a path `${substring 0 50 (toString x)}...'";
# trace the arguments passed to function and its result
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
# FIXME: rename this?
traceValIfNot = c: x:
if c x then true else trace (showVal x) false;
# -- TESTING --
/* Evaluate a set of tests. A test is an attribute set {expr,
expected}, denoting an expression and its expected result. The
@ -99,9 +109,68 @@ rec {
# usage: { testX = allTrue [ true ]; }
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
strict = v:
trace "Warning: strict is deprecated and will be removed in the next release"
(builtins.seq v v);
# -- DEPRECATED --
traceShowVal = x: trace (showVal x) x;
traceShowValMarked = str: x: trace (str + showVal x) x;
attrNamesToStr = a:
trace ( "Warning: `attrNamesToStr` is deprecated "
+ "and will be removed in the next release. "
+ "Please use more specific concatenation "
+ "for your uses (`lib.concat(Map)StringsSep`)." )
(lib.concatStringsSep "; " (map (x: "${x}=") (attrNames a)));
showVal = with lib;
trace ( "Warning: `showVal` is deprecated "
+ "and will be removed in the next release, "
+ "please use `traceSeqN`" )
(let
modify = v:
let pr = f: { __pretty = f; val = v; };
in if isDerivation v then pr
(drv: "<δ:${drv.name}:${concatStringsSep ","
(attrNames drv)}>")
else if [] == v then pr (const "[]")
else if isList v then pr (l: "[ ${go (head l)}, ]")
else if isAttrs v then pr
(a: "{ ${ concatStringsSep ", " (attrNames a)} }")
else v;
go = x: generators.toPretty
{ allowPrettyValues = true; }
(modify x);
in go);
traceXMLVal = x:
trace ( "Warning: `traceXMLVal` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `traceValFn builtins.toXML`." )
(trace (builtins.toXML x) x);
traceXMLValMarked = str: x:
trace ( "Warning: `traceXMLValMarked` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `traceValFn (x: str + builtins.toXML x)`." )
(trace (str + builtins.toXML x) x);
# trace the arguments passed to function and its result
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough
traceCall = n: f: a: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
traceCall2 = n: f: a: b: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
traceCall3 = n: f: a: b: c: let t = n2: x: traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
traceValIfNot = c: x:
trace ( "Warning: `traceValIfNot` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `if/then/else` and `traceValSeq 1`.")
(if c x then true else traceSeq (showVal x) false);
addErrorContextToAttrs = attrs:
trace ( "Warning: `addErrorContextToAttrs` is deprecated "
+ "and will be removed in the next release. "
+ "Please use `builtins.addErrorContext` directly." )
(lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v) attrs);
# example: (traceCallXml "myfun" id 3) will output something like
# calling myfun arg 1: 3 result: 3
@ -109,17 +178,20 @@ rec {
# note: if result doesn't evaluate you'll get no trace at all (FIXME)
# args should be printed in any case
traceCallXml = a:
if !isInt a then
trace ( "Warning: `traceCallXml` is deprecated "
+ "and will be removed in the next release. "
+ "Please complain if you use the function regularly." )
(if !isInt a then
traceCallXml 1 "calling ${a}\n"
else
let nr = a;
in (str: expr:
if isFunction expr then
(arg:
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg)
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (builtins.seq arg arg)}" (expr arg)
)
else
let r = strict expr;
let r = builtins.seq expr expr;
in trace "${str}\n result:\n${builtins.toXML r}" r
);
));
}

View File

@ -115,11 +115,12 @@ let
unknownModule mkOption;
inherit (types) isType setType defaultTypeMerge defaultFunctor
isOptionType mkOptionType;
inherit (debug) addErrorContextToAttrs traceIf traceVal
inherit (debug) addErrorContextToAttrs traceIf traceVal traceValFn
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
traceValSeqN traceShowVal traceShowValMarked
showVal traceCall traceCall2 traceCall3 traceValIfNot runTests
testAllTrue strict traceCallXml attrNamesToStr;
traceValSeqFn traceValSeqN traceValSeqNFn traceShowVal
traceShowValMarked showVal traceCall traceCall2 traceCall3
traceValIfNot runTests testAllTrue traceCallXml
attrNamesToStr;
inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
defaultOverridableDelayableArgs composedArgsAndFun
maybeAttrNullable maybeAttr ifEnable checkFlag getValue

View File

@ -143,18 +143,13 @@ rec {
(This means fn is type Val -> String.) */
allowPrettyValues ? false
}@args: v: with builtins;
if isInt v then toString v
let isPath = v: typeOf v == "path";
in if isInt v then toString v
else if isString v then ''"${libStr.escape [''"''] v}"''
else if true == v then "true"
else if false == v then "false"
else if null == v then "null"
else if isFunction v then
let fna = lib.functionArgs v;
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then "(${name})" else name)
fna);
in if fna == {} then "<λ>"
else "<λ:{${showFnas}}>"
else if null == v then "null"
else if isPath v then toString v
else if isList v then "[ "
+ libStr.concatMapStringsSep " " (toPretty args) v
+ " ]"
@ -163,12 +158,21 @@ rec {
if attrNames v == [ "__pretty" "val" ] && allowPrettyValues
then v.__pretty v.val
# TODO: there is probably a better representation?
else if v ? type && v.type == "derivation" then "<δ>"
else if v ? type && v.type == "derivation" then
"<δ:${v.name}>"
# "<δ:${concatStringsSep "," (builtins.attrNames v)}>"
else "{ "
+ libStr.concatStringsSep " " (libAttr.mapAttrsToList
(name: value:
"${toPretty args name} = ${toPretty args value};") v)
+ " }"
else abort "generators.toPretty: should never happen (v = ${v})";
else if isFunction v then
let fna = lib.functionArgs v;
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then "(${name})" else name)
fna);
in if fna == {} then "<λ>"
else "<λ:{${showFnas}}>"
else abort "toPretty: should never happen (v = ${v})";
}

View File

@ -159,7 +159,7 @@ rec {
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
value = addErrorContext (context name)
value = builtins.addErrorContext (context name)
(args.${name} or config._module.args.${name});
}) requiredArgs);
@ -309,7 +309,7 @@ rec {
res.mergedValue;
in opt //
{ value = addErrorContext "while evaluating the option `${showOption loc}':" value;
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
definitions = map (def: def.value) res.defsFinal;
files = map (def: def.file) res.defsFinal;
inherit (res) isDefined;

View File

@ -44,6 +44,8 @@ rec {
};
# Misc boolean options
useAndroidPrebuilt = false;
useiOSPrebuilt = false;
isiPhoneSimulator = false;
} // mapAttrs (n: v: v final.parsed) inspect.predicates
// args;
in assert final.useAndroidPrebuilt -> final.isAndroid;

View File

@ -26,7 +26,7 @@ in rec {
none = [];
arm = filterDoubles predicates.isArm;
arm = filterDoubles predicates.isAarch32;
aarch64 = filterDoubles predicates.isAarch64;
x86 = filterDoubles predicates.isx86;
i686 = filterDoubles predicates.isi686;

View File

@ -7,7 +7,7 @@ in rec {
all = [ {} ]; # `{}` matches anything
none = [];
arm = [ patterns.isArm ];
arm = [ patterns.isAarch32 ];
aarch64 = [ patterns.isAarch64 ];
x86 = [ patterns.isx86 ];
i686 = [ patterns.isi686 ];

View File

@ -9,8 +9,8 @@ rec {
isx86_64 = { cpu = cpuTypes.x86_64; };
isPowerPC = { cpu = cpuTypes.powerpc; };
isx86 = { cpu = { family = "x86"; }; };
isArm = { cpu = { family = "arm"; }; };
isAarch64 = { cpu = { family = "aarch64"; }; };
isAarch32 = { cpu = { family = "arm"; bits = 32; }; };
isAarch64 = { cpu = { family = "arm"; bits = 64; }; };
isMips = { cpu = { family = "mips"; }; };
isRiscV = { cpu = { family = "riscv"; }; };
isWasm = { cpu = { family = "wasm"; }; };
@ -41,6 +41,9 @@ rec {
isEfi = map (family: { cpu.family = family; })
[ "x86" "arm" "aarch64" ];
# Deprecated
isArm = isAarch32;
};
matchAnyAttrs = patterns:

View File

@ -34,7 +34,7 @@ rec {
################################################################################
types.openSignifiantByte = mkOptionType {
types.openSignificantByte = mkOptionType {
name = "significant-byte";
description = "Endianness";
merge = mergeOneOption;
@ -42,7 +42,7 @@ rec {
types.significantByte = enum (attrValues significantBytes);
significantBytes = setTypes types.openSignifiantByte {
significantBytes = setTypes types.openSignificantByte {
bigEndian = {};
littleEndian = {};
};
@ -72,7 +72,7 @@ rec {
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; };
armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "aarch64"; };
aarch64 = { bits = 64; significantByte = littleEndian; family = "arm"; };
i686 = { bits = 32; significantByte = littleEndian; family = "x86"; };
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; };
mips = { bits = 32; significantByte = bigEndian; family = "mips"; };
@ -201,7 +201,7 @@ rec {
################################################################################
types.system = mkOptionType {
types.parsedPlatform = mkOptionType {
name = "system";
description = "fully parsed representation of llvm- or nix-style platform tuple";
merge = mergeOneOption;
@ -215,7 +215,7 @@ rec {
isSystem = isType "system";
mkSystem = components:
assert types.system.check components;
assert types.parsedPlatform.check components;
setType "system" components;
mkSkeletonFromList = l: {

View File

@ -317,7 +317,8 @@ runTests {
expr = mapAttrs (const (generators.toPretty {})) rec {
int = 42;
bool = true;
string = "fnord";
string = ''fno"rd'';
path = /. + "/foo"; # toPath returns a string
null_ = null;
function = x: x;
functionArgs = { arg ? 4, foo }: arg;
@ -328,13 +329,14 @@ runTests {
expected = rec {
int = "42";
bool = "true";
string = "\"fnord\"";
string = ''"fno\"rd"'';
path = "/foo";
null_ = "null";
function = "<λ>";
functionArgs = "<λ:{(arg),foo}>";
list = "[ 3 4 ${function} [ false ] ]";
attrs = "{ \"foo\" = null; \"foo bar\" = \"baz\"; }";
drv = "<δ>";
drv = "<δ:test>";
};
};

View File

@ -28,6 +28,11 @@
github = "AndersonTorres";
name = "Anderson Torres";
};
Anton-Latukha = {
email = "anton.latuka+nixpkgs@gmail.com";
github = "Anton-Latukha";
name = "Anton Latukha";
};
Baughn = {
email = "sveina@gmail.com";
github = "Baughn";
@ -305,6 +310,16 @@
github = "akru";
name = "Alexander Krupenkin ";
};
alexchapman = {
name = "Alex Chapman";
email = "alex@farfromthere.net";
github = "AJChapman";
};
alexfmpe = {
email = "alexandre.fmp.esteves@gmail.com";
github = "alexfmpe";
name = "Alexandre Esteves";
};
alexvorobiev = {
email = "alexander.vorobiev@gmail.com";
github = "alexvorobiev";
@ -582,6 +597,11 @@
github = "bergey";
name = "Daniel Bergey";
};
bfortz = {
email = "bernard.fortz@gmail.com";
github = "bfortz";
name = "Bernard Fortz";
};
bgamari = {
email = "ben@smart-cactus.org";
github = "bgamari";
@ -700,6 +720,11 @@
github = "canndrew";
name = "Andrew Cann";
};
carlosdagos = {
email = "m@cdagostino.io";
github = "carlosdagos";
name = "Carlos D'Agostino";
};
carlsverre = {
email = "accounts@carlsverre.com";
github = "carlsverre";
@ -1216,7 +1241,7 @@
name = "Mabry Cervin";
};
eqyiel = {
email = "r@rkm.id.au";
email = "ruben@maher.fyi";
github = "eqyiel";
name = "Ruben Maher";
};
@ -1701,6 +1726,11 @@
github = "jbedo";
name = "Justin Bedő";
};
jbgi = {
email = "jb@giraudeau.info";
github = "jbgi";
name = "Jean-Baptiste Giraudeau";
};
jcumming = {
email = "jack@mudshark.org";
name = "Jack Cummings";
@ -1716,7 +1746,7 @@
name = "Jeffrey David Johnson";
};
jensbin = {
email = "jensbin@protonmail.com";
email = "jensbin+git@pm.me";
github = "jensbin";
name = "Jens Binkert";
};
@ -1966,6 +1996,11 @@
github = "kragniz";
name = "Louis Taylor";
};
krav = {
email = "kristoffer@microdisko.no";
github = "krav";
name = "Kristoffer Thømt Ravneberg";
};
kristoff3r = {
email = "k.soeholm@gmail.com";
github = "kristoff3r";
@ -2491,6 +2526,11 @@
github = "fstamour";
name = "Francis St-Amour";
};
mrkkrp = {
email = "markkarpov92@gmail.com";
github = "mrkkrp";
name = "Mark Karpov";
};
mrVanDalo = {
email = "contact@ingolf-wagner.de";
github = "mrVanDalo";
@ -2645,6 +2685,11 @@
github = "nmattia";
name = "Nicolas Mattia";
};
nocent = {
email = "nocent@protonmail.ch";
github = "nocent";
name = "nocent";
};
nocoolnametom = {
email = "nocoolnametom@gmail.com";
github = "nocoolnametom";
@ -3406,6 +3451,11 @@
github = "grwlf";
name = "Sergey Mironov";
};
sna = {
email = "abouzahra.9@wright.edu";
github = "s-na";
name = "S. Nordin Abouzahra";
};
snyh = {
email = "snyh@snyh.org";
github = "snyh";
@ -3451,6 +3501,11 @@
github = "spwhitt";
name = "Spencer Whitt";
};
srghma = {
email = "srghma@gmail.com";
github = "srghma";
name = "Sergei Khoma";
};
srhb = {
email = "sbrofeldt@gmail.com";
github = "srhb";
@ -3760,6 +3815,11 @@
github = "twey";
name = "James Twey Kay";
};
typetetris = {
email = "ericwolf42@mail.com";
github = "typetetris";
name = "Eric Wolf";
};
unode = {
email = "alves.rjc@gmail.com";
github = "unode";
@ -3966,6 +4026,11 @@
github = "womfoo";
name = "Kranium Gikos Mendoza";
};
worldofpeace = {
email = "worldofpeace@users.noreply.github.com";
github = "worldofpeace";
name = "Worldofpeace";
};
wscott = {
email = "wsc9tt@gmail.com";
github = "wscott";
@ -3984,7 +4049,7 @@
xeji = {
email = "xeji@cat3.de";
github = "xeji";
name = "xeji";
name = "Uli Baum";
};
xnaveira = {
email = "xnaveira@gmail.com";
@ -4130,9 +4195,4 @@
github = "zzamboni";
name = "Diego Zamboni";
};
srghma = {
email = "srghma@gmail.com";
github = "srghma";
name = "Sergei Khoma";
};
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python -p pythonFull pythonPackages.requests pythonPackages.pyquery pythonPackages.click
#!nix-shell -i python3 -p 'python3.withPackages(ps: with ps; [ requests pyquery click ])'
# To use, just execute this script with --help to display help.
@ -16,7 +16,7 @@ maintainers_json = subprocess.check_output([
'nix-instantiate', '-E', 'import ./maintainers/maintainer-list.nix {}', '--eval', '--json'
])
maintainers = json.loads(maintainers_json)
MAINTAINERS = {v: k for k, v in maintainers.iteritems()}
MAINTAINERS = {v: k for k, v in maintainers.items()}
def get_response_text(url):
@ -45,6 +45,17 @@ def get_maintainers(attr_name):
except:
return []
def print_build(table_row):
a = pq(table_row)('a')[1]
print("- [ ] [{}]({})".format(a.text, a.get('href')), flush=True)
maintainers = get_maintainers(a.text)
if maintainers:
print(" - maintainers: {}".format(", ".join(map(lambda u: '@' + u, maintainers))))
# TODO: print last three persons that touched this file
# TODO: pinpoint the diff that broke this build, or maybe it's transient or maybe it never worked?
sys.stdout.flush()
@click.command()
@click.option(
@ -73,23 +84,17 @@ def cli(jobset):
# TODO: aborted evaluations
# TODO: dependency failed without propagated builds
print('\nFailures:')
for tr in d('img[alt="Failed"]').parents('tr'):
a = pq(tr)('a')[1]
print("- [ ] [{}]({})".format(a.text, a.get('href')))
print_build(tr)
sys.stdout.flush()
maintainers = get_maintainers(a.text)
if maintainers:
print(" - maintainers: {}".format(", ".join(map(lambda u: '@' + u, maintainers))))
# TODO: print last three persons that touched this file
# TODO: pinpoint the diff that broke this build, or maybe it's transient or maybe it never worked?
sys.stdout.flush()
print('\nDependency failures:')
for tr in d('img[alt="Dependency failed"]').parents('tr'):
print_build(tr)
if __name__ == "__main__":
try:
cli()
except:
except Exception as e:
import pdb;pdb.post_mortem()

View File

@ -53,7 +53,7 @@ manual</link> for the rest.</para>
</row>
<row>
<entry><literal>{ x = 1; y = 2; }</literal></entry>
<entry>An set with attributes names <literal>x</literal> and <literal>y</literal></entry>
<entry>A set with attributes named <literal>x</literal> and <literal>y</literal></entry>
</row>
<row>
<entry><literal>{ foo.bar = 1; }</literal></entry>

View File

@ -0,0 +1,59 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-importing-modules">
<title>Importing Modules</title>
<para>
Sometimes NixOS modules need to be used in configuration but exist
outside of Nixpkgs. These modules can be imported:
</para>
<programlisting>
{ config, lib, pkgs, ... }:
{
imports =
[ # Use a locally-available module definition in
# ./example-module/default.nix
./example-module
];
services.exampleModule.enable = true;
}
</programlisting>
<para>
The environment variable <literal>NIXOS_EXTRA_MODULE_PATH</literal> is
an absolute path to a NixOS module that is included alongside the
Nixpkgs NixOS modules. Like any NixOS module, this module can import
additional modules:
</para>
<programlisting>
# ./module-list/default.nix
[
./example-module1
./example-module2
]
</programlisting>
<programlisting>
# ./extra-module/default.nix
{ imports = import ./module-list.nix; }
</programlisting>
<programlisting>
# NIXOS_EXTRA_MODULE_PATH=/absolute/path/to/extra-module
{ config, lib, pkgs, ... }:
{
# No `imports` needed
services.exampleModule1.enable = true;
}
</programlisting>
</section>

View File

@ -180,6 +180,7 @@ in {
<xi:include href="option-def.xml" />
<xi:include href="assertions.xml" />
<xi:include href="meta-attributes.xml" />
<xi:include href="importing-modules.xml" />
<xi:include href="replace-modules.xml" />
</chapter>

View File

@ -51,7 +51,7 @@ ISO, copy its contents verbatim to your drive, then either:
<listitem>
<para>If you want to load the contents of the ISO to ram after bootin
(So you can remove the stick after bootup) you can append the parameter
<literal>copytoram</literal>to the <literal>options</literal> field.</para>
<literal>copytoram</literal> to the <literal>options</literal> field.</para>
</listitem>
</itemizedlist>
</para>

View File

@ -115,23 +115,17 @@ for a UEFI installation is by and large the same as a BIOS installation. The dif
<varlistentry><term>UEFI systems</term>
<listitem><para>For creating boot partitions:
<command>mkfs.fat</command>. Again its recommended to assign a
label to the boot partition: <option>-L
label to the boot partition: <option>-n
<replaceable>label</replaceable></option>. For example:
<screen>
# mkfs.fat -F 32 -L boot /dev/sda3</screen>
# mkfs.fat -F 32 -n boot /dev/sda3</screen>
</para></listitem></varlistentry></variablelist></listitem>
<listitem><para>For creating LVM volumes, the LVM commands, e.g.,
<screen>
# pvcreate /dev/sda1 /dev/sdb1
# vgcreate MyVolGroup /dev/sda1 /dev/sdb1
# lvcreate --size 2G --name bigdisk MyVolGroup
# lvcreate --size 1G --name smalldisk MyVolGroup</screen>
</para></listitem>
<command>pvcreate</command>, <command>vgcreate</command>, and
<command>lvcreate</command>.</para></listitem>
<listitem><para>For creating software RAID devices, use
<command>mdadm</command>.</para></listitem>
@ -155,6 +149,7 @@ for a UEFI installation is by and large the same as a BIOS installation. The dif
<listitem><para>Mount the boot file system on <filename>/mnt/boot</filename>, e.g.
<screen>
# mkdir -p /mnt/boot
# mount /dev/disk/by-label/boot /mnt/boot
</screen>
@ -366,8 +361,9 @@ drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config"
# mkfs.ext4 -L nixos /dev/sda1
# mkswap -L swap /dev/sda2
# swapon /dev/sda2
# mkfs.fat -F 32 -L boot /dev/sda3 # <lineannotation>(for UEFI systems only)</lineannotation>
# mkfs.fat -F 32 -n boot /dev/sda3 # <lineannotation>(for UEFI systems only)</lineannotation>
# mount /dev/disk/by-label/nixos /mnt
# mkdir -p /mnt/boot # <lineannotation>(for UEFI systems only)</lineannotation>
# mount /dev/disk/by-label/boot /mnt/boot # <lineannotation>(for UEFI systems only)</lineannotation>
# nixos-generate-config --root /mnt
# nano /mnt/etc/nixos/configuration.nix

View File

@ -40,7 +40,7 @@ points to the generated virtual network.
test1 = {pkgs, config, ...}:
{
services.openssh.enable = true;
nixpkgs.system = "i686-linux";
nixpkgs.localSystem.system = "i686-linux";
deployment.targetHost = "test1.example.net";
# Other NixOS options
@ -51,7 +51,7 @@ points to the generated virtual network.
services.openssh.enable = true;
services.httpd.enable = true;
environment.systemPackages = [ pkgs.lynx ];
nixpkgs.system = "x86_64-linux";
nixpkgs.localSystem.system = "x86_64-linux";
deployment.targetHost = "test2.example.net";
# Other NixOS options
@ -66,7 +66,7 @@ In each NixOS configuration, two attributes have a special meaning.
The <varname>deployment.targetHost</varname> specifies the address
(domain name or IP address)
of the system which is used by <command>ssh</command> to perform
remote deployment operations. The <varname>nixpkgs.system</varname>
remote deployment operations. The <varname>nixpkgs.localSystem.system</varname>
attribute can be used to specify an architecture for the target machine,
such as <varname>i686-linux</varname> which builds a 32-bit NixOS
configuration. Omitting this property will build the configuration

View File

@ -56,6 +56,11 @@ has the following highlights: </para>
following incompatible changes:</para>
<itemizedlist>
<listitem>
<para>
<literal>lib.strict</literal> is removed. Use <literal>builtins.seq</literal> instead.
</para>
</listitem>
<listitem>
<para>
The <literal>clementine</literal> package points now to the free derivation.
@ -77,6 +82,46 @@ following incompatible changes:</para>
<itemizedlist>
<listitem>
<para>
<literal>lib.attrNamesToStr</literal> has been deprecated. Use
more specific concatenation (<literal>lib.concat(Map)StringsSep</literal>)
instead.
</para>
</listitem>
<listitem>
<para>
<literal>lib.addErrorContextToAttrs</literal> has been deprecated. Use
<literal>builtins.addErrorContext</literal> directly.
</para>
</listitem>
<listitem>
<para>
<literal>lib.showVal</literal> has been deprecated. Use
<literal>lib.traceSeqN</literal> instead.
</para>
</listitem>
<listitem>
<para>
<literal>lib.traceXMLVal</literal> has been deprecated. Use
<literal>lib.traceValFn builtins.toXml</literal> instead.
</para>
</listitem>
<listitem>
<para>
<literal>lib.traceXMLValMarked</literal> has been deprecated. Use
<literal>lib.traceValFn (x: str + builtins.toXML x)</literal> instead.
</para>
</listitem>
<listitem>
<para>
<literal>lib.traceValIfNot</literal> has been deprecated. Use
<literal>if/then/else</literal> and <literal>lib.traceValSeq</literal>
instead.
</para>
</listitem>
<listitem>
<para>
<literal>lib.traceCallXml</literal> has been deprecated. Please complain
if you use the function regularly.
</para>
</listitem>
</itemizedlist>

View File

@ -26,7 +26,7 @@
, lib ? import ../../lib
}:
let extraArgs_ = extraArgs; pkgs_ = pkgs; system_ = system;
let extraArgs_ = extraArgs; pkgs_ = pkgs;
extraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import (builtins.toPath e))];
in
@ -36,7 +36,7 @@ let
_file = ./eval-config.nix;
key = _file;
config = {
nixpkgs.system = lib.mkDefault system_;
nixpkgs.localSystem = lib.mkDefault { inherit system; };
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
};
};

View File

@ -9,7 +9,7 @@
];
qemuSerialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
else if pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64 then "ttyAMA0"
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
qemuBinary = qemuPkg: {

View File

@ -612,7 +612,7 @@ sub waitForX {
my ($self, $regexp) = @_;
$self->nest("waiting for the X11 server", sub {
retry sub {
my ($status, $out) = $self->execute("journalctl -b SYSLOG_IDENTIFIER=systemd | grep 'session opened'");
my ($status, $out) = $self->execute("journalctl -b SYSLOG_IDENTIFIER=systemd | grep 'Reached target Current graphical'");
return 0 if $status != 0;
($status, $out) = $self->execute("[ -e /tmp/.X11-unix/X0 ]");
return 1 if $status == 0;

View File

@ -111,6 +111,8 @@ in rec {
ocrProg = tesseract_4.override { enableLanguages = [ "eng" ]; };
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
# Generate onvenience wrappers for running the test driver
# interactively with the specified network, and for starting the
# VMs from the command line.
@ -128,7 +130,7 @@ in rec {
wrapProgram $out/bin/nixos-test-driver \
--add-flags "''${vms[*]}" \
${lib.optionalString enableOCR
"--prefix PATH : '${ocrProg}/bin:${imagemagick}/bin'"} \
"--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
--run "export testScript=\"\$(cat $out/test-script)\"" \
--set VLANS '${toString vlans}'
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms

View File

@ -26,11 +26,11 @@ with lib;
nano zile
texinfo # for the stand-alone Info reader
]
++ stdenv.lib.optional (!stdenv.isArm) grub2;
++ stdenv.lib.optional (!stdenv.isAarch32) grub2;
# GNU GRUB, where available.
boot.loader.grub.enable = !pkgs.stdenv.isArm;
boot.loader.grub.enable = !pkgs.stdenv.isAarch32;
boot.loader.grub.version = 2;
# GNU lsh.

View File

@ -214,6 +214,8 @@ in {
(mkIf cfg.enable {
environment.systemPackages = [ overriddenPackage ];
sound.enable = true;
environment.etc = [
{ target = "asound.conf";
source = alsaConf; }

View File

@ -92,7 +92,7 @@ let
group = mkOption {
type = types.str;
apply = x: assert (builtins.stringLength x < 17 || abort "Group name '${x}' is longer than 16 characters which is not allowed!"); x;
apply = x: assert (builtins.stringLength x < 32 || abort "Group name '${x}' is longer than 31 characters which is not allowed!"); x;
default = "nogroup";
description = "The user's primary group.";
};

View File

@ -25,16 +25,16 @@ in
type = types.bool;
description = ''
Enable in-memory compressed swap space provided by the zram kernel
module. It is recommended to enable only for kernel 3.14 or higher.
module.
See https://www.kernel.org/doc/Documentation/blockdev/zram.txt
'';
};
numDevices = mkOption {
default = 4;
default = 1;
type = types.int;
description = ''
Number of zram swap devices to create. It should be equal to the
number of CPU cores your system has.
Number of zram swap devices to create.
'';
};

View File

@ -14,7 +14,6 @@ let
name = "mesa-drivers+txc-${p.mesa_drivers.version}";
paths =
[ p.mesa_drivers
p.mesa_drivers.out # mainly for libGL
(if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc)
];
};
@ -33,89 +32,92 @@ in
{
options = {
hardware.opengl.enable = mkOption {
description = ''
Whether to enable OpenGL drivers. This is needed to enable
OpenGL support in X11 systems, as well as for Wayland compositors
like sway, way-cooler and Weston. It is enabled by default
by the corresponding modules, so you do not usually have to
set it yourself, only if there is no module for your wayland
compositor of choice. See services.xserver.enable,
programs.sway.enable, and programs.way-cooler.enable.
'';
type = types.bool;
default = false;
};
hardware.opengl.driSupport = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable accelerated OpenGL rendering through the
Direct Rendering Interface (DRI).
'';
};
hardware.opengl = {
enable = mkOption {
description = ''
Whether to enable OpenGL drivers. This is needed to enable
OpenGL support in X11 systems, as well as for Wayland compositors
like sway, way-cooler and Weston. It is enabled by default
by the corresponding modules, so you do not usually have to
set it yourself, only if there is no module for your wayland
compositor of choice. See services.xserver.enable,
programs.sway.enable, and programs.way-cooler.enable.
'';
type = types.bool;
default = false;
};
hardware.opengl.driSupport32Bit = mkOption {
type = types.bool;
default = false;
description = ''
On 64-bit systems, whether to support Direct Rendering for
32-bit applications (such as Wine). This is currently only
supported for the <literal>nvidia</literal> and
<literal>ati_unfree</literal> drivers, as well as
<literal>Mesa</literal>.
'';
};
driSupport = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable accelerated OpenGL rendering through the
Direct Rendering Interface (DRI).
'';
};
hardware.opengl.s3tcSupport = mkOption {
type = types.bool;
default = false;
description = ''
Make S3TC(S3 Texture Compression) via libtxc_dxtn available
to OpenGL drivers instead of the patent-free S2TC replacement.
driSupport32Bit = mkOption {
type = types.bool;
default = false;
description = ''
On 64-bit systems, whether to support Direct Rendering for
32-bit applications (such as Wine). This is currently only
supported for the <literal>nvidia</literal> and
<literal>ati_unfree</literal> drivers, as well as
<literal>Mesa</literal>.
'';
};
Using this library may require a patent license depending on your location.
'';
};
s3tcSupport = mkOption {
type = types.bool;
default = false;
description = ''
Make S3TC(S3 Texture Compression) via libtxc_dxtn available
to OpenGL drivers instead of the patent-free S2TC replacement.
hardware.opengl.package = mkOption {
type = types.package;
internal = true;
description = ''
The package that provides the OpenGL implementation.
'';
};
Using this library may require a patent license depending on your location.
'';
};
hardware.opengl.package32 = mkOption {
type = types.package;
internal = true;
description = ''
The package that provides the 32-bit OpenGL implementation on
64-bit systems. Used when <option>driSupport32Bit</option> is
set.
'';
};
package = mkOption {
type = types.package;
internal = true;
description = ''
The package that provides the OpenGL implementation.
'';
};
hardware.opengl.extraPackages = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample "with pkgs; [ vaapiIntel libvdpau-va-gl vaapiVdpau intel-ocl ]";
description = ''
Additional packages to add to OpenGL drivers. This can be used
to add OpenCL drivers, VA-API/VDPAU drivers etc.
'';
};
package32 = mkOption {
type = types.package;
internal = true;
description = ''
The package that provides the 32-bit OpenGL implementation on
64-bit systems. Used when <option>driSupport32Bit</option> is
set.
'';
};
hardware.opengl.extraPackages32 = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample "with pkgs.pkgsi686Linux; [ vaapiIntel libvdpau-va-gl vaapiVdpau ]";
description = ''
Additional packages to add to 32-bit OpenGL drivers on
64-bit systems. Used when <option>driSupport32Bit</option> is
set. This can be used to add OpenCL drivers, VA-API/VDPAU drivers etc.
'';
extraPackages = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample "with pkgs; [ vaapiIntel libvdpau-va-gl vaapiVdpau intel-ocl ]";
description = ''
Additional packages to add to OpenGL drivers. This can be used
to add OpenCL drivers, VA-API/VDPAU drivers etc.
'';
};
extraPackages32 = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample "with pkgs.pkgsi686Linux; [ vaapiIntel libvdpau-va-gl vaapiVdpau ]";
description = ''
Additional packages to add to 32-bit OpenGL drivers on
64-bit systems. Used when <option>driSupport32Bit</option> is
set. This can be used to add OpenCL drivers, VA-API/VDPAU drivers etc.
'';
};
};
};

View File

@ -25,13 +25,6 @@ let
nvidia_x11 = nvidiaForKernel config.boot.kernelPackages;
nvidia_libs32 = (nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; };
nvidiaPackage = nvidia: pkgs:
if !nvidia.useGLVND then nvidia.out
else pkgs.buildEnv {
name = "nvidia-libs";
paths = [ pkgs.libglvnd nvidia.out ];
};
enabled = nvidia_x11 != null;
in
@ -57,8 +50,8 @@ in
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
};
hardware.opengl.package = nvidiaPackage nvidia_x11 pkgs;
hardware.opengl.package32 = nvidiaPackage nvidia_libs32 pkgs_i686;
hardware.opengl.package = nvidia_x11.out;
hardware.opengl.package32 = nvidia_libs32.out;
environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
++ lib.filter (p: p != null) [ nvidia_x11.persistenced ];

View File

@ -21,7 +21,9 @@ let
if [ ! -e $out/nixos/nixpkgs ]; then
ln -s . $out/nixos/nixpkgs
fi
echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision
'';
in

View File

@ -59,7 +59,7 @@ let
INITRD /boot/${config.system.boot.loader.initrdFile}
# A variant to boot with verbose logging to the console
LABEL boot-nomodeset
LABEL boot-debug
MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
LINUX /boot/${config.system.boot.loader.kernelFile}
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
@ -73,7 +73,8 @@ let
APPEND ${toString config.boot.loader.grub.memtest86.params}
'';
isolinuxCfg = baseIsolinuxCfg + (optionalString config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
isolinuxCfg = concatStringsSep "\n"
([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
# The EFI boot image.
efiDir = pkgs.runCommand "efi-directory" {} ''

View File

@ -1,6 +1,6 @@
{
x86_64-linux = "/nix/store/6p2gambjac7xdkd2a7w1dsxdk1q5cq4d-nix-2.0";
i686-linux = "/nix/store/zznnaijjk3nwx0cmpczxsvngmqzhl7r4-nix-2.0";
aarch64-linux = "/nix/store/ci96w9kxfkmlc7x2vwqiz4da0r6abxnq-nix-2.0";
x86_64-darwin = "/nix/store/xmi4fylvx4qc79ji9v5q3zfy9vfdy4sv-nix-2.0";
x86_64-linux = "/nix/store/2gk7rk2sx2dkmsjr59gignrfdmya8f6s-nix-2.0.1";
i686-linux = "/nix/store/5160glkphiv13qggnivyidg8r0491pbl-nix-2.0.1";
aarch64-linux = "/nix/store/jk29zz3ns9vdkkclcyzzkpzp8dhv1x3i-nix-2.0.1";
x86_64-darwin = "/nix/store/4a9czmrpd4hf3r80zcmga2c2lm3hbbvv-nix-2.0.1";
}

View File

@ -51,8 +51,9 @@ if [[ ! -e $mountPoint/etc/NIXOS ]]; then
exit 126
fi
mkdir -m 0755 -p "$mountPoint/dev"
mkdir -m 0755 -p "$mountPoint/dev" "$mountPoint/sys"
mount --rbind /dev "$mountPoint/dev"
mount --rbind /sys "$mountPoint/sys"
# Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
LOCALE_ARCHIVE=$system/sw/lib/locale/locale-archive chroot "$mountPoint" "$system/activate" >&2 || true

View File

@ -577,15 +577,14 @@ $bootLoaderConfig
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# List packages installed in system profile. To search by name, run:
# \$ nix-env -qaP | grep wget
# List packages installed in system profile. To search, run:
# \$ nix search wget
# environment.systemPackages = with pkgs; [
# wget vim
# ];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.bash.enableCompletion = true;
# programs.mtr.enable = true;
# programs.gnupg.agent = { enable = true; enableSSHSupport = true; };

View File

@ -16,7 +16,10 @@ let cfg = config.documentation; in
description = ''
Whether to install documentation of packages from
<option>environment.systemPackages</option> into the generated system path.
See "Multiple-output packages" chapter in the nixpkgs manual for more info.
'';
# which is at ../../../doc/multiple-output.xml
};
man.enable = mkOption {
@ -28,6 +31,15 @@ let cfg = config.documentation; in
'';
};
info.enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to install info pages and the <command>info</command> command.
This also includes "info" outputs.
'';
};
doc.enable = mkOption {
type = types.bool;
default = true;
@ -38,12 +50,19 @@ let cfg = config.documentation; in
'';
};
info.enable = mkOption {
dev.enable = mkOption {
type = types.bool;
default = true;
default = false;
description = ''
Whether to install info pages and the <command>info</command> command.
This also includes "info" outputs.
Whether to install documentation targeted at developers.
<itemizedlist>
<listitem><para>This includes man pages targeted at developers if <option>man.enable</option> is
set (this also includes "devman" outputs).</para></listitem>
<listitem><para>This includes info pages targeted at developers if <option>info.enable</option>
is set (this also includes "devinfo" outputs).</para></listitem>
<listitem><para>This includes other pages targeted at developers if <option>doc.enable</option>
is set (this also includes "devdoc" outputs).</para></listitem>
</itemizedlist>
'';
};
@ -56,20 +75,20 @@ let cfg = config.documentation; in
(mkIf cfg.man.enable {
environment.systemPackages = [ pkgs.man-db ];
environment.pathsToLink = [ "/share/man" ];
environment.extraOutputsToInstall = [ "man" ];
environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable [ "devman" ];
})
(mkIf cfg.info.enable {
environment.systemPackages = [ pkgs.texinfoInteractive ];
environment.pathsToLink = [ "/share/info" ];
environment.extraOutputsToInstall = [ "info" ] ++ optional cfg.dev.enable [ "devinfo" ];
})
(mkIf cfg.doc.enable {
# TODO(@oxij): put it here and remove from profiles?
# environment.systemPackages = [ pkgs.w3m ]; # w3m-nox?
environment.pathsToLink = [ "/share/doc" ];
environment.extraOutputsToInstall = [ "doc" ];
})
(mkIf cfg.info.enable {
environment.systemPackages = [ pkgs.texinfoInteractive ];
environment.pathsToLink = [ "/share/info" ];
environment.extraOutputsToInstall = [ "info" ];
environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable [ "devdoc" ];
})
]);

View File

@ -56,7 +56,7 @@
#dialout = 27; # unused
polkituser = 28;
#utmp = 29; # unused
ddclient = 30;
# ddclient = 30; # converted to DynamicUser = true
davfs2 = 31;
#disnix = 33; # unused
osgi = 34;
@ -344,7 +344,7 @@
dialout = 27;
#polkituser = 28; # currently unused, polkitd doesn't need a group
utmp = 29;
ddclient = 30;
# ddclient = 30; # converted to DynamicUser = true
davfs2 = 31;
disnix = 33;
osgi = 34;

View File

@ -97,7 +97,7 @@ in {
Whether not to index bind mounts
'';
};
};
config = mkIf cfg.enable {
@ -133,13 +133,26 @@ in {
systemd.services.update-locatedb =
{ description = "Update Locate Database";
path = mkIf (!isMLocate) [ pkgs.su ];
# mlocate's updatedb takes flags via a configuration file or
# on the command line, but not by environment variable.
script =
if isMLocate
then let toFlags = x: optional (cfg.${x} != [])
"--${lib.toLower x} '${concatStringsSep " " cfg.${x}}'";
args = concatLists (map toFlags ["pruneFS" "pruneNames" "prunePaths"]);
in ''
exec ${cfg.locate}/bin/updatedb \
--output ${toString cfg.output} ${concatStringsSep " " args} \
--prune-bind-mounts ${if cfg.pruneBindMounts then "yes" else "no"} \
${concatStringsSep " " cfg.extraFlags}
''
else ''
exec ${cfg.locate}/bin/updatedb \
${optionalString (cfg.localuser != null && ! isMLocate) ''--localuser=${cfg.localuser}''} \
--output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
'';
environment = {
environment = optionalAttrs (!isMLocate) {
PRUNEFS = concatStringsSep " " cfg.pruneFS;
PRUNEPATHS = concatStringsSep " " cfg.prunePaths;
PRUNENAMES = concatStringsSep " " cfg.pruneNames;

View File

@ -33,7 +33,11 @@ let
configType = mkOptionType {
name = "nixpkgs-config";
description = "nixpkgs config";
check = traceValIfNot isConfig;
check = x:
let traceXIfNot = c:
if c x then true
else lib.traceSeqN 1 x false;
in traceXIfNot isConfig;
merge = args: fold (def: mergeConfig def.value) {};
};
@ -58,10 +62,13 @@ in
pkgs = mkOption {
defaultText = literalExample
''import "''${nixos}/.." {
inherit (config.nixpkgs) config overlays system;
inherit (config.nixpkgs) config overlays localSystem crossSystem;
}
'';
default = import ../../.. { inherit (cfg) config overlays system crossSystem; };
default = import ../../.. {
localSystem = { inherit (cfg) system; } // cfg.localSystem;
inherit (cfg) config overlays crossSystem;
};
type = pkgsType;
example = literalExample ''import <nixpkgs> {}'';
description = ''
@ -73,8 +80,9 @@ in
relative to the location of this NixOS module, because
NixOS and Nixpkgs are distributed together for consistency,
so the <code>nixos</code> in the default value is in fact a
relative path. The <code>config</code>, <code>overlays</code>
and <code>system</code> come from this option's siblings.
relative path. The <code>config</code>, <code>overlays</code>,
<code>localSystem</code>, and <code>crossSystem</code> come
from this option's siblings.
This option can be used by applications like NixOps to increase
the performance of evaluation, or to create packages that depend
@ -130,13 +138,40 @@ in
'';
};
crossSystem = mkOption {
type = types.nullOr types.attrs;
default = null;
localSystem = mkOption {
type = types.attrs; # TODO utilize lib.systems.parsedPlatform
default = { system = builtins.currentSystem; };
example = { system = "aarch64-linux"; config = "aarch64-unknown-linux-gnu"; };
defaultText = literalExample
''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform'';
description = ''
The description of the system we're cross-compiling to, or null
if this isn't a cross-compile. See the description of the
crossSystem argument in the nixpkgs manual.
Specifies the platform on which NixOS should be built. When
<code>nixpkgs.crossSystem</code> is unset, it also specifies
the platform <emphasis>for</emphasis> which NixOS should be
built. If this option is unset, it defaults to the platform
type of the machine where evaluation happens. Specifying this
option is useful when doing distributed multi-platform
deployment, or when building virtual machines. See its
description in the Nixpkgs manual for more details.
Ignored when <code>nixpkgs.pkgs</code> is set.
'';
};
crossSystem = mkOption {
type = types.nullOr types.attrs; # TODO utilize lib.systems.parsedPlatform
default = null;
example = { system = "aarch64-linux"; config = "aarch64-unknown-linux-gnu"; };
defaultText = literalExample
''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform'';
description = ''
Specifies the platform for which NixOS should be
built. Specify this only if it is different from
<code>nixpkgs.localSystem</code>, the platform
<emphasis>on</emphasis> which NixOS should be built. In other
words, specify this to cross-compile NixOS. Otherwise it
should be set as null, the default. See its description in the
Nixpkgs manual for more details.
Ignored when <code>nixpkgs.pkgs</code> is set.
'';
@ -146,10 +181,20 @@ in
type = types.str;
example = "i686-linux";
description = ''
Specifies the Nix platform type for which NixOS should be built.
If unset, it defaults to the platform type of your host system.
Specifying this option is useful when doing distributed
multi-platform deployment, or when building virtual machines.
Specifies the Nix platform type on which NixOS should be built.
It is better to specify <code>nixpkgs.localSystem</code> instead.
<programlisting>
{
nixpkgs.system = ..;
}
</programlisting>
is the same as
<programlisting>
{
nixpkgs.localSystem.system = ..;
}
</programlisting>
See <code>nixpkgs.localSystem</code> for more information.
Ignored when <code>nixpkgs.pkgs</code> is set.
'';

View File

@ -16,21 +16,6 @@ in
options.system = {
# XXX: Reintroduce old options to make nixops before 1.6 able to evaluate configurations
# XXX: Remove after nixops has been bumped to a compatible version
nixosVersion = mkOption {
readOnly = true;
internal = true;
type = types.str;
default = config.system.nixos.version;
};
nixosVersionSuffix = mkOption {
readOnly = true;
internal = true;
type = types.str;
default = config.system.nixos.versionSuffix;
};
nixos.version = mkOption {
internal = true;
type = types.str;

View File

@ -166,6 +166,7 @@
./services/backup/crashplan-small-business.nix
./services/backup/mysql-backup.nix
./services/backup/postgresql-backup.nix
./services/backup/restic.nix
./services/backup/rsnapshot.nix
./services/backup/tarsnap.nix
./services/backup/znapzend.nix
@ -194,6 +195,7 @@
./services/databases/clickhouse.nix
./services/databases/couchdb.nix
./services/databases/firebird.nix
./services/databases/foundationdb.nix
./services/databases/hbase.nix
./services/databases/influxdb.nix
./services/databases/memcached.nix
@ -325,7 +327,7 @@
./services/misc/geoip-updater.nix
./services/misc/gitea.nix
#./services/misc/gitit.nix
#./services/misc/gitlab.nix
./services/misc/gitlab.nix
./services/misc/gitolite.nix
./services/misc/gitweb.nix
./services/misc/gogs.nix
@ -480,6 +482,7 @@
./services/networking/gnunet.nix
./services/networking/gogoclient.nix
./services/networking/gvpe.nix
./services/networking/hans.nix
./services/networking/haproxy.nix
./services/networking/heyefi.nix
./services/networking/hostapd.nix
@ -533,7 +536,7 @@
./services/networking/prayer.nix
./services/networking/privoxy.nix
./services/networking/prosody.nix
# ./services/networking/quagga.nix
./services/networking/quagga.nix
./services/networking/quassel.nix
./services/networking/racoon.nix
./services/networking/radicale.nix
@ -547,6 +550,7 @@
./services/networking/searx.nix
./services/networking/seeks.nix
./services/networking/skydns.nix
./services/networking/shadowsocks.nix
./services/networking/shairport-sync.nix
./services/networking/shout.nix
./services/networking/sniproxy.nix
@ -558,6 +562,7 @@
./services/networking/ssh/lshd.nix
./services/networking/ssh/sshd.nix
./services/networking/strongswan.nix
./services/networking/strongswan-swanctl/module.nix
./services/networking/stunnel.nix
./services/networking/supplicant.nix
./services/networking/supybot.nix

View File

@ -110,7 +110,7 @@ in
};
enableCompletion = mkOption {
default = false;
default = true;
description = ''
Enable Bash completion for all interactive bash shells.
'';

View File

@ -23,6 +23,8 @@ with lib;
(config:
let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config;
in if enabled then [ pkgs.gutenprint ] else [ ]))
(mkRenamedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ])
(mkRemovedOptionModule [ "services" "ddclient" "homeDir" ] "")
(mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
(mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
(mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ])
@ -187,22 +189,20 @@ with lib;
(mkRenamedOptionModule [ "services" "xserver" "desktopManager" "kde5" ] [ "services" "xserver" "desktopManager" "plasma5" ])
# Fontconfig
(mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "allowBitmaps" ] [ "config" "fonts" "fontconfig" "allowBitmaps" ])
(mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "allowType1" ] [ "config" "fonts" "fontconfig" "allowType1" ])
(mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "useEmbeddedBitmaps" ] [ "config" "fonts" "fontconfig" "useEmbeddedBitmaps" ])
(mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "forceAutohint" ] [ "config" "fonts" "fontconfig" "forceAutohint" ])
(mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ] [ "config" "fonts" "fontconfig" "renderMonoTTFAsBitmap" ])
(mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "allowBitmaps" ] [ "fonts" "fontconfig" "allowBitmaps" ])
(mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "allowType1" ] [ "fonts" "fontconfig" "allowType1" ])
(mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "useEmbeddedBitmaps" ] [ "fonts" "fontconfig" "useEmbeddedBitmaps" ])
(mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "forceAutohint" ] [ "fonts" "fontconfig" "forceAutohint" ])
(mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ] [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ])
# Profile splitting
(mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ])
# misc/version.nix
#(mkRenamedOptionModule [ "config" "system" "nixosVersion" ] [ "config" "system" "nixos" "version" ])
(mkRenamedOptionModule [ "config" "system" "nixosRelease" ] [ "config" "system" "nixos" "release" ])
#(mkRenamedOptionModule [ "config" "system" "nixosVersionSuffix" ] [ "config" "system" "nixos" "versionSuffix" ])
(mkRenamedOptionModule [ "config" "system" "nixosRevision" ] [ "config" "system" "nixos" "revision" ])
(mkRenamedOptionModule [ "config" "system" "nixosCodeName" ] [ "config" "system" "nixos" "codeName" ])
(mkRenamedOptionModule [ "config" "system" "nixosLabel" ] [ "config" "system" "nixos" "label" ])
(mkRenamedOptionModule [ "system" "nixosVersion" ] [ "system" "nixos" "version" ])
(mkRenamedOptionModule [ "system" "nixosVersionSuffix" ] [ "system" "nixos" "versionSuffix" ])
(mkRenamedOptionModule [ "system" "nixosRevision" ] [ "system" "nixos" "revision" ])
(mkRenamedOptionModule [ "system" "nixosLabel" ] [ "system" "nixos" "label" ])
# Users
(mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ])

View File

@ -58,9 +58,11 @@ let
default = "";
example = "systemctl reload nginx.service";
description = ''
Commands to run after certificates are re-issued. Typically
Commands to run after new certificates go live. Typically
the web server and other servers using certificates need to
be reloaded.
Executed in the same directory with the new certificate.
'';
};
@ -78,6 +80,27 @@ let
'';
};
activationDelay = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Systemd time span expression to delay copying new certificates to main
state directory. See <citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
preDelay = mkOption {
type = types.lines;
default = "";
description = ''
Commands to run after certificates are re-issued but before they are
activated. Typically the new certificate is published to DNS.
Executed in the same directory with the new certificate.
'';
};
extraDomains = mkOption {
type = types.attrsOf (types.nullOr types.str);
default = {};
@ -186,14 +209,15 @@ in
servicesLists = mapAttrsToList certToServices cfg.certs;
certToServices = cert: data:
let
cpath = "${cfg.directory}/${cert}";
domain = if data.domain != null then data.domain else cert;
cpath = lpath + optionalString (data.activationDelay != null) ".staging";
lpath = "${cfg.directory}/${cert}";
rights = if data.allowKeysForGroup then "750" else "700";
cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
++ optionals (data.email != null) [ "--email" data.email ]
++ concatMap (p: [ "-f" p ]) data.plugins
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
++ (if cfg.production then []
else ["--server" "https://acme-staging.api.letsencrypt.org/directory"]);
++ optionals (!cfg.production) ["--server" "https://acme-staging.api.letsencrypt.org/directory"];
acmeService = {
description = "Renew ACME Certificate for ${cert}";
after = [ "network.target" "network-online.target" ];
@ -206,7 +230,7 @@ in
Group = data.group;
PrivateTmp = true;
};
path = [ pkgs.simp_le ];
path = with pkgs; [ simp_le systemd ];
preStart = ''
mkdir -p '${cfg.directory}'
chown 'root:root' '${cfg.directory}'
@ -229,17 +253,39 @@ in
exit "$EXITCODE"
'';
postStop = ''
cd '${cpath}'
if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then
echo "Executing postRun hook..."
${data.postRun}
${if data.activationDelay != null then ''
${data.preDelay}
if [ -d '${lpath}' ]; then
systemd-run --no-block --on-active='${data.activationDelay}' --unit acme-setlive-${cert}.service
else
systemctl --wait start acme-setlive-${cert}.service
fi
'' else data.postRun}
fi
'';
before = [ "acme-certificates.target" ];
wantedBy = [ "acme-certificates.target" ];
};
delayService = {
description = "Set certificate for ${cert} live";
path = with pkgs; [ rsync ];
serviceConfig = {
Type = "oneshot";
};
script = ''
rsync -a --delete-after '${cpath}/' '${lpath}'
'';
postStop = data.postRun;
};
selfsignedService = {
description = "Create preliminary self-signed certificate for ${cert}";
path = [ pkgs.openssl ];
preStart = ''
if [ ! -d '${cpath}' ]
then
@ -250,37 +296,41 @@ in
'';
script =
''
# Create self-signed key
workdir="/run/acme-selfsigned-${cert}"
${pkgs.openssl.bin}/bin/openssl genrsa -des3 -passout pass:x -out $workdir/server.pass.key 2048
${pkgs.openssl.bin}/bin/openssl rsa -passin pass:x -in $workdir/server.pass.key -out $workdir/server.key
${pkgs.openssl.bin}/bin/openssl req -new -key $workdir/server.key -out $workdir/server.csr \
workdir="$(mktemp -d)"
# Create CA
openssl genrsa -des3 -passout pass:x -out $workdir/ca.pass.key 2048
openssl rsa -passin pass:x -in $workdir/ca.pass.key -out $workdir/ca.key
openssl req -new -key $workdir/ca.key -out $workdir/ca.csr \
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com"
openssl x509 -req -days 1 -in $workdir/ca.csr -signkey $workdir/ca.key -out $workdir/ca.crt
# Create key
openssl genrsa -des3 -passout pass:x -out $workdir/server.pass.key 2048
openssl rsa -passin pass:x -in $workdir/server.pass.key -out $workdir/server.key
openssl req -new -key $workdir/server.key -out $workdir/server.csr \
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
${pkgs.openssl.bin}/bin/openssl x509 -req -days 1 -in $workdir/server.csr -signkey $workdir/server.key -out $workdir/server.crt
openssl x509 -req -days 1 -in $workdir/server.csr -CA $workdir/ca.crt \
-CAkey $workdir/ca.key -CAserial $workdir/ca.srl -CAcreateserial \
-out $workdir/server.crt
# Move key to destination
mv $workdir/server.key ${cpath}/key.pem
mv $workdir/server.crt ${cpath}/fullchain.pem
# Copy key to destination
cp $workdir/server.key ${cpath}/key.pem
# Create full.pem for e.g. lighttpd (same format as "simp_le ... -f full.pem" creates)
cat "${cpath}/key.pem" "${cpath}/fullchain.pem" > "${cpath}/full.pem"
# Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
cat $workdir/{server.crt,ca.crt} > "${cpath}/fullchain.pem"
# Clean up working directory
rm $workdir/server.csr
rm $workdir/server.pass.key
# Create full.pem for e.g. lighttpd
cat $workdir/{server.key,server.crt,ca.crt} > "${cpath}/full.pem"
# Give key acme permissions
chmod ${rights} '${cpath}/key.pem'
chown '${data.user}:${data.group}' '${cpath}/key.pem'
chmod ${rights} '${cpath}/fullchain.pem'
chown '${data.user}:${data.group}' '${cpath}/fullchain.pem'
chmod ${rights} '${cpath}/full.pem'
chown '${data.user}:${data.group}' '${cpath}/full.pem'
chown '${data.user}:${data.group}' "${cpath}/"{key,fullchain,full}.pem
chmod ${rights} "${cpath}/"{key,fullchain,full}.pem
'';
serviceConfig = {
Type = "oneshot";
RuntimeDirectory = "acme-selfsigned-${cert}";
PermissionsStartOnly = true;
PrivateTmp = true;
User = data.user;
Group = data.group;
};
@ -297,11 +347,8 @@ in
};
in (
[ { name = "acme-${cert}"; value = acmeService; } ]
++
(if cfg.preliminarySelfsigned
then [ { name = "acme-selfsigned-${cert}"; value = selfsignedService; } ]
else []
)
++ optional cfg.preliminarySelfsigned { name = "acme-selfsigned-${cert}"; value = selfsignedService; }
++ optional (data.activationDelay != null) { name = "acme-setlive-${cert}"; value = delayService; }
);
servicesAttr = listToAttrs services;
injectServiceDep = {

View File

@ -234,6 +234,11 @@ let
password, KDE will prompt separately after login.
'';
};
sssdStrictAccess = mkOption {
default = false;
type = types.bool;
description = "enforce sssd access control";
};
enableGnomeKeyring = mkOption {
default = false;
@ -264,11 +269,13 @@ let
text = mkDefault
(''
# Account management.
account sufficient pam_unix.so
account ${if cfg.sssdStrictAccess then "required" else "sufficient"} pam_unix.so
${optionalString use_ldap
"account sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
${optionalString config.services.sssd.enable
${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false)
"account sufficient ${pkgs.sssd}/lib/security/pam_sss.so"}
${optionalString (config.services.sssd.enable && cfg.sssdStrictAccess)
"account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so"}
${optionalString config.krb5.enable
"account sufficient ${pam_krb5}/lib/security/pam_krb5.so"}

View File

@ -10,8 +10,8 @@
#include <errno.h>
#include <linux/capability.h>
#include <sys/capability.h>
#include <linux/prctl.h>
#include <sys/prctl.h>
#include <limits.h>
#include <cap-ng.h>
// Make sure assertions are not compiled out, we use them to codify

View File

@ -54,6 +54,11 @@ in
description = ''
Whether to enable volume and capture control with keyboard media keys.
You want to leave this disabled if you run a desktop environment
like KDE, Gnome, Xfce, etc, as those handle such things themselves.
You might want to enable this if you run a minimalistic desktop
environment or work from bare linux ttys/framebuffers.
Enabling this will turn on <option>services.actkbd</option>.
'';
};

View File

@ -0,0 +1,150 @@
{ config, lib, pkgs, ... }:
with lib;
{
options.services.restic.backups = mkOption {
description = ''
Periodic backups to create with Restic.
'';
type = types.attrsOf (types.submodule ({ name, config, ... }: {
options = {
passwordFile = mkOption {
type = types.str;
description = ''
Read the repository password from a file.
'';
example = "/etc/nixos/restic-password";
};
repository = mkOption {
type = types.str;
description = ''
repository to backup to.
'';
example = "sftp:backup@192.168.1.100:/backups/${name}";
};
paths = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Which paths to backup.
'';
example = [
"/var/lib/postgresql"
"/home/user/backup"
];
};
timerConfig = mkOption {
type = types.attrsOf types.str;
default = {
OnCalendar = "daily";
};
description = ''
When to run the backup. See man systemd.timer for details.
'';
example = {
OnCalendar = "00:05";
RandomizedDelaySec = "5h";
};
};
user = mkOption {
type = types.str;
default = "root";
description = ''
As which user the backup should run.
'';
example = "postgresql";
};
extraBackupArgs = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra arguments passed to restic backup.
'';
example = [
"--exclude-file=/etc/nixos/restic-ignore"
];
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra extended options to be passed to the restic --option flag.
'';
example = [
"sftp.command='ssh backup@192.168.1.100 -i /home/user/.ssh/id_rsa -s sftp'"
];
};
initialize = mkOption {
type = types.bool;
default = false;
description = ''
Create the repository if it doesn't exist.
'';
};
};
}));
default = {};
example = {
localbackup = {
paths = [ "/home" ];
repository = "/mnt/backup-hdd";
passwordFile = "/etc/nixos/secrets/restic-password";
initialize = true;
};
remotebackup = {
paths = [ "/home" ];
repository = "sftp:backup@host:/backups/home";
passwordFile = "/etc/nixos/secrets/restic-password";
extraOptions = [
"sftp.command='ssh backup@host -i /etc/nixos/secrets/backup-private-key -s sftp'"
];
timerConfig = {
OnCalendar = "00:05";
RandomizedDelaySec = "5h";
};
};
};
};
config = {
systemd.services =
mapAttrs' (name: backup:
let
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
connectTo = elemAt (splitString ":" backup.repository) 1;
resticCmd = "${pkgs.restic}/bin/restic${extraOptions}";
in nameValuePair "restic-backups-${name}" ({
environment = {
RESTIC_PASSWORD_FILE = backup.passwordFile;
RESTIC_REPOSITORY = backup.repository;
};
path = with pkgs; [
openssh
];
restartIfChanged = false;
serviceConfig = {
Type = "oneshot";
ExecStart = "${resticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${concatStringsSep " " backup.paths}";
User = backup.user;
};
} // optionalAttrs backup.initialize {
preStart = ''
${resticCmd} snapshots || ${resticCmd} init
'';
})
) config.services.restic.backups;
systemd.timers =
mapAttrs' (name: backup: nameValuePair "restic-backups-${name}" {
wantedBy = [ "timers.target" ];
timerConfig = backup.timerConfig;
}) config.services.restic.backups;
};
}

View File

@ -6,6 +6,13 @@ let
cfg = config.services.boinc;
allowRemoteGuiRpcFlag = optionalString cfg.allowRemoteGuiRpc "--allow_remote_gui_rpc";
fhsEnv = pkgs.buildFHSUserEnv {
name = "boinc-fhs-env";
targetPkgs = pkgs': [ cfg.package ] ++ cfg.extraEnvPackages;
runScript = "/bin/boinc_client";
};
fhsEnvExecutable = "${fhsEnv}/bin/${fhsEnv.name}";
in
{
options.services.boinc = {
@ -49,6 +56,43 @@ in
See also: <link xlink:href="http://boinc.berkeley.edu/wiki/Controlling_BOINC_remotely#Remote_access"/>
'';
};
extraEnvPackages = mkOption {
type = types.listOf types.package;
default = [];
example = "[ pkgs.virtualbox ]";
description = ''
Additional packages to make available in the environment in which
BOINC will run. Common choices are:
<variablelist>
<varlistentry>
<term><varname>pkgs.virtualbox</varname></term>
<listitem><para>
The VirtualBox virtual machine framework. Required by some BOINC
projects, such as ATLAS@home.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>pkgs.ocl-icd</varname></term>
<listitem><para>
OpenCL infrastructure library. Required by BOINC projects that
use OpenCL, in addition to a device-specific OpenCL driver.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>pkgs.linuxPackages.nvidia_x11</varname></term>
<listitem><para>
Provides CUDA libraries. Required by BOINC projects that use
CUDA. Note that this requires an NVIDIA graphics device to be
present on the system.
</para><para>
Also provides OpenCL drivers for NVIDIA GPUs;
<varname>pkgs.ocl-icd</varname> is also needed in this case.
</para></listitem>
</varlistentry>
</variablelist>
'';
};
};
config = mkIf cfg.enable {
@ -70,7 +114,7 @@ in
chown boinc ${cfg.dataDir}
'';
script = ''
${cfg.package}/bin/boinc_client --dir ${cfg.dataDir} --redirectio ${allowRemoteGuiRpcFlag}
${fhsEnvExecutable} --dir ${cfg.dataDir} --redirectio ${allowRemoteGuiRpcFlag}
'';
serviceConfig = {
PermissionsStartOnly = true; # preStart must be run as root

View File

@ -17,7 +17,7 @@ let
hooksDir = let
mkHookEntry = name: value: ''
cat > $out/${name} <<EOF
cat > $out/${name} <<'EOF'
#! ${pkgs.runtimeShell}
set -e
${value}

View File

@ -0,0 +1,360 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.foundationdb;
# used for initial cluster configuration
initialIpAddr = if (cfg.publicAddress != "auto") then cfg.publicAddress else "127.0.0.1";
fdbServers = n:
concatStringsSep "\n" (map (x: "[fdbserver.${toString (x+cfg.listenPortStart)}]") (range 0 (n - 1)));
backupAgents = n:
concatStringsSep "\n" (map (x: "[backup_agent.${toString x}]") (range 1 n));
configFile = pkgs.writeText "foundationdb.conf" ''
[general]
cluster_file = /etc/foundationdb/fdb.cluster
[fdbmonitor]
restart_delay = ${toString cfg.restartDelay}
user = ${cfg.user}
group = ${cfg.group}
[fdbserver]
command = ${pkgs.foundationdb}/bin/fdbserver
public_address = ${cfg.publicAddress}:$ID
listen_address = ${cfg.listenAddress}
datadir = ${cfg.dataDir}/$ID
logdir = ${cfg.logDir}
logsize = ${cfg.logSize}
maxlogssize = ${cfg.maxLogSize}
${optionalString (cfg.class != null) "class = ${cfg.class}"}
memory = ${cfg.memory}
storage_memory = ${cfg.storageMemory}
${optionalString (cfg.locality.machineId != null) "locality_machineid=${cfg.locality.machineId}"}
${optionalString (cfg.locality.zoneId != null) "locality_zoneid=${cfg.locality.zoneId}"}
${optionalString (cfg.locality.datacenterId != null) "locality_dcid=${cfg.locality.datacenterId}"}
${optionalString (cfg.locality.dataHall != null) "locality_data_hall=${cfg.locality.dataHall}"}
${fdbServers cfg.serverProcesses}
[backup_agent]
command = ${pkgs.foundationdb}/libexec/backup_agent
${backupAgents cfg.backupProcesses}
'';
in
{
options.services.foundationdb = {
enable = mkEnableOption "FoundationDB Server";
publicAddress = mkOption {
type = types.str;
default = "auto";
description = "Publicly visible IP address of the process. Port is determined by process ID";
};
listenAddress = mkOption {
type = types.str;
default = "public";
description = "Publicly visible IP address of the process. Port is determined by process ID";
};
listenPortStart = mkOption {
type = types.int;
default = 4500;
description = ''
Starting port number for database listening sockets. Every FDB process binds to a
subsequent port, to this number reflects the start of the overall range. e.g. having
8 server processes will use all ports between 4500 and 4507.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open the firewall ports corresponding to FoundationDB processes and coordinators
using <option>config.networking.firewall.*</option>.
'';
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/foundationdb";
description = "Data directory. All cluster data will be put under here.";
};
logDir = mkOption {
type = types.path;
default = "/var/log/foundationdb";
description = "Log directory.";
};
user = mkOption {
type = types.str;
default = "foundationdb";
description = "User account under which FoundationDB runs.";
};
group = mkOption {
type = types.str;
default = "foundationdb";
description = "Group account under which FoundationDB runs.";
};
class = mkOption {
type = types.nullOr (types.enum [ "storage" "transaction" "stateless" ]);
default = null;
description = "Process class";
};
restartDelay = mkOption {
type = types.int;
default = 10;
description = "Number of seconds to wait before restarting servers.";
};
logSize = mkOption {
type = types.string;
default = "10MiB";
description = ''
Roll over to a new log file after the current log file
reaches the specified size.
'';
};
maxLogSize = mkOption {
type = types.string;
default = "100MiB";
description = ''
Delete the oldest log file when the total size of all log
files exceeds the specified size. If set to 0, old log files
will not be deleted.
'';
};
serverProcesses = mkOption {
type = types.int;
default = 1;
description = "Number of fdbserver processes to run.";
};
backupProcesses = mkOption {
type = types.int;
default = 1;
description = "Number of backup_agent processes to run for snapshots.";
};
memory = mkOption {
type = types.string;
default = "8GiB";
description = ''
Maximum memory used by the process. The default value is
<literal>8GiB</literal>. When specified without a unit,
<literal>MiB</literal> is assumed. This parameter does not
change the memory allocation of the program. Rather, it sets
a hard limit beyond which the process will kill itself and
be restarted. The default value of <literal>8GiB</literal>
is double the intended memory usage in the default
configuration (providing an emergency buffer to deal with
memory leaks or similar problems). It is not recommended to
decrease the value of this parameter below its default
value. It may be increased if you wish to allocate a very
large amount of storage engine memory or cache. In
particular, when the <literal>storageMemory</literal>
parameter is increased, the <literal>memory</literal>
parameter should be increased by an equal amount.
'';
};
storageMemory = mkOption {
type = types.string;
default = "1GiB";
description = ''
Maximum memory used for data storage. The default value is
<literal>1GiB</literal>. When specified without a unit,
<literal>MB</literal> is assumed. Clusters using the memory
storage engine will be restricted to using this amount of
memory per process for purposes of data storage. Memory
overhead associated with storing the data is counted against
this total. If you increase the
<literal>storageMemory</literal>, you should also increase
the <literal>memory</literal> parameter by the same amount.
'';
};
locality = mkOption {
default = {
machineId = null;
zoneId = null;
datacenterId = null;
dataHall = null;
};
description = ''
FoundationDB locality settings.
'';
type = types.submodule ({
options = {
machineId = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
Machine identifier key. All processes on a machine should share a
unique id. By default, processes on a machine determine a unique id to share.
This does not generally need to be set.
'';
};
zoneId = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
Zone identifier key. Processes that share a zone id are
considered non-unique for the purposes of data replication.
If unset, defaults to machine id.
'';
};
datacenterId = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
Data center identifier key. All processes physically located in a
data center should share the id. If you are depending on data
center based replication this must be set on all processes.
'';
};
dataHall = mkOption {
default = null;
type = types.nullOr types.str;
description = ''
Data hall identifier key. All processes physically located in a
data hall should share the id. If you are depending on data
hall based replication this must be set on all processes.
'';
};
};
});
};
extraReadWritePaths = mkOption {
default = [ ];
type = types.listOf types.path;
description = ''
An extra set of filesystem paths that FoundationDB can read to
and write from. By default, FoundationDB runs under a heavily
namespaced systemd environment without write access to most of
the filesystem outside of its data and log directories. By
adding paths to this list, the set of writeable paths will be
expanded. This is useful for allowing e.g. backups to local files,
which must be performed on behalf of the foundationdb service.
'';
};
pidfile = mkOption {
type = types.path;
default = "/run/foundationdb.pid";
description = "Path to pidfile for fdbmonitor.";
};
};
config = mkIf cfg.enable {
meta.doc = ./foundationdb.xml;
meta.maintainers = with lib.maintainers; [ thoughtpolice ];
environment.systemPackages = [ pkgs.foundationdb ];
users.extraUsers = optionalAttrs (cfg.user == "foundationdb") (singleton
{ name = "foundationdb";
description = "FoundationDB User";
uid = config.ids.uids.foundationdb;
group = cfg.group;
});
users.extraGroups = optionalAttrs (cfg.group == "foundationdb") (singleton
{ name = "foundationdb";
gid = config.ids.gids.foundationdb;
});
networking.firewall.allowedTCPPortRanges = mkIf cfg.openFirewall
[ { from = cfg.listenPortStart;
to = (cfg.listenPortStart + cfg.serverProcesses) - 1;
}
];
systemd.services.foundationdb = {
description = "FoundationDB Service";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
unitConfig =
{ RequiresMountsFor = "${cfg.dataDir} ${cfg.logDir}";
};
serviceConfig =
let rwpaths = [ cfg.dataDir cfg.logDir cfg.pidfile "/etc/foundationdb" ]
++ cfg.extraReadWritePaths;
in
{ Type = "simple";
Restart = "always";
RestartSec = 5;
User = cfg.user;
Group = cfg.group;
PIDFile = "${cfg.pidfile}";
PermissionsStartOnly = true; # setup needs root perms
TimeoutSec = 120; # give reasonable time to shut down
# Security options
NoNewPrivileges = true;
ProtectHome = true;
ProtectSystem = "strict";
ProtectKernelTunables = true;
ProtectControlGroups = true;
PrivateTmp = true;
PrivateDevices = true;
ReadWritePaths = lib.concatStringsSep " " (map (x: "-" + x) rwpaths);
};
path = [ pkgs.foundationdb pkgs.coreutils ];
preStart = ''
rm -f ${cfg.pidfile} && \
touch ${cfg.pidfile} && \
chown -R ${cfg.user}:${cfg.group} ${cfg.pidfile}
for x in "${cfg.logDir}" "${cfg.dataDir}" /etc/foundationdb; do
[ ! -d "$x" ] && mkdir -m 0700 -vp "$x" && chown -R ${cfg.user}:${cfg.group} "$x";
done
if [ ! -f /etc/foundationdb/fdb.cluster ]; then
cf=/etc/foundationdb/fdb.cluster
desc=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8)
rand=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8)
echo ''${desc}:''${rand}@${initialIpAddr}:${builtins.toString cfg.listenPortStart} > $cf
chmod 0660 $cf && chown -R ${cfg.user}:${cfg.group} $cf
touch "${cfg.dataDir}/.first_startup"
fi
'';
script = ''
exec fdbmonitor --lockfile ${cfg.pidfile} --conffile ${configFile};
'';
postStart = ''
if [ -e "${cfg.dataDir}/.first_startup" ]; then
fdbcli --exec "configure new single ssd"
rm -f "${cfg.dataDir}/.first_startup";
fi
'';
};
};
}

View File

@ -0,0 +1,280 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="module-foundationdb">
<title>FoundationDB</title>
<para><emphasis>Source:</emphasis> <filename>modules/services/databases/foundationdb.nix</filename></para>
<para><emphasis>Upstream documentation:</emphasis> <link xlink:href="https://apple.github.io/foundationdb/"/></para>
<para><emphasis>Maintainer:</emphasis> Austin Seipp</para>
<para><emphasis>Default version:</emphasis> 5.1.x</para>
<para>FoundationDB (or "FDB") is a distributed, open source, high performance,
transactional key-value store. It can store petabytes of data and deliver
exceptional performance while maintaining consistency and ACID semantics
(serializable transactions) over a large cluster.</para>
<section><title>Configuring and basic setup</title>
<para>To enable FoundationDB, add the following to your
<filename>configuration.nix</filename>:
<programlisting>
services.foundationdb.enable = true;
</programlisting>
</para>
<para>After running <command>nixos-rebuild</command>, you can verify whether
FoundationDB is running by executing <command>fdbcli</command> (which is added
to <option>environment.systemPackages</option>):
<programlisting>
$ sudo -u foundationdb fdbcli
Using cluster file `/etc/foundationdb/fdb.cluster'.
The database is available.
Welcome to the fdbcli. For help, type `help'.
fdb> status
Using cluster file `/etc/foundationdb/fdb.cluster'.
Configuration:
Redundancy mode - single
Storage engine - memory
Coordinators - 1
Cluster:
FoundationDB processes - 1
Machines - 1
Memory availability - 5.4 GB per process on machine with least available
Fault Tolerance - 0 machines
Server time - 04/20/18 15:21:14
...
fdb>
</programlisting>
</para>
<para>FoundationDB is run under the <command>foundationdb</command> user and
group by default, but this may be changed in the NixOS configuration. The
systemd unit <command>foundationdb.service</command> controls the
<command>fdbmonitor</command> process.</para>
<para>By default, the NixOS module for FoundationDB creates a single
SSD-storage based database for development and basic usage. This storage engine
is designed for SSDs and will perform poorly on HDDs; however it can handle far
more data than the alternative "memory" engine and is a better default choice
for most deployments. (Note that you can change the storage backend on-the-fly
for a given FoundationDB cluster using <command>fdbcli</command>.)</para>
<para>Furthermore, only 1 server process and 1 backup agent are started in the
default configuration. See below for more on scaling to increase this.</para>
<para>FoundationDB stores all data for all server processes under
<filename>/var/lib/foundationdb</filename>. You can override this using
<option>services.foundationdb.dataDir</option>, e.g.
<programlisting>
services.foundationdb.dataDir = "/data/fdb";
</programlisting>
</para>
<para>Similarly, logs are stored under
<filename>/var/log/foundationdb</filename> by default, and there is a
corresponding <option>services.foundationdb.logDir</option> as well.</para>
</section>
<section><title>Scaling processes and backup agents</title>
<para>Scaling the number of server processes is quite easy; simply specify
<option>services.foundationdb.serverProcesses</option> to be the number of
FoundationDB worker processes that should be started on the machine.</para>
<para>FoundationDB worker processes typically require 4GB of RAM per-process at
minimum for good performance, so this option is set to 1 by default since the
maximum amount of RAM is unknown. You're advised to abide by this restriction,
so pick a number of processes so that each has 4GB or more.</para>
<para>A similar option exists in order to scale backup agent processes,
<option>services.foundationdb.backupProcesses</option>. Backup agents are not
as performance/RAM sensitive, so feel free to experiment with the number of
available backup processes.</para>
</section>
<section><title>Clustering</title>
<para>FoundationDB on NixOS works similarly to other Linux systems, so this
section will be brief. Please refer to the full FoundationDB documentation for
more on clustering.</para>
<para>FoundationDB organizes clusters using a set of
<emphasis>coordinators</emphasis>, which are just specially-designated worker
processes. By default, every installation of FoundationDB on NixOS will start
as its own individual cluster, with a single coordinator: the first worker
process on <command>localhost</command>.</para>
<para>Coordinators are specified globally using the
<command>/etc/foundationdb/fdb.cluster</command> file, which all servers and
client applications will use to find and join coordinators. Note that this file
<emphasis>can not</emphasis> be managed by NixOS so easily: FoundationDB is
designed so that it will rewrite the file at runtime for all clients and nodes
when cluster coordinators change, with clients transparently handling this
without intervention. It is fundamentally a mutable file, and you should not
try to manage it in any way in NixOS.</para>
<para>When dealing with a cluster, there are two main things you want to
do:</para>
<itemizedlist>
<listitem><para>Add a node to the cluster for storage/compute.</para></listitem>
<listitem><para>Promote an ordinary worker to a coordinator.</para></listitem>
</itemizedlist>
<para>A node must already be a member of the cluster in order to properly be
promoted to a coordinator, so you must always add it first if you wish to
promote it.</para>
<para>To add a machine to a FoundationDB cluster:</para>
<itemizedlist>
<listitem><para>Choose one of the servers to start as the initial coordinator.
</para></listitem>
<listitem><para>Copy the <command>/etc/foundationdb/fdb.cluster</command> file
from this server to all the other servers. Restart FoundationDB on all of
these other servers, so they join the cluster.</para></listitem>
<listitem><para>All of these servers are now connected and working together
in the cluster, under the chosen coordinator.</para></listitem>
</itemizedlist>
<para>At this point, you can add as many nodes as you want by just repeating
the above steps. By default there will still be a single coordinator: you can
use <command>fdbcli</command> to change this and add new coordinators.</para>
<para>As a convenience, FoundationDB can automatically assign coordinators
based on the redundancy mode you wish to achieve for the cluster. Once all the
nodes have been joined, simply set the replication policy, and then issue the
<command>coordinators auto</command> command</para>
<para>For example, assuming we have 3 nodes available, we can enable double
redundancy mode, then auto-select coordinators. For double redundancy, 3
coordinators is ideal: therefore FoundationDB will make
<emphasis>every</emphasis> node a coordinator automatically:</para>
<programlisting>
fdbcli> configure double ssd
fdbcli> coordinators auto
</programlisting>
<para>This will transparently update all the servers within seconds, and
appropriately rewrite the <command>fdb.cluster</command> file, as well as
informing all client processes to do the same.</para>
</section>
<section><title>Client connectivity</title>
<para>By default, all clients must use the current
<command>fdb.cluster</command> file to access a given FoundationDB cluster.
This file is located by default in
<command>/etc/foundationdb/fdb.cluster</command> on all machines with the
FoundationDB service enabled, so you may copy the active one from your cluster
to a new node in order to connect, if it is not part of the cluster.</para>
</section>
<section><title>Backups and Disaster Recovery</title>
<para>The usual rules for doing FoundationDB backups apply on NixOS as written
in the FoundationDB manual. However, one important difference is the security
profile for NixOS: by default, the <command>foundationdb</command> systemd unit
uses <emphasis>Linux namespaces</emphasis> to restrict write access to the
system, except for the log directory, data directory, and the
<command>/etc/foundationdb/</command> directory. This is enforced by default
and cannot be disabled.</para>
<para>However, a side effect of this is that the <command>fdbbackup</command>
command doesn't work properly for local filesystem backups: FoundationDB uses a
server process alongside the database processes to perform backups and copy the
backups to the filesystem. As a result, this process is put under the
restricted namespaces above: the backup process can only write to a limited
number of paths.</para>
<para>In order to allow flexible backup locations on local disks, the
FoundationDB NixOS module supports a
<option>services.foundationdb.extraReadWritePaths</option> option. This option
takes a list of paths, and adds them to the systemd unit, allowing the
processes inside the service to write (and read) the specified
directories.</para>
<para>For example, to create backups in <command>/opt/fdb-backups</command>,
first set up the paths in the module options:</para>
<programlisting>
services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
</programlisting>
<para>Restart the FoundationDB service, and it will now be able to write to
this directory (even if it does not yet exist.) Note: this path
<emphasis>must</emphasis> exist before restarting the unit. Otherwise, systemd
will not include it in the private FoundationDB namespace (and it will not add
it dynamically at runtime).</para>
<para>You can now perform a backup:</para>
<programlisting>
$ sudo -u foundationdb fdbbackup start -t default -d file:///opt/fdb-backups
$ sudo -u foundationdb fdbbackup status -t default
</programlisting>
</section>
<section><title>Known limitations</title>
<para>The FoundationDB setup for NixOS should currently be considered beta.
FoundationDB is not new software, but the NixOS compilation and integration has
only undergone fairly basic testing of all the available functionality.</para>
<itemizedlist>
<listitem><para>TLS plugin support is compiled in, but it's currently not
possible to specify the set of TLS certificate options in
<command>services.foundationdb</command></para></listitem>
<listitem><para>There is no way to specify individual parameters for
individual <command>fdbserver</command> processes. Currently, all server
processes inherit all the global <command>fdbmonitor</command> settings.
</para></listitem>
<listitem><para>Python bindings are not currently installed.</para></listitem>
<listitem><para>Ruby bindings are not currently installed.</para></listitem>
<listitem><para>Java bindings are not currently installed.</para></listitem>
<listitem><para>Go bindings are not currently installed.</para></listitem>
</itemizedlist>
</section>
<section><title>Options</title>
<para>NixOS's FoundationDB module allows you to configure all of the most
relevant configuration options for <command>fdbmonitor</command>, matching it
quite closely. For a complete list of all options, check <command>man
configuration.nix</command>.</para>
</section>
<section><title>Full documentation</title>
<para>FoundationDB is a complex piece of software, and requires careful
administration to properly use. Full documentation for administration can be
found here: <link xlink:href="https://apple.github.io/foundationdb/"/>.</para>
</section>
</chapter>

View File

@ -22,7 +22,7 @@ let
web_root = ${cfg.package}/etc/pgmanage/web_root
data_root = ${cfg.dataRoot}
sql_root = ${cfg.sqlRoot}
${optionalString (!isNull cfg.tls) ''
tls_cert = ${cfg.tls.cert}
@ -130,7 +130,7 @@ let
'';
};
dataRoot = mkOption {
sqlRoot = mkOption {
type = types.str;
default = "/var/lib/pgmanage";
description = ''
@ -210,7 +210,7 @@ in {
users."${pgmanage}" = {
name = pgmanage;
group = pgmanage;
home = cfg.dataRoot;
home = cfg.sqlRoot;
createHome = true;
};
groups."${pgmanage}" = {

View File

@ -36,9 +36,6 @@ let
${cfg.extraConfig}
'';
pre84 = versionOlder (builtins.parseDrvName postgresql.name).version "8.4";
in
{
@ -182,7 +179,7 @@ in
services.postgresql.authentication = mkAfter
''
# Generated file; do not edit!
local all all ident ${optionalString pre84 "sameuser"}
local all all ident
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
'';

View File

@ -15,6 +15,25 @@ let
fi
'';
desktopApplicationFile = pkgs.writeTextFile {
name = "emacsclient.desktop";
destination = "/share/applications/emacsclient.desktop";
text = ''
[Desktop Entry]
Name=Emacsclient
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=emacseditor %F
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupWMClass=Emacs
Keywords=Text;Editor;
'';
};
in {
options.services.emacs = {
@ -74,7 +93,7 @@ in {
};
} // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
environment.systemPackages = [ cfg.package editorScript ];
environment.systemPackages = [ cfg.package editorScript desktopApplicationFile ];
environment.variables = {
# This is required so that GTK applications launched from Emacs

View File

@ -3,8 +3,8 @@
with lib;
let
bluez-bluetooth = pkgs.bluez;
cfg = config.hardware.bluetooth;
bluez-bluetooth = cfg.package;
in {
@ -21,6 +21,16 @@ in {
description = "Whether to power up the default Bluetooth controller on boot.";
};
package = mkOption {
type = types.package;
default = pkgs.bluez;
defaultText = "pkgs.bluez";
example = "pkgs.bluez.override { enableMidi = true; }";
description = ''
Which BlueZ package to use.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";

View File

@ -26,8 +26,15 @@ in {
name = "trezord-udev-rules";
destination = "/etc/udev/rules.d/51-trezor.rules";
text = ''
SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0666", GROUP="dialout", SYMLINK+="trezor%n"
KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", MODE="0666", GROUP="dialout"
# Trezor 1
SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0666", GROUP="dialout", SYMLINK+="trezor%n"
KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", MODE="0666", GROUP="dialout"
# Trezor 2 (Model-T)
SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c0", MODE="0661", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl", SYMLINK+="trezor%n"
SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c1", MODE="0660", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl", SYMLINK+="trezor%n"
KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", MODE="0660", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl"
];
'';
});
@ -38,7 +45,7 @@ in {
path = [];
serviceConfig = {
Type = "simple";
ExecStart = "${pkgs.trezord}/bin/trezord -f";
ExecStart = "${pkgs.trezord}/bin/trezord-go";
User = "trezord";
};
};

View File

@ -158,7 +158,7 @@ in
services.dysnomia.properties = {
hostname = config.networking.hostName;
system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system;
inherit (config.nixpkgs.localSystem) system;
supportedTypes = (import "${pkgs.stdenv.mkDerivation {
name = "supportedtypes";

View File

@ -8,9 +8,6 @@ let
cfg = config.services.gitlab;
ruby = cfg.packages.gitlab.ruby;
bundler = pkgs.bundler;
gemHome = "${cfg.packages.gitlab.rubyEnv}/${ruby.gemPath}";
gitlabSocket = "${cfg.statePath}/tmp/sockets/gitlab.socket";
gitalySocket = "${cfg.statePath}/tmp/sockets/gitaly.socket";
@ -137,8 +134,6 @@ let
gitlabEnv = {
HOME = "${cfg.statePath}/home";
GEM_HOME = gemHome;
BUNDLE_GEMFILE = "${cfg.packages.gitlab}/share/gitlab/Gemfile";
UNICORN_PATH = "${cfg.statePath}/";
GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/";
GITLAB_STATE_PATH = "${cfg.statePath}";
@ -158,19 +153,17 @@ let
gitlab-rake = pkgs.stdenv.mkDerivation rec {
name = "gitlab-rake";
buildInputs = [ cfg.packages.gitlab cfg.packages.gitlab.rubyEnv pkgs.makeWrapper ];
phases = "installPhase fixupPhase";
buildPhase = "";
buildInputs = [ pkgs.makeWrapper ];
dontBuild = true;
unpackPhase = ":";
installPhase = ''
mkdir -p $out/bin
makeWrapper ${cfg.packages.gitlab.rubyEnv}/bin/bundle $out/bin/gitlab-bundle \
makeWrapper ${cfg.packages.gitlab.rubyEnv}/bin/rake $out/bin/gitlab-rake \
${concatStrings (mapAttrsToList (name: value: "--set ${name} '${value}' ") gitlabEnv)} \
--set GITLAB_CONFIG_PATH '${cfg.statePath}/config' \
--set PATH '${lib.makeBinPath [ pkgs.nodejs pkgs.gzip pkgs.git pkgs.gnutar config.services.postgresql.package ]}:$PATH' \
--set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \
--run 'cd ${cfg.packages.gitlab}/share/gitlab'
makeWrapper $out/bin/gitlab-bundle $out/bin/gitlab-rake \
--add-flags "exec rake"
'';
};
@ -482,10 +475,10 @@ in {
Type = "simple";
User = cfg.user;
Group = cfg.group;
TimeoutSec = "300";
TimeoutSec = "infinity";
Restart = "on-failure";
WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/bundle exec \"sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production -P ${cfg.statePath}/tmp/sidekiq.pid\"";
ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production -P ${cfg.statePath}/tmp/sidekiq.pid";
};
};
@ -493,11 +486,9 @@ in {
after = [ "network.target" "gitlab.service" ];
wantedBy = [ "multi-user.target" ];
environment.HOME = gitlabEnv.HOME;
environment.GEM_HOME = "${cfg.packages.gitaly.rubyEnv}/${ruby.gemPath}";
environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH;
path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv ruby ];
path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv cfg.packages.gitaly.rubyEnv.wrappedRuby ];
serviceConfig = {
#PermissionsStartOnly = true; # preStart must be run as root
Type = "simple";
User = cfg.user;
Group = cfg.group;
@ -529,7 +520,7 @@ in {
Type = "simple";
User = cfg.user;
Group = cfg.group;
TimeoutSec = "300";
TimeoutSec = "infinity";
Restart = "on-failure";
WorkingDirectory = gitlabEnv.HOME;
ExecStart =
@ -658,10 +649,10 @@ in {
Type = "simple";
User = cfg.user;
Group = cfg.group;
TimeoutSec = "300";
TimeoutSec = "infinity";
Restart = "on-failure";
WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
ExecStart = "${cfg.packages.gitlab.rubyEnv}/bin/bundle exec \"unicorn -c ${cfg.statePath}/config/unicorn.rb -E production\"";
ExecStart = "${cfg.packages.gitlab.rubyEnv}/bin/unicorn -c ${cfg.statePath}/config/unicorn.rb -E production";
};
};

View File

@ -32,6 +32,14 @@ in
'';
};
gitwebTheme = mkOption {
default = false;
type = types.bool;
description = ''
Use an alternative theme for gitweb, strongly inspired by GitHub.
'';
};
gitwebConfigFile = mkOption {
default = pkgs.writeText "gitweb.conf" ''
# path to git projects (<project>.git)

View File

@ -5,7 +5,10 @@ with lib;
let
cfg = config.services.home-assistant;
configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config);
# cfg.config != null can be assumed here
configFile = pkgs.writeText "configuration.json"
(builtins.toJSON (if cfg.applyDefaultConfig then
(lib.recursiveUpdate defaultConfig cfg.config) else cfg.config));
availableComponents = pkgs.home-assistant.availableComponents;
@ -38,6 +41,12 @@ let
then (cfg.package.override { inherit extraComponents; })
else cfg.package;
# If you are changing this, please update the description in applyDefaultConfig
defaultConfig = {
homeassistant.time_zone = config.time.timeZone;
http.server_port = (toString cfg.port);
};
in {
meta.maintainers = with maintainers; [ dotlambda ];
@ -50,6 +59,26 @@ in {
description = "The config directory, where your <filename>configuration.yaml</filename> is located.";
};
port = mkOption {
default = 8123;
type = types.int;
description = "The port on which to listen.";
};
applyDefaultConfig = mkOption {
default = true;
type = types.bool;
description = ''
Setting this option enables a few configuration options for HA based on NixOS configuration (such as time zone) to avoid having to manually specify configuration we already have.
</para>
<para>
Currently one side effect of enabling this is that the <literal>http</literal> component will be enabled.
</para>
<para>
This only takes effect if <literal>config != null</literal> in order to ensure that a manually managed <filename>configuration.yaml</filename> is not overwritten.
'';
};
config = mkOption {
default = null;
type = with types; nullOr attrs;
@ -106,19 +135,20 @@ in {
description = "Home Assistant";
after = [ "network.target" ];
preStart = lib.optionalString (cfg.config != null) ''
rm -f ${cfg.configDir}/configuration.yaml
ln -s ${configFile} ${cfg.configDir}/configuration.yaml
config=${cfg.configDir}/configuration.yaml
rm -f $config
${pkgs.remarshal}/bin/json2yaml -i ${configFile} -o $config
chmod 444 $config
'';
serviceConfig = {
ExecStart = ''
${package}/bin/hass --config "${cfg.configDir}"
'';
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
User = "hass";
Group = "hass";
Restart = "on-failure";
ProtectSystem = "strict";
ReadWritePaths = "${cfg.configDir}";
PrivateTmp = true;
RemoveIPC = true;
};
path = [
"/run/wrappers" # needed for ping

View File

@ -7,6 +7,13 @@ let
in {
options.services.logkeys = {
enable = mkEnableOption "logkeys service";
device = mkOption {
description = "Use the given device as keyboard input event device instead of /dev/input/eventX default.";
default = null;
type = types.nullOr types.string;
example = "/dev/input/event15";
};
};
config = mkIf cfg.enable {
@ -14,7 +21,7 @@ in {
description = "LogKeys Keylogger Daemon";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.logkeys}/bin/logkeys -s";
ExecStart = "${pkgs.logkeys}/bin/logkeys -s${lib.optionalString (cfg.device != null) " -d ${cfg.device}"}";
ExecStop = "${pkgs.logkeys}/bin/logkeys -k";
Type = "forking";
};

View File

@ -213,7 +213,7 @@ in {
PermissionsStartOnly = true;
};
preStart = ''
mkdir -m 0700 -p ${cfg.workDir}
mkdir -m 0701 -p ${cfg.workDir}
'';
};
};

View File

@ -23,7 +23,7 @@ let
options =
let
scrubbedEval = evalModules {
modules = [ { nixpkgs.system = config.nixpkgs.system; } ] ++ baseModules;
modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ baseModules;
args = (config._module.args) // { modules = [ ]; };
specialArgs = { pkgs = scrubDerivations "pkgs" pkgs; };
};

View File

@ -50,7 +50,7 @@ in {
protocol = mkOption {
description = "Which protocol to listen.";
default = "http";
type = types.enum ["http" "https"];
type = types.enum ["http" "https" "socket"];
};
addr = mkOption {

View File

@ -20,6 +20,7 @@ let
exporterOpts = {
blackbox = import ./exporters/blackbox.nix { inherit config lib pkgs; };
collectd = import ./exporters/collectd.nix { inherit config lib pkgs; };
dovecot = import ./exporters/dovecot.nix { inherit config lib pkgs; };
fritzbox = import ./exporters/fritzbox.nix { inherit config lib pkgs; };
json = import ./exporters/json.nix { inherit config lib pkgs; };
minio = import ./exporters/minio.nix { inherit config lib pkgs; };

View File

@ -0,0 +1,50 @@
{ config, lib, pkgs }:
with lib;
let
cfg = config.services.prometheus.exporters.dovecot;
in
{
port = 9166;
extraOpts = {
telemetryPath = mkOption {
type = types.str;
default = "/metrics";
description = ''
Path under which to expose metrics.
'';
};
socketPath = mkOption {
type = types.path;
default = "/var/run/dovecot/stats";
example = "/var/run/dovecot2/stats";
description = ''
Path under which the stats socket is placed.
The user/group under which the exporter runs,
should be able to access the socket in order
to scrape the metrics successfully.
'';
};
scopes = mkOption {
type = types.listOf types.str;
default = [ "user" ];
example = [ "user" "global" ];
description = ''
Stats scopes to query.
'';
};
};
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
--dovecot.socket-path ${cfg.socketPath} \
--dovecot.scopes ${concatStringsSep "," cfg.scopes} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View File

@ -32,6 +32,33 @@ in
Path where Postfix places it's showq socket.
'';
};
systemd = {
enable = mkEnableOption ''
reading metrics from the systemd-journal instead of from a logfile
'';
unit = mkOption {
type = types.str;
default = "postfix.service";
description = ''
Name of the postfix systemd unit.
'';
};
slice = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Name of the postfix systemd slice.
This overrides the <option>systemd.unit</option>.
'';
};
journalPath = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to the systemd journal.
'';
};
};
};
serviceOpts = {
serviceConfig = {
@ -39,7 +66,15 @@ in
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
--postfix.showq_path ${cfg.showqPath} \
${concatStringsSep " \\\n " (cfg.extraFlags
++ optional cfg.systemd.enable "--systemd.enable"
++ optional cfg.systemd.enable (if cfg.systemd.slice != null
then "--systemd.slice ${cfg.systemd.slice}"
else "--systemd.unit ${cfg.systemd.unit}")
++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null))
"--systemd.jounal_path ${cfg.systemd.journalPath}"
++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${cfg.logfilePath}")}
'';
};
};

View File

@ -6,6 +6,7 @@ let
confFile = pkgs.writeText "dante-sockd.conf" ''
user.privileged: root
user.unprivileged: dante
logoutput: syslog
${cfg.config}
'';
@ -21,11 +22,10 @@ in
enable = mkEnableOption "Dante SOCKS proxy";
config = mkOption {
default = null;
type = types.nullOr types.str;
type = types.lines;
description = ''
Contents of Dante's configuration file
NOTE: user.privileged/user.unprivileged are set by the service
Contents of Dante's configuration file.
NOTE: user.privileged, user.unprivileged and logoutput are set by the service.
'';
};
};
@ -33,7 +33,7 @@ in
config = mkIf cfg.enable {
assertions = [
{ assertion = cfg.config != null;
{ assertion = cfg.config != "";
message = "please provide Dante configuration file contents";
}
];
@ -54,7 +54,8 @@ in
Type = "simple";
ExecStart = "${pkgs.dante}/bin/sockd -f ${confFile}";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
Restart = "always";
# Can crash sometimes; see https://github.com/NixOS/nixpkgs/pull/39005#issuecomment-381828708
Restart = "on-failure";
};
};
};

View File

@ -3,24 +3,24 @@
let
cfg = config.services.ddclient;
boolToStr = bool: if bool then "yes" else "no";
dataDir = "/var/lib/ddclient";
configText = ''
# This file can be used as a template for configFile or is automatically generated by Nix options.
daemon=${toString cfg.interval}
cache=${cfg.homeDir}/ddclient.cache
pid=/run/ddclient/ddclient.pid
foreground=NO
cache=${dataDir}/ddclient.cache
foreground=YES
use=${cfg.use}
login=${cfg.username}
password=${cfg.password}
protocol=${cfg.protocol}
${let server = cfg.server; in
lib.optionalString (server != "") "server=${server}"}
${lib.optionalString (cfg.script != "") "script=${cfg.script}"}
${lib.optionalString (cfg.server != "") "server=${cfg.server}"}
${lib.optionalString (cfg.zone != "") "zone=${cfg.zone}"}
ssl=${boolToStr cfg.ssl}
wildcard=YES
quiet=${boolToStr cfg.quiet}
verbose=${boolToStr cfg.verbose}
${cfg.domain}
${lib.concatStringsSep "," cfg.domains}
${cfg.extraConfig}
'';
@ -44,17 +44,11 @@ with lib;
'';
};
homeDir = mkOption {
default = "/var/lib/ddclient";
type = str;
description = "Home directory for the daemon user.";
};
domain = mkOption {
default = "";
type = str;
domains = mkOption {
default = [ "" ];
type = listOf str;
description = ''
Domain name to synchronize.
Domain name(s) to synchronize.
'';
};
@ -62,7 +56,7 @@ with lib;
default = "";
type = str;
description = ''
Username.
User name.
'';
};
@ -75,9 +69,12 @@ with lib;
};
interval = mkOption {
default = 600;
type = int;
description = "The interval at which to run the check and update.";
default = "10min";
type = str;
description = ''
The interval at which to run the check and update.
See <command>man 7 systemd.time</command> for the format.
'';
};
configFile = mkOption {
@ -95,7 +92,7 @@ with lib;
default = "dyndns2";
type = str;
description = ''
Protocol to use with dynamic DNS provider (see http://sourceforge.net/apps/trac/ddclient/wiki/Protocols).
Protocol to use with dynamic DNS provider (see https://sourceforge.net/p/ddclient/wiki/protocols).
'';
};
@ -115,11 +112,20 @@ with lib;
'';
};
extraConfig = mkOption {
default = "";
type = lines;
quiet = mkOption {
default = false;
type = bool;
description = ''
Extra configuration. Contents will be added verbatim to the configuration file.
Print no messages for unnecessary updates.
'';
};
script = mkOption {
default = "";
type = str;
description = ''
script as required by some providers.
'';
};
@ -139,11 +145,19 @@ with lib;
'';
};
quiet = mkOption {
default = false;
type = bool;
zone = mkOption {
default = "";
type = str;
description = ''
Print no messages for unnecessary updates.
zone as required by some providers.
'';
};
extraConfig = mkOption {
default = "";
type = lines;
description = ''
Extra configuration. Contents will be added verbatim to the configuration file.
'';
};
};
@ -153,23 +167,8 @@ with lib;
###### implementation
config = mkIf config.services.ddclient.enable {
users = {
extraGroups.ddclient.gid = config.ids.gids.ddclient;
extraUsers.ddclient = {
uid = config.ids.uids.ddclient;
description = "ddclient daemon user";
group = "ddclient";
home = cfg.homeDir;
createHome = true;
};
};
environment.etc."ddclient.conf" = {
enable = cfg.configFile == "/etc/ddclient.conf";
uid = config.ids.uids.ddclient;
gid = config.ids.gids.ddclient;
mode = "0600";
text = configText;
};
@ -180,15 +179,22 @@ with lib;
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."ddclient.conf".source ];
serviceConfig = {
RuntimeDirectory = "ddclient";
# we cannot run in forking mode as it swallows all the program output
Type = "simple";
User = "ddclient";
Group = "ddclient";
ExecStart = "${lib.getBin pkgs.ddclient}/bin/ddclient -foreground -file ${cfg.configFile}";
ProtectSystem = "full";
PrivateTmp = true;
serviceConfig = rec {
DynamicUser = true;
RuntimeDirectory = StateDirectory;
StateDirectory = builtins.baseNameOf dataDir;
Type = "oneshot";
ExecStartPre = "!${lib.getBin pkgs.coreutils}/bin/install -m666 ${cfg.configFile} /run/${RuntimeDirectory}/ddclient.conf";
ExecStart = "${lib.getBin pkgs.ddclient}/bin/ddclient -file /run/${RuntimeDirectory}/ddclient.conf";
};
};
systemd.timers.ddclient = {
description = "Run ddclient";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = cfg.interval;
OnUnitInactiveSec = cfg.interval;
};
};
};

View File

@ -9,12 +9,12 @@ let
mkdir -p $out/{servers,ip}
${concatMapStrings (ip: ''
echo > "$out/ip/"${lib.escapeShellArg ip}
touch "$out/ip/"${lib.escapeShellArg ip}
'') cfg.clientIps}
${concatStrings (mapAttrsToList (host: ips: ''
${concatMapStrings (ip: ''
echo ${lib.escapeShellArg ip} > "$out/servers/"${lib.escapeShellArg host}
echo ${lib.escapeShellArg ip} >> "$out/servers/"${lib.escapeShellArg host}
'') ips}
'') cfg.domainServers)}
@ -34,33 +34,49 @@ in {
options = {
services.dnscache = {
enable = mkOption {
default = false;
type = types.bool;
description = "Whether to run the dnscache caching dns server";
description = "Whether to run the dnscache caching dns server.";
};
ip = mkOption {
default = "0.0.0.0";
type = types.str;
description = "IP address on which to listen for connections";
description = "IP address on which to listen for connections.";
};
clientIps = mkOption {
default = [ "127.0.0.1" ];
type = types.listOf types.str;
description = "client IP addresses (or prefixes) from which to accept connections";
description = "Client IP addresses (or prefixes) from which to accept connections.";
example = ["192.168" "172.23.75.82"];
};
domainServers = mkOption {
default = { };
type = types.attrsOf (types.listOf types.str);
description = "table of {hostname: server} pairs to use as authoritative servers for hosts (and subhosts)";
description = ''
Table of {hostname: server} pairs to use as authoritative servers for hosts (and subhosts).
If entry for @ is not specified predefined list of root servers is used.
'';
example = {
"example.com" = ["8.8.8.8" "8.8.4.4"];
"@" = ["8.8.8.8" "8.8.4.4"];
"example.com" = ["192.168.100.100"];
};
};
forwardOnly = mkOption {
default = false;
type = types.bool;
description = ''
Whether to treat root servers (for @) as caching
servers, requesting addresses the same way a client does. This is
needed if you want to use e.g. Google DNS as your upstream DNS.
'';
};
};
};
@ -82,6 +98,7 @@ in {
'';
script = ''
cd /var/lib/dnscache/
${optionalString cfg.forwardOnly "export FORWARDONLY=1"}
exec ./run
'';
};

View File

@ -0,0 +1,145 @@
# NixOS module for hans, ip over icmp daemon
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.hans;
hansUser = "hans";
in
{
### configuration
options = {
services.hans = {
clients = mkOption {
default = {};
description = ''
Each attribute of this option defines a systemd service that
runs hans. Many or none may be defined.
The name of each service is
<literal>hans-<replaceable>name</replaceable></literal>
where <replaceable>name</replaceable> is the name of the
corresponding attribute name.
'';
example = literalExample ''
{
foo = {
server = "192.0.2.1";
extraConfig = "-v";
}
}
'';
type = types.attrsOf (types.submodule (
{
options = {
server = mkOption {
type = types.str;
default = "";
description = "IP address of server running hans";
example = "192.0.2.1";
};
extraConfig = mkOption {
type = types.str;
default = "";
description = "Additional command line parameters";
example = "-v";
};
passwordFile = mkOption {
type = types.str;
default = "";
description = "File that containts password";
};
};
}));
};
server = {
enable = mkOption {
type = types.bool;
default = false;
description = "enable hans server";
};
ip = mkOption {
type = types.str;
default = "";
description = "The assigned ip range";
example = "198.51.100.0";
};
respondToSystemPings = mkOption {
type = types.bool;
default = false;
description = "Force hans respond to ordinary pings";
};
extraConfig = mkOption {
type = types.str;
default = "";
description = "Additional command line parameters";
example = "-v";
};
passwordFile = mkOption {
type = types.str;
default = "";
description = "File that containts password";
};
};
};
};
### implementation
config = mkIf (cfg.server.enable || cfg.clients != {}) {
boot.kernel.sysctl = optionalAttrs cfg.server.respondToSystemPings {
"net.ipv4.icmp_echo_ignore_all" = 1;
};
boot.kernelModules = [ "tun" ];
systemd.services =
let
createHansClientService = name: cfg:
{
description = "hans client - ${name}";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
script = "${pkgs.hans}/bin/hans -f -u ${hansUser} ${cfg.extraConfig} -c ${cfg.server} ${optionalString (cfg.passwordFile != "") "-p $(cat \"${cfg.passwordFile}\")"}";
serviceConfig = {
RestartSec = "30s";
Restart = "always";
};
};
in
listToAttrs (
mapAttrsToList
(name: value: nameValuePair "hans-${name}" (createHansClientService name value))
cfg.clients
) // {
hans = mkIf (cfg.server.enable) {
description = "hans, ip over icmp server daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
script = "${pkgs.hans}/bin/hans -f -u ${hansUser} ${cfg.server.extraConfig} -s ${cfg.server.ip} ${optionalString cfg.server.respondToSystemPings "-r"} ${optionalString (cfg.server.passwordFile != "") "-p $(cat \"${cfg.server.passwordFile}\")"}";
};
};
users.extraUsers = singleton {
name = hansUser;
description = "Hans daemon user";
};
};
meta.maintainers = with maintainers; [ gnidorah ];
}

View File

@ -32,7 +32,7 @@ in
foo = {
server = "tunnel.mdomain.com";
relay = "8.8.8.8";
extraConfig = "-P mysecurepassword";
extraConfig = "-v";
}
}
'';
@ -57,7 +57,13 @@ in
type = types.str;
default = "";
description = "Additional command line parameters";
example = "-P mysecurepassword -l 192.168.1.10 -p 23";
example = "-l 192.168.1.10 -p 23";
};
passwordFile = mkOption {
type = types.str;
default = "";
description = "File that containts password";
};
};
}));
@ -88,7 +94,13 @@ in
type = types.str;
default = "";
description = "Additional command line parameters";
example = "-P mysecurepassword -l 192.168.1.10 -p 23";
example = "-l 192.168.1.10 -p 23";
};
passwordFile = mkOption {
type = types.str;
default = "";
description = "File that containts password";
};
};
@ -108,10 +120,10 @@ in
description = "iodine client - ${name}";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
script = "${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "-P $(cat \"${cfg.passwordFile}\")"} ${cfg.relay} ${cfg.server}";
serviceConfig = {
RestartSec = "30s";
Restart = "always";
ExecStart = "${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${cfg.relay} ${cfg.server}";
};
};
in
@ -124,7 +136,7 @@ in
description = "iodine, ip over dns server daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${cfg.server.ip} ${cfg.server.domain}";
script = "${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "-P $(cat \"${cfg.server.passwordFile}\")"} ${cfg.server.ip} ${cfg.server.domain}";
};
};

View File

@ -26,7 +26,7 @@ in {
wants = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.iwd}/bin/iwd";
serviceConfig.ExecStart = "${pkgs.iwd}/libexec/iwd";
};
};

View File

@ -80,7 +80,7 @@ in
pidfile = mkOption {
type = types.path;
default = "/tmp/murmurd.pid";
default = "/run/murmur/murmurd.pid";
description = "Path to PID file for Murmur daemon.";
};
@ -252,6 +252,7 @@ in
serviceConfig = {
Type = "forking";
RuntimeDirectory = "murmur";
PIDFile = cfg.pidfile;
Restart = "always";
User = "murmur";

View File

@ -250,6 +250,46 @@ let
Use imports or pkgs.lib.readFile if you don't want this data in your config file.
'';
};
dnssec = mkEnableOption "DNSSEC";
dnssecPolicy = {
algorithm = mkOption {
type = types.str;
default = "RSASHA256";
description = "Which algorithm to use for DNSSEC";
};
keyttl = mkOption {
type = types.str;
default = "1h";
description = "TTL for dnssec records";
};
coverage = mkOption {
type = types.str;
default = "1y";
description = ''
The length of time to ensure that keys will be correct; no action will be taken to create new keys to be activated after this time.
'';
};
zsk = mkOption {
type = keyPolicy;
default = { keySize = 2048;
prePublish = "1w";
postPublish = "1w";
rollPeriod = "1mo";
};
description = "Key policy for zone signing keys";
};
ksk = mkOption {
type = keyPolicy;
default = { keySize = 4096;
prePublish = "1mo";
postPublish = "1mo";
rollPeriod = "0";
};
description = "Key policy for key signing keys";
};
};
maxRefreshSecs = mkOption {
type = types.nullOr types.int;
@ -367,10 +407,61 @@ let
and stats_noreset.
'';
};
};
};
keyPolicy = types.submodule {
options = {
keySize = mkOption {
type = types.int;
description = "Key size in bits";
};
prePublish = mkOption {
type = types.str;
description = "How long in advance to publish new keys";
};
postPublish = mkOption {
type = types.str;
description = "How long after deactivation to keep a key in the zone";
};
rollPeriod = mkOption {
type = types.str;
description = "How frequently to change keys";
};
};
};
dnssecZones = (filterAttrs (n: v: if v ? dnssec then v.dnssec else false) zoneConfigs);
dnssec = length (attrNames dnssecZones) != 0;
signZones = optionalString dnssec ''
mkdir -p ${stateDir}/dnssec
chown ${username}:${username} ${stateDir}/dnssec
chmod 0600 ${stateDir}/dnssec
${concatStrings (mapAttrsToList signZone dnssecZones)}
'';
signZone = name: zone: ''
${pkgs.bind}/bin/dnssec-keymgr -g ${pkgs.bind}/bin/dnssec-keygen -s ${pkgs.bind}/bin/dnssec-settime -K ${stateDir}/dnssec -c ${policyFile name zone.dnssecPolicy} ${name}
${pkgs.bind}/bin/dnssec-signzone -S -K ${stateDir}/dnssec -o ${name} -O full -N date ${stateDir}/zones/${name}
${nsdPkg}/sbin/nsd-checkzone ${name} ${stateDir}/zones/${name}.signed && mv -v ${stateDir}/zones/${name}.signed ${stateDir}/zones/${name}
'';
policyFile = name: policy: pkgs.writeText "${name}.policy" ''
zone ${name} {
algorithm ${policy.algorithm};
key-size zsk ${toString policy.zsk.keySize};
key-size ksk ${toString policy.ksk.keySize};
keyttl ${policy.keyttl};
pre-publish zsk ${policy.zsk.prePublish};
pre-publish ksk ${policy.ksk.prePublish};
post-publish zsk ${policy.zsk.postPublish};
post-publish ksk ${policy.ksk.postPublish};
roll-period zsk ${policy.zsk.rollPeriod};
roll-period ksk ${policy.ksk.rollPeriod};
coverage ${policy.coverage};
};
'';
in
{
# options are ordered alphanumerically
@ -380,6 +471,14 @@ in
bind8Stats = mkEnableOption "BIND8 like statistics";
dnssecInterval = mkOption {
type = types.str;
default = "1h";
description = ''
How often to check whether dnssec key rollover is required
'';
};
extraConfig = mkOption {
type = types.str;
default = "";
@ -741,7 +840,6 @@ in
};
zones = mkOption {
type = types.attrsOf zoneOptions;
default = {};
@ -785,7 +883,6 @@ in
serverGroup1.
'';
};
};
config = mkIf cfg.enable {
@ -832,9 +929,9 @@ in
mkdir -m 0700 -p "${stateDir}/var"
cat > "${stateDir}/don't touch anything in here" << EOF
Everything in this directory except NSD's state in var is
automatically generated and will be purged and redeployed
by the nsd.service pre-start script.
Everything in this directory except NSD's state in var and dnssec
is automatically generated and will be purged and redeployed by
the nsd.service pre-start script.
EOF
chown ${username}:${username} -R "${stateDir}/private"
@ -848,6 +945,34 @@ in
'';
};
nixpkgs.config = mkIf dnssec {
bind.enablePython = true;
};
systemd.timers."nsd-dnssec" = mkIf dnssec {
description = "Automatic DNSSEC key rollover";
wantedBy = [ "nsd.service" ];
timerConfig = {
OnActiveSec = cfg.dnssecInterval;
OnUnitActiveSec = cfg.dnssecInterval;
};
};
systemd.services."nsd-dnssec" = mkIf dnssec {
description = "DNSSEC key rollover";
wantedBy = [ "nsd.service" ];
before = [ "nsd.service" ];
script = signZones;
postStop = ''
${pkgs.systemd}/bin/systemctl kill -s SIGHUP nsd.service
'';
};
};
meta.maintainers = with lib.maintainers; [ hrdinka ];

View File

@ -65,7 +65,7 @@ let
path = [ pkgs.iptables pkgs.iproute pkgs.nettools ];
serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --config ${configFile}";
serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --suppress-timestamps --config ${configFile}";
serviceConfig.Restart = "always";
serviceConfig.Type = "notify";
};

View File

@ -301,6 +301,18 @@ in
default = "/var/lib/prosody";
};
user = mkOption {
type = types.str;
default = "prosody";
description = "User account under which prosody runs.";
};
group = mkOption {
type = types.str;
default = "prosody";
description = "Group account under which prosody runs.";
};
allowRegistration = mkOption {
type = types.bool;
default = false;
@ -427,7 +439,7 @@ in
environment.etc."prosody/prosody.cfg.lua".text = ''
pidfile = "${cfg.dataDir}/prosody.pid"
pidfile = "/run/prosody/prosody.pid"
log = "*syslog"
@ -475,15 +487,15 @@ in
'') cfg.virtualHosts) }
'';
users.extraUsers.prosody = {
users.extraUsers.prosody = mkIf (cfg.user == "prosody") {
uid = config.ids.uids.prosody;
description = "Prosody user";
createHome = true;
group = "prosody";
inherit (cfg) group;
home = "${cfg.dataDir}";
};
users.extraGroups.prosody = {
users.extraGroups.prosody = mkIf (cfg.group == "prosody") {
gid = config.ids.gids.prosody;
};
@ -494,9 +506,11 @@ in
wantedBy = [ "multi-user.target" ];
restartTriggers = [ config.environment.etc."prosody/prosody.cfg.lua".source ];
serviceConfig = {
User = "prosody";
User = cfg.user;
Group = cfg.group;
Type = "forking";
PIDFile = "${cfg.dataDir}/prosody.pid";
RuntimeDirectory = [ "prosody" ];
PIDFile = "/run/prosody/prosody.pid";
ExecStart = "${cfg.package}/bin/prosodyctl start";
};
};

View File

@ -133,7 +133,7 @@ in
users.groups = {
quagga = {};
# Members of the quaggavty group can use vtysh to inspect the Quagga daemons
quaggavty = {};
quaggavty = { members = [ "quagga" ]; };
};
systemd.services =

View File

@ -0,0 +1,112 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.shadowsocks;
opts = {
server = cfg.localAddress;
server_port = cfg.port;
method = cfg.encryptionMethod;
mode = cfg.mode;
user = "nobody";
fast_open = true;
} // optionalAttrs (cfg.password != null) { password = cfg.password; };
configFile = pkgs.writeText "shadowsocks.json" (builtins.toJSON opts);
in
{
###### interface
options = {
services.shadowsocks = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to run shadowsocks-libev shadowsocks server.
'';
};
localAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = ''
Local address to which the server binds.
'';
};
port = mkOption {
type = types.int;
default = 8388;
description = ''
Port which the server uses.
'';
};
password = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Password for connecting clients.
'';
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Password file with a password for connecting clients.
'';
};
mode = mkOption {
type = types.enum [ "tcp_only" "tcp_and_udp" "udp_only" ];
default = "tcp_and_udp";
description = ''
Relay protocols.
'';
};
encryptionMethod = mkOption {
type = types.str;
default = "chacha20-ietf-poly1305";
description = ''
Encryption method. See <link xlink:href="https://github.com/shadowsocks/shadowsocks-org/wiki/AEAD-Ciphers"/>.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
assertions = singleton
{ assertion = cfg.password == null || cfg.passwordFile == null;
message = "Cannot use both password and passwordFile for shadowsocks-libev";
};
systemd.services.shadowsocks-libev = {
description = "shadowsocks-libev Daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.shadowsocks-libev ] ++ optional (cfg.passwordFile != null) pkgs.jq;
serviceConfig.PrivateTmp = true;
script = ''
${optionalString (cfg.passwordFile != null) ''
cat ${configFile} | jq --arg password "$(cat "${cfg.passwordFile}")" '. + { password: $password }' > /tmp/shadowsocks.json
''}
exec ss-server -c ${if cfg.passwordFile != null then "/tmp/shadowsocks.json" else configFile}
'';
};
};
}

View File

@ -213,6 +213,65 @@ in
description = "Files from which authorized keys are read.";
};
kexAlgorithms = mkOption {
type = types.listOf types.str;
default = [
"curve25519-sha256@libssh.org"
"diffie-hellman-group-exchange-sha256"
];
description = ''
Allowed key exchange algorithms
</para>
<para>
Defaults to recommended settings from both
<link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html" />
and
<link xlink:href="https://wiki.mozilla.org/Security/Guidelines/OpenSSH#Modern_.28OpenSSH_6.7.2B.29" />
'';
};
ciphers = mkOption {
type = types.listOf types.str;
default = [
"chacha20-poly1305@openssh.com"
"aes256-gcm@openssh.com"
"aes128-gcm@openssh.com"
"aes256-ctr"
"aes192-ctr"
"aes128-ctr"
];
description = ''
Allowed ciphers
</para>
<para>
Defaults to recommended settings from both
<link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html" />
and
<link xlink:href="https://wiki.mozilla.org/Security/Guidelines/OpenSSH#Modern_.28OpenSSH_6.7.2B.29" />
'';
};
macs = mkOption {
type = types.listOf types.str;
default = [
"hmac-sha2-512-etm@openssh.com"
"hmac-sha2-256-etm@openssh.com"
"umac-128-etm@openssh.com"
"hmac-sha2-512"
"hmac-sha2-256"
"umac-128@openssh.com"
];
description = ''
Allowed MACs
</para>
<para>
Defaults to recommended settings from both
<link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html" />
and
<link xlink:href="https://wiki.mozilla.org/Security/Guidelines/OpenSSH#Modern_.28OpenSSH_6.7.2B.29" />
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
@ -363,14 +422,9 @@ in
HostKey ${k.path}
'')}
### Recommended settings from both:
# https://stribika.github.io/2015/01/04/secure-secure-shell.html
# and
# https://wiki.mozilla.org/Security/Guidelines/OpenSSH#Modern_.28OpenSSH_6.7.2B.29
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
KexAlgorithms ${concatStringsSep "," cfg.kexAlgorithms}
Ciphers ${concatStringsSep "," cfg.ciphers}
MACs ${concatStringsSep "," cfg.macs}
# LogLevel VERBOSE logs user's key fingerprint on login.
# Needed to have a clear audit track of which key was used to log in.

View File

@ -0,0 +1,82 @@
{ config, lib, pkgs, ... }:
with lib;
with (import ./param-lib.nix lib);
let
cfg = config.services.strongswan-swanctl;
swanctlParams = import ./swanctl-params.nix lib;
in {
options.services.strongswan-swanctl = {
enable = mkEnableOption "strongswan-swanctl service";
package = mkOption {
type = types.package;
default = pkgs.strongswan;
defaultText = "pkgs.strongswan";
description = ''
The strongswan derivation to use.
'';
};
strongswan.extraConfig = mkOption {
type = types.str;
default = "";
description = ''
Contents of the <literal>strongswan.conf</literal> file.
'';
};
swanctl = paramsToOptions swanctlParams;
};
config = mkIf cfg.enable {
assertions = [
{ assertion = !config.services.strongswan.enable;
message = "cannot enable both services.strongswan and services.strongswan-swanctl. Choose either one.";
}
];
environment.etc."swanctl/swanctl.conf".text =
paramsToConf cfg.swanctl swanctlParams;
# The swanctl command complains when the following directories don't exist:
# See: https://wiki.strongswan.org/projects/strongswan/wiki/Swanctldirectory
system.activationScripts.strongswan-swanctl-etc = stringAfter ["etc"] ''
mkdir -p '/etc/swanctl/x509' # Trusted X.509 end entity certificates
mkdir -p '/etc/swanctl/x509ca' # Trusted X.509 Certificate Authority certificates
mkdir -p '/etc/swanctl/x509ocsp'
mkdir -p '/etc/swanctl/x509aa' # Trusted X.509 Attribute Authority certificates
mkdir -p '/etc/swanctl/x509ac' # Attribute Certificates
mkdir -p '/etc/swanctl/x509crl' # Certificate Revocation Lists
mkdir -p '/etc/swanctl/pubkey' # Raw public keys
mkdir -p '/etc/swanctl/private' # Private keys in any format
mkdir -p '/etc/swanctl/rsa' # PKCS#1 encoded RSA private keys
mkdir -p '/etc/swanctl/ecdsa' # Plain ECDSA private keys
mkdir -p '/etc/swanctl/bliss'
mkdir -p '/etc/swanctl/pkcs8' # PKCS#8 encoded private keys of any type
mkdir -p '/etc/swanctl/pkcs12' # PKCS#12 containers
'';
systemd.services.strongswan-swanctl = {
description = "strongSwan IPsec IKEv1/IKEv2 daemon using swanctl";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" "keys.target" ];
wants = [ "keys.target" ];
path = with pkgs; [ kmod iproute iptables utillinux ];
environment.STRONGSWAN_CONF = pkgs.writeTextFile {
name = "strongswan.conf";
text = cfg.strongswan.extraConfig;
};
restartTriggers = [ config.environment.etc."swanctl/swanctl.conf".source ];
serviceConfig = {
ExecStart = "${cfg.package}/sbin/charon-systemd";
Type = "notify";
ExecStartPost = "${cfg.package}/sbin/swanctl --load-all --noprompt";
ExecReload = "${cfg.package}/sbin/swanctl --reload";
Restart = "on-abnormal";
};
};
};
}

View File

@ -0,0 +1,162 @@
# In the following context a parameter is an attribute set that
# contains a NixOS option and a render function. It also contains the
# attribute: '_type = "param"' so we can distinguish it from other
# sets.
#
# The render function is used to convert the value of the option to a
# snippet of strongswan.conf. Most parameters simply render their
# value to a string. For example, take the following parameter:
#
# threads = mkIntParam 10 "Threads to use for request handling.";
#
# When a users defines the corresponding option as for example:
#
# services.strongswan-swanctl.strongswan.threads = 32;
#
# It will get rendered to the following snippet in strongswan.conf:
#
# threads = 32
#
# Some parameters however need to be able to change the attribute
# name. For example, take the following parameter:
#
# id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") "...";
#
# A user can define the corresponding option as for example:
#
# id = {
# "foo" = "bar";
# "baz" = "qux";
# };
#
# This will get rendered to the following snippet:
#
# foo-id = bar
# baz-id = qux
#
# For this reason the render function is not simply a function from
# value -> string but a function from a value to an attribute set:
# { "${name}" = string }. This allows parameters to change the attribute
# name like in the previous example.
lib :
with lib;
with (import ./param-lib.nix lib);
rec {
mkParamOfType = type : strongswanDefault : description : {
_type = "param";
option = mkOption {
type = types.nullOr type;
default = null;
description = documentDefault description strongswanDefault;
};
render = single toString;
};
documentDefault = description : strongswanDefault :
if isNull strongswanDefault
then description
else description + ''
</para><para>
StrongSwan default: <literal><![CDATA[${builtins.toJSON strongswanDefault}]]></literal>
'';
single = f: name: value: { "${name}" = f value; };
mkStrParam = mkParamOfType types.str;
mkOptionalStrParam = mkStrParam null;
mkEnumParam = values : mkParamOfType (types.enum values);
mkIntParam = mkParamOfType types.int;
mkOptionalIntParam = mkIntParam null;
# We should have floats in Nix...
mkFloatParam = mkStrParam;
# TODO: Check for hex format:
mkHexParam = mkStrParam;
mkOptionalHexParam = mkOptionalStrParam;
# TODO: Check for duration format:
mkDurationParam = mkStrParam;
mkOptionalDurationParam = mkOptionalStrParam;
mkYesNoParam = strongswanDefault : description : {
_type = "param";
option = mkOption {
type = types.nullOr types.bool;
default = null;
description = documentDefault description strongswanDefault;
};
render = single (b: if b then "yes" else "no");
};
yes = true;
no = false;
mkSpaceSepListParam = mkSepListParam " ";
mkCommaSepListParam = mkSepListParam ",";
mkSepListParam = sep : strongswanDefault : description : {
_type = "param";
option = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
description = documentDefault description strongswanDefault;
};
render = single (value: concatStringsSep sep value);
};
mkAttrsOfParams = params :
mkAttrsOf params (types.submodule {options = paramsToOptions params;});
mkAttrsOfParam = param :
mkAttrsOf param param.option.type;
mkAttrsOf = param : option : description : {
_type = "param";
option = mkOption {
type = types.attrsOf option;
default = {};
inherit description;
};
render = single (attrs:
(paramsToRenderedStrings attrs
(mapAttrs (_n: _v: param) attrs)));
};
mkPrefixedAttrsOfParams = params :
mkPrefixedAttrsOf params (types.submodule {options = paramsToOptions params;});
mkPrefixedAttrsOfParam = param :
mkPrefixedAttrsOf param param.option.type;
mkPrefixedAttrsOf = p : option : description : {
_type = "param";
option = mkOption {
type = types.attrsOf option;
default = {};
inherit description;
};
render = prefix: attrs:
let prefixedAttrs = mapAttrs' (name: nameValuePair "${prefix}-${name}") attrs;
in paramsToRenderedStrings prefixedAttrs
(mapAttrs (_n: _v: p) prefixedAttrs);
};
mkPostfixedAttrsOfParams = params : description : {
_type = "param";
option = mkOption {
type = types.attrsOf (types.submodule {options = paramsToOptions params;});
default = {};
inherit description;
};
render = postfix: attrs:
let postfixedAttrs = mapAttrs' (name: nameValuePair "${name}-${postfix}") attrs;
in paramsToRenderedStrings postfixedAttrs
(mapAttrs (_n: _v: params) postfixedAttrs);
};
}

View File

@ -0,0 +1,82 @@
lib :
with lib;
rec {
paramsToConf = cfg : ps : mkConf 0 (paramsToRenderedStrings cfg ps);
# mkConf takes an indentation level (which usually starts at 0) and a nested
# attribute set of strings and will render that set to a strongswan.conf style
# configuration format. For example:
#
# mkConf 0 {a = "1"; b = { c = { "foo" = "2"; "bar" = "3"; }; d = "4";};} => ''
# a = 1
# b {
# c {
# foo = 2
# bar = 3
# }
# d = 4
# }''
mkConf = indent : ps :
concatMapStringsSep "\n"
(name:
let value = ps."${name}";
indentation = replicate indent " ";
in
indentation + (
if isAttrs value
then "${name} {\n" +
mkConf (indent + 2) value + "\n" +
indentation + "}"
else "${name} = ${value}"
)
)
(attrNames ps);
replicate = n : c : concatStrings (builtins.genList (_x : c) n);
# `paramsToRenderedStrings cfg ps` converts the NixOS configuration `cfg`
# (typically the "config" argument of a NixOS module) and the set of
# parameters `ps` (an attribute set where the values are constructed using the
# parameter constructors in ./param-constructors.nix) to a nested attribute
# set of strings (rendered parameters).
paramsToRenderedStrings = cfg : ps :
filterEmptySets (
(mapParamsRecursive (path: name: param:
let value = attrByPath path null cfg;
in optionalAttrs (!isNull value) (param.render name value)
) ps));
filterEmptySets = set : filterAttrs (n: v: !(isNull v)) (mapAttrs (name: value:
if isAttrs value
then let value' = filterEmptySets value;
in if value' == {}
then null
else value'
else value
) set);
# Recursively map over every parameter in the given attribute set.
mapParamsRecursive = mapAttrsRecursiveCond' (as: (!(as ? "_type" && as._type == "param")));
mapAttrsRecursiveCond' = cond: f: set:
let
recurse = path: set:
let
g =
name: value:
if isAttrs value && cond value
then { "${name}" = recurse (path ++ [name]) value; }
else f (path ++ [name]) name value;
in mapAttrs'' g set;
in recurse [] set;
mapAttrs'' = f: set:
foldl' (a: b: a // b) {} (map (attr: f attr set.${attr}) (attrNames set));
# Extract the options from the given set of parameters.
paramsToOptions = ps :
mapParamsRecursive (_path: name: param: { "${name}" = param.option; }) ps;
}

File diff suppressed because it is too large Load Diff

View File

@ -4,22 +4,22 @@ let
cfg = config.services.unifi;
stateDir = "/var/lib/unifi";
cmd = ''
@${pkgs.jre}/bin/java java \
@${cfg.jrePackage}/bin/java java \
${optionalString (cfg.initialJavaHeapSize != null) "-Xms${(toString cfg.initialJavaHeapSize)}m"} \
${optionalString (cfg.maximumJavaHeapSize != null) "-Xmx${(toString cfg.maximumJavaHeapSize)}m"} \
-jar ${stateDir}/lib/ace.jar
'';
mountPoints = [
{
what = "${pkgs.unifi}/dl";
what = "${cfg.unifiPackage}/dl";
where = "${stateDir}/dl";
}
{
what = "${pkgs.unifi}/lib";
what = "${cfg.unifiPackage}/lib";
where = "${stateDir}/lib";
}
{
what = "${pkgs.mongodb}/bin";
what = "${cfg.mongodbPackage}/bin";
where = "${stateDir}/bin";
}
{
@ -41,6 +41,33 @@ in
'';
};
services.unifi.jrePackage = mkOption {
type = types.package;
default = pkgs.jre8;
defaultText = "pkgs.jre8";
description = ''
The JRE package to use. Check the release notes to ensure it is supported.
'';
};
services.unifi.unifiPackage = mkOption {
type = types.package;
default = pkgs.unifiLTS;
defaultText = "pkgs.unifiLTS";
description = ''
The unifi package to use.
'';
};
services.unifi.mongodbPackage = mkOption {
type = types.package;
default = pkgs.mongodb;
defaultText = "pkgs.mongodb";
description = ''
The mongodb package to use.
'';
};
services.unifi.dataDir = mkOption {
type = types.str;
default = "${stateDir}/data";
@ -137,7 +164,7 @@ in
rm -rf "${stateDir}/webapps"
mkdir -p "${stateDir}/webapps"
chown unifi "${stateDir}/webapps"
ln -s "${pkgs.unifi}/webapps/ROOT" "${stateDir}/webapps/ROOT"
ln -s "${cfg.unifiPackage}/webapps/ROOT" "${stateDir}/webapps/ROOT"
'';
postStop = ''

View File

@ -53,30 +53,30 @@ let
};
preSetup = mkOption {
example = literalExample [''
example = literalExample ''
${pkgs.iproute}/bin/ip netns add foo
''];
default = [];
type = with types; listOf str;
'';
default = "";
type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines;
description = ''
A list of commands called at the start of the interface setup.
Commands called at the start of the interface setup.
'';
};
postSetup = mkOption {
example = literalExample [''
${pkgs.bash} -c 'printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0'
''];
default = [];
type = with types; listOf str;
description = "A list of commands called at the end of the interface setup.";
example = literalExample ''
printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0
'';
default = "";
type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines;
description = "Commands called at the end of the interface setup.";
};
postShutdown = mkOption {
example = literalExample ["${pkgs.openresolv}/bin/resolvconf -d wg0"];
default = [];
type = with types; listOf str;
description = "A list of commands called after shutting down the interface.";
example = literalExample "${pkgs.openresolv}/bin/resolvconf -d wg0";
default = "";
type = with types; coercedTo (listOf str) (concatStringsSep "\n") lines;
description = "Commands called after shutting down the interface.";
};
table = mkOption {
@ -182,9 +182,6 @@ let
};
ipCommand = "${pkgs.iproute}/bin/ip";
wgCommand = "${pkgs.wireguard}/bin/wg";
generateUnit = name: values:
# exactly one way to specify the private key must be set
assert (values.privateKey != null) != (values.privateKeyFile != null);
@ -196,49 +193,53 @@ let
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.DEVICE = name;
path = with pkgs; [ kmod iproute wireguard ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = flatten([
values.preSetup
};
"-${ipCommand} link del dev ${name}"
"${ipCommand} link add dev ${name} type wireguard"
script = ''
modprobe wireguard
(map (ip:
"${ipCommand} address add ${ip} dev ${name}"
) values.ips)
${values.preSetup}
("${wgCommand} set ${name} private-key ${privKey}" +
optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}")
ip link add dev ${name} type wireguard
(map (peer:
${concatMapStringsSep "\n" (ip:
"ip address add ${ip} dev ${name}"
) values.ips}
wg set ${name} private-key ${privKey} ${
optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}"}
${concatMapStringsSep "\n" (peer:
assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set
let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile;
in
"${wgCommand} set ${name} peer ${peer.publicKey}" +
optionalString (psk != null) " preshared-key ${psk}" +
optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" +
optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" +
optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"
) values.peers)
"wg set ${name} peer ${peer.publicKey}" +
optionalString (psk != null) " preshared-key ${psk}" +
optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" +
optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" +
optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"
) values.peers}
"${ipCommand} link set up dev ${name}"
ip link set up dev ${name}
(optionals (values.allowedIPsAsRoutes != false) (map (peer:
(map (allowedIP:
"${ipCommand} route replace ${allowedIP} dev ${name} table ${values.table}"
) peer.allowedIPs)
) values.peers))
${optionalString (values.allowedIPsAsRoutes != false) (concatStringsSep "\n" (concatMap (peer:
(map (allowedIP:
"ip route replace ${allowedIP} dev ${name} table ${values.table}"
) peer.allowedIPs)
) values.peers))}
values.postSetup
]);
ExecStop = flatten([
"${ipCommand} link del dev ${name}"
values.postShutdown
]);
};
${values.postSetup}
'';
preStop = ''
ip link del dev ${name}
${values.postShutdown}
'';
};
in

View File

@ -83,6 +83,8 @@ let
WebInterface ${if cfg.webInterface then "Yes" else "No"}
LogLevel ${cfg.logLevel}
${cfg.extraConf}
'';
@ -165,6 +167,15 @@ in
'';
};
logLevel = mkOption {
type = types.str;
default = "info";
example = "debug";
description = ''
Specifies the cupsd logging verbosity.
'';
};
extraFilesConf = mkOption {
type = types.lines;
default = "";
@ -180,7 +191,7 @@ in
example =
''
BrowsePoll cups.example.com
LogLevel debug
MaxCopies 42
'';
description = ''
Extra contents of the configuration file of the CUPS daemon
@ -345,8 +356,6 @@ in
services.printing.extraConf =
''
LogLevel info
DefaultAuthType Basic
<Location />

View File

@ -32,8 +32,11 @@ let
(if es5 then (pkgs.writeTextDir "log4j2.properties" cfg.logging)
else (pkgs.writeTextDir "logging.yml" cfg.logging))
];
# Elasticsearch 5.x won't start when the scripts directory does not exist
postBuild = if es5 then "${pkgs.coreutils}/bin/mkdir -p $out/scripts" else "";
postBuild = concatStringsSep "\n" (concatLists [
# Elasticsearch 5.x won't start when the scripts directory does not exist
(optional es5 "${pkgs.coreutils}/bin/mkdir -p $out/scripts")
(optional es6 "ln -s ${cfg.package}/config/jvm.options $out/jvm.options")
]);
};
esPlugins = pkgs.buildEnv {

View File

@ -6,70 +6,81 @@ with lib;
let
cfg = config.services.oauth2_proxy;
# Use like:
# repeatedArgs (arg: "--arg=${arg}") args
repeatedArgs = concatMapStringsSep " ";
# oauth2_proxy provides many options that are only relevant if you are using
# a certain provider. This set maps from provider name to a function that
# takes the configuration and returns a string that can be inserted into the
# command-line to launch oauth2_proxy.
providerSpecificOptions = {
azure = cfg: ''
--azure-tenant=${cfg.azure.tenant} \
--resource=${cfg.azure.resource} \
'';
azure = cfg: {
azure.tenant = cfg.azure.tenant;
resource = cfg.azure.resource;
};
github = cfg: ''
${optionalString (!isNull cfg.github.org) "--github-org=${cfg.github.org}"} \
${optionalString (!isNull cfg.github.team) "--github-org=${cfg.github.team}"} \
'';
github = cfg: { github = {
inherit (cfg.github) org team;
}; };
google = cfg: ''
--google-admin-email=${cfg.google.adminEmail} \
--google-service-account=${cfg.google.serviceAccountJSON} \
${repeatedArgs (group: "--google-group=${group}") cfg.google.groups} \
'';
google = cfg: { google = with cfg.google; optionalAttrs (groups != []) {
admin-email = adminEmail;
service-account = serviceAccountJSON;
group = groups;
}; };
};
authenticatedEmailsFile = pkgs.writeText "authenticated-emails" cfg.email.addresses;
getProviderOptions = cfg: provider: providerSpecificOptions.${provider} or (_: "") cfg;
getProviderOptions = cfg: provider: providerSpecificOptions.${provider} or (_: {}) cfg;
mkCommandLine = cfg: ''
--provider='${cfg.provider}' \
${optionalString (!isNull cfg.email.addresses) "--authenticated-emails-file='${authenticatedEmailsFile}'"} \
--approval-prompt='${cfg.approvalPrompt}' \
${optionalString (cfg.passBasicAuth && !isNull cfg.basicAuthPassword) "--basic-auth-password='${cfg.basicAuthPassword}'"} \
--client-id='${cfg.clientID}' \
--client-secret='${cfg.clientSecret}' \
${optionalString (!isNull cfg.cookie.domain) "--cookie-domain='${cfg.cookie.domain}'"} \
--cookie-expire='${cfg.cookie.expire}' \
--cookie-httponly=${boolToString cfg.cookie.httpOnly} \
--cookie-name='${cfg.cookie.name}' \
--cookie-secret='${cfg.cookie.secret}' \
--cookie-secure=${boolToString cfg.cookie.secure} \
${optionalString (!isNull cfg.cookie.refresh) "--cookie-refresh='${cfg.cookie.refresh}'"} \
${optionalString (!isNull cfg.customTemplatesDir) "--custom-templates-dir='${cfg.customTemplatesDir}'"} \
${repeatedArgs (x: "--email-domain='${x}'") cfg.email.domains} \
--http-address='${cfg.httpAddress}' \
${optionalString (!isNull cfg.htpasswd.file) "--htpasswd-file='${cfg.htpasswd.file}' --display-htpasswd-form=${boolToString cfg.htpasswd.displayForm}"} \
${optionalString (!isNull cfg.loginURL) "--login-url='${cfg.loginURL}'"} \
--pass-access-token=${boolToString cfg.passAccessToken} \
--pass-basic-auth=${boolToString cfg.passBasicAuth} \
--pass-host-header=${boolToString cfg.passHostHeader} \
--proxy-prefix='${cfg.proxyPrefix}' \
${optionalString (!isNull cfg.profileURL) "--profile-url='${cfg.profileURL}'"} \
${optionalString (!isNull cfg.redeemURL) "--redeem-url='${cfg.redeemURL}'"} \
${optionalString (!isNull cfg.redirectURL) "--redirect-url='${cfg.redirectURL}'"} \
--request-logging=${boolToString cfg.requestLogging} \
${optionalString (!isNull cfg.scope) "--scope='${cfg.scope}'"} \
${repeatedArgs (x: "--skip-auth-regex='${x}'") cfg.skipAuthRegexes} \
${optionalString (!isNull cfg.signatureKey) "--signature-key='${cfg.signatureKey}'"} \
--upstream='${cfg.upstream}' \
${optionalString (!isNull cfg.validateURL) "--validate-url='${cfg.validateURL}'"} \
${optionalString cfg.tls.enable "--tls-cert='${cfg.tls.certificate}' --tls-key='${cfg.tls.key}' --https-address='${cfg.tls.httpsAddress}'"} \
'' + getProviderOptions cfg cfg.provider;
allConfig = with cfg; {
inherit (cfg) provider scope upstream;
approval-prompt = approvalPrompt;
basic-auth-password = basicAuthPassword;
client-id = clientID;
client-secret = clientSecret;
custom-templates-dir = customTemplatesDir;
email-domain = email.domains;
http-address = httpAddress;
login-url = loginURL;
pass-access-token = passAccessToken;
pass-basic-auth = passBasicAuth;
pass-host-header = passHostHeader;
proxy-prefix = proxyPrefix;
profile-url = profileURL;
redeem-url = redeemURL;
redirect-url = redirectURL;
request-logging = requestLogging;
skip-auth-regex = skipAuthRegexes;
signature-key = signatureKey;
validate-url = validateURL;
htpasswd-file = htpasswd.file;
cookie = {
inherit (cookie) domain secure expire name secret refresh;
httponly = cookie.httpOnly;
};
set-xauthrequest = setXauthrequest;
} // lib.optionalAttrs (!isNull cfg.email.addresses) {
authenticated-emails-file = authenticatedEmailsFile;
} // lib.optionalAttrs (cfg.passBasicAuth) {
basic-auth-password = cfg.basicAuthPassword;
} // lib.optionalAttrs (!isNull cfg.htpasswd.file) {
display-htpasswd-file = cfg.htpasswd.displayForm;
} // lib.optionalAttrs tls.enable {
tls-cert = tls.certificate;
tls-key = tls.key;
https-address = tls.httpsAddress;
} // (getProviderOptions cfg cfg.provider) // cfg.extraConfig;
mapConfig = key: attr:
if (!isNull attr && attr != []) then (
if (builtins.typeOf attr) == "set" then concatStringsSep " "
(mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
if (builtins.typeOf attr) == "list" then concatMapStringsSep " " (mapConfig key) attr else
if (builtins.typeOf attr) == "bool" then "--${key}=${boolToString attr}" else
if (builtins.typeOf attr) == "string" then "--${key}='${attr}'" else
"--${key}=${toString attr}")
else "";
configString = concatStringsSep " " (mapAttrsToList mapConfig allConfig);
in
{
options.services.oauth2_proxy = {
@ -110,7 +121,7 @@ in
};
clientID = mkOption {
type = types.str;
type = types.nullOr types.str;
description = ''
The OAuth Client ID.
'';
@ -118,7 +129,7 @@ in
};
clientSecret = mkOption {
type = types.str;
type = types.nullOr types.str;
description = ''
The OAuth Client Secret.
'';
@ -272,7 +283,8 @@ in
####################################################
# UPSTREAM Configuration
upstream = mkOption {
type = types.commas;
type = with types; coercedTo string (x: [x]) (listOf string);
default = [];
description = ''
The http url(s) of the upstream endpoint or <literal>file://</literal>
paths for static files. Routing is based on the path.
@ -365,7 +377,7 @@ in
};
secret = mkOption {
type = types.str;
type = types.nullOr types.str;
description = ''
The seed string for secure cookies.
'';
@ -494,10 +506,43 @@ in
'';
};
setXauthrequest = mkOption {
type = types.nullOr types.bool;
default = false;
description = ''
Set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode). Setting this to 'null' means using the upstream default (false).
'';
};
extraConfig = mkOption {
default = {};
description = ''
Extra config to pass to oauth2_proxy.
'';
};
keyFile = mkOption {
type = types.nullOr types.string;
default = null;
description = ''
oauth2_proxy allows passing sensitive configuration via environment variables.
Make a file that contains lines like
OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
and specify the path here.
'';
example = "/run/keys/oauth2_proxy";
};
};
config = mkIf cfg.enable {
services.oauth2_proxy = mkIf (!isNull cfg.keyFile) {
clientID = mkDefault null;
clientSecret = mkDefault null;
cookie.secret = mkDefault null;
};
users.extraUsers.oauth2_proxy = {
description = "OAuth2 Proxy";
};
@ -511,7 +556,8 @@ in
serviceConfig = {
User = "oauth2_proxy";
Restart = "always";
ExecStart = "${cfg.package.bin}/bin/oauth2_proxy ${mkCommandLine cfg}";
ExecStart = "${cfg.package.bin}/bin/oauth2_proxy ${configString}";
EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
};
};

View File

@ -703,14 +703,10 @@ in
after = [ "network.target" ];
restartTriggers = [ torRcFile ];
# Translated from the upstream contrib/dist/tor.service.in
preStart = ''
install -o tor -g tor -d ${torDirectory}/onion ${torRunDirectory}
${pkgs.tor}/bin/tor -f ${torRcFile} --verify-config
'';
serviceConfig =
{ Type = "simple";
# Translated from the upstream contrib/dist/tor.service.in
ExecStartPre = "${pkgs.tor}/bin/tor -f ${torRcFile} --verify-config";
ExecStart = "${pkgs.tor}/bin/tor -f ${torRcFile} --RunAsDaemon 0";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
KillSignal = "SIGINT";
@ -725,6 +721,8 @@ in
# DeviceAllow /dev/urandom r
# .. but we can't specify DeviceAllow multiple times. 'closed'
# is close enough.
RuntimeDirectory = "tor";
StateDirectory = [ "tor" "tor/onion" ];
PrivateTmp = "yes";
DevicePolicy = "closed";
InaccessibleDirectories = "/home";

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