Merge remote-tracking branch 'channels/nixpkgs-unstable' into tbs
This commit is contained in:
commit
56b1a13ea9
@ -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
1
.github/CODEOWNERS
vendored
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@ -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 <<filename>nixpkgs/pkgs/build-support/setup-hooks/multiple-outputs.sh</filename>>; 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 – a default output name is defined, falling back to other possibilities if the output isn't defined.</para>
|
||||
|
||||
@ -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
|
||||
|
||||
184
lib/debug.nix
184
lib/debug.nix
@ -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
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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})";
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 ];
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -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>";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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";
|
||||
};
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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>
|
||||
|
||||
59
nixos/doc/manual/development/importing-modules.xml
Normal file
59
nixos/doc/manual/development/importing-modules.xml
Normal 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>
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 it’s 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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_);
|
||||
};
|
||||
};
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -214,6 +214,8 @@ in {
|
||||
(mkIf cfg.enable {
|
||||
environment.systemPackages = [ overriddenPackage ];
|
||||
|
||||
sound.enable = true;
|
||||
|
||||
environment.etc = [
|
||||
{ target = "asound.conf";
|
||||
source = alsaConf; }
|
||||
|
||||
@ -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.";
|
||||
};
|
||||
|
||||
@ -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.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@ -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.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@ -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 ];
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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" {} ''
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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; };
|
||||
|
||||
|
||||
@ -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" ];
|
||||
})
|
||||
|
||||
]);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
'';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -110,7 +110,7 @@ in
|
||||
};
|
||||
|
||||
enableCompletion = mkOption {
|
||||
default = false;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable Bash completion for all interactive bash shells.
|
||||
'';
|
||||
|
||||
@ -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" ])
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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"}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>.
|
||||
'';
|
||||
};
|
||||
|
||||
150
nixos/modules/services/backup/restic.nix
Normal file
150
nixos/modules/services/backup/restic.nix
Normal 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;
|
||||
};
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -17,7 +17,7 @@ let
|
||||
|
||||
hooksDir = let
|
||||
mkHookEntry = name: value: ''
|
||||
cat > $out/${name} <<EOF
|
||||
cat > $out/${name} <<'EOF'
|
||||
#! ${pkgs.runtimeShell}
|
||||
set -e
|
||||
${value}
|
||||
|
||||
360
nixos/modules/services/databases/foundationdb.nix
Normal file
360
nixos/modules/services/databases/foundationdb.nix
Normal 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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
280
nixos/modules/services/databases/foundationdb.xml
Normal file
280
nixos/modules/services/databases/foundationdb.xml
Normal 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>
|
||||
@ -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}" = {
|
||||
|
||||
@ -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
|
||||
'';
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = "";
|
||||
|
||||
@ -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";
|
||||
};
|
||||
};
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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";
|
||||
};
|
||||
|
||||
@ -213,7 +213,7 @@ in {
|
||||
PermissionsStartOnly = true;
|
||||
};
|
||||
preStart = ''
|
||||
mkdir -m 0700 -p ${cfg.workDir}
|
||||
mkdir -m 0701 -p ${cfg.workDir}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@ -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; };
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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; };
|
||||
|
||||
@ -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}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -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}")}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -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
|
||||
'';
|
||||
};
|
||||
|
||||
145
nixos/modules/services/networking/hans.nix
Normal file
145
nixos/modules/services/networking/hans.nix
Normal 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 ];
|
||||
}
|
||||
@ -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}";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ in {
|
||||
wants = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig.ExecStart = "${pkgs.iwd}/bin/iwd";
|
||||
serviceConfig.ExecStart = "${pkgs.iwd}/libexec/iwd";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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 ];
|
||||
|
||||
@ -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";
|
||||
};
|
||||
|
||||
@ -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";
|
||||
};
|
||||
};
|
||||
|
||||
@ -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 =
|
||||
|
||||
112
nixos/modules/services/networking/shadowsocks.nix
Normal file
112
nixos/modules/services/networking/shadowsocks.nix
Normal 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}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
@ -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
@ -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 = ''
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 />
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user