Merge branch 'master' into nixos-nixpkgs-pkgs-use-overlays
This commit is contained in:
commit
03fc1167e8
24
.github/CODEOWNERS
vendored
24
.github/CODEOWNERS
vendored
@ -12,7 +12,7 @@
|
||||
|
||||
# Libraries
|
||||
/lib @edolstra @nbp
|
||||
/lib/systems @nbp @ericson2314
|
||||
/lib/systems @nbp @ericson2314 @matthewbauer
|
||||
/lib/generators.nix @edolstra @nbp @Profpatsch
|
||||
/lib/debug.nix @edolstra @nbp @Profpatsch
|
||||
|
||||
@ -20,9 +20,11 @@
|
||||
/default.nix @nbp
|
||||
/pkgs/top-level/default.nix @nbp @Ericson2314
|
||||
/pkgs/top-level/impure.nix @nbp @Ericson2314
|
||||
/pkgs/top-level/stage.nix @nbp @Ericson2314
|
||||
/pkgs/stdenv/generic @Ericson2314
|
||||
/pkgs/stdenv/cross @Ericson2314
|
||||
/pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/stdenv/generic @Ericson2314 @matthewbauer
|
||||
/pkgs/stdenv/cross @Ericson2314 @matthewbauer
|
||||
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej
|
||||
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
|
||||
/pkgs/build-support/setup-hooks @Ericson2314
|
||||
@ -74,6 +76,14 @@
|
||||
/pkgs/stdenv/darwin @NixOS/darwin-maintainers
|
||||
/pkgs/os-specific/darwin @NixOS/darwin-maintainers
|
||||
|
||||
# C compilers
|
||||
/pkgs/development/compilers/gcc @matthewbauer
|
||||
/pkgs/development/compilers/llvm @matthewbauer
|
||||
|
||||
# Compatibility stuff
|
||||
/pkgs/top-level/unix-tools.nix @matthewbauer
|
||||
/pkgs/development/tools/xcbuild @matthewbauer
|
||||
|
||||
# Beam-related (Erlang, Elixir, LFE, etc)
|
||||
/pkgs/development/beam-modules @gleber
|
||||
/pkgs/development/interpreters/erlang @gleber
|
||||
@ -97,3 +107,9 @@
|
||||
/pkgs/desktops/plasma-5 @ttuegel
|
||||
/pkgs/development/libraries/kde-frameworks @ttuegel
|
||||
/pkgs/development/libraries/qt-5 @ttuegel
|
||||
|
||||
# PostgreSQL and related stuff
|
||||
/pkgs/servers/sql/postgresql @thoughtpolice
|
||||
/nixos/modules/services/databases/postgresql.xml @thoughtpolice
|
||||
/nixos/modules/services/databases/postgresql.nix @thoughtpolice
|
||||
/nixos/tests/postgresql.nix @thoughtpolice
|
||||
|
@ -842,9 +842,12 @@ src = fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nix";
|
||||
rev = "1f795f9f44607cc5bec70d1300150bfefcef2aae";
|
||||
sha256 = "04yri911rj9j19qqqn6m82266fl05pz98inasni0vxr1cf1gdgv9";
|
||||
sha256 = "1i2yxndxb6yc9l6c99pypbd92lfq5aac4klq7y2v93c9qvx2cgpc";
|
||||
}
|
||||
</programlisting>
|
||||
Find the value to put as <literal>sha256</literal> by running
|
||||
<literal>nix run -f '<nixpkgs>' nix-prefetch-github -c nix-prefetch-github --rev 1f795f9f44607cc5bec70d1300150bfefcef2aae NixOS nix</literal>
|
||||
or <literal>nix-prefetch-url --unpack https://github.com/NixOS/nix/archive/1f795f9f44607cc5bec70d1300150bfefcef2aae.tar.gz</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
@ -670,7 +670,7 @@ python3Packages.buildPythonApplication rec {
|
||||
sha256 = "035w8gqql36zlan0xjrzz9j4lh9hs0qrsgnbyw07qs7lnkvbdv9x";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3Packages; [ tornado_4 pythondaemon ];
|
||||
propagatedBuildInputs = with python3Packages; [ tornado_4 python-daemon ];
|
||||
|
||||
meta = with lib; {
|
||||
...
|
||||
|
@ -23,27 +23,54 @@ rec {
|
||||
|
||||
# -- TRACING --
|
||||
|
||||
/* Trace msg, but only if pred is true.
|
||||
/* Conditionally trace the supplied message, based on a predicate.
|
||||
|
||||
Type: traceIf :: bool -> string -> a -> a
|
||||
|
||||
Example:
|
||||
traceIf true "hello" 3
|
||||
trace: hello
|
||||
=> 3
|
||||
*/
|
||||
traceIf = pred: msg: x: if pred then trace msg x else x;
|
||||
traceIf =
|
||||
# Predicate to check
|
||||
pred:
|
||||
# Message that should be traced
|
||||
msg:
|
||||
# Value to return
|
||||
x: if pred then trace msg x else x;
|
||||
|
||||
/* Trace the value and also return it.
|
||||
/* Trace the supplied value after applying a function to it, and
|
||||
return the original value.
|
||||
|
||||
Type: traceValFn :: (a -> b) -> a -> a
|
||||
|
||||
Example:
|
||||
traceValFn (v: "mystring ${v}") "foo"
|
||||
trace: mystring foo
|
||||
=> "foo"
|
||||
*/
|
||||
traceValFn = f: x: trace (f x) x;
|
||||
traceValFn =
|
||||
# Function to apply
|
||||
f:
|
||||
# Value to trace and return
|
||||
x: trace (f x) x;
|
||||
|
||||
/* Trace the supplied value and return it.
|
||||
|
||||
Type: traceVal :: a -> a
|
||||
|
||||
Example:
|
||||
traceVal 42
|
||||
# trace: 42
|
||||
=> 42
|
||||
*/
|
||||
traceVal = traceValFn id;
|
||||
|
||||
/* `builtins.trace`, but the value is `builtins.deepSeq`ed first.
|
||||
|
||||
Type: traceSeq :: a -> b -> b
|
||||
|
||||
Example:
|
||||
trace { a.b.c = 3; } null
|
||||
trace: { a = <CODE>; }
|
||||
@ -52,7 +79,11 @@ rec {
|
||||
trace: { a = { b = { c = 3; }; }; }
|
||||
=> null
|
||||
*/
|
||||
traceSeq = x: y: trace (builtins.deepSeq x x) y;
|
||||
traceSeq =
|
||||
# The value to trace
|
||||
x:
|
||||
# The value to return
|
||||
y: trace (builtins.deepSeq x x) y;
|
||||
|
||||
/* Like `traceSeq`, but only evaluate down to depth n.
|
||||
This is very useful because lots of `traceSeq` usages
|
||||
@ -76,27 +107,49 @@ rec {
|
||||
in trace (generators.toPretty { allowPrettyValues = true; }
|
||||
(modify depth snip x)) y;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeq` */
|
||||
traceValSeqFn = f: v: traceValFn f (builtins.deepSeq v v);
|
||||
/* A combination of `traceVal` and `traceSeq` that applies a
|
||||
provided function to the value to be traced after `deepSeq`ing
|
||||
it.
|
||||
*/
|
||||
traceValSeqFn =
|
||||
# Function to apply
|
||||
f:
|
||||
# Value to trace
|
||||
v: traceValFn f (builtins.deepSeq v v);
|
||||
|
||||
/* A combination of `traceVal` and `traceSeq`. */
|
||||
traceValSeq = traceValSeqFn id;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeqN` that applies a
|
||||
provided function to the value to be traced. */
|
||||
traceValSeqNFn =
|
||||
# Function to apply
|
||||
f:
|
||||
depth:
|
||||
# Value to trace
|
||||
v: traceSeqN depth (f v) v;
|
||||
|
||||
/* A combination of `traceVal` and `traceSeqN`. */
|
||||
traceValSeqNFn = f: depth: v: traceSeqN depth (f v) v;
|
||||
traceValSeqN = traceValSeqNFn id;
|
||||
|
||||
|
||||
# -- TESTING --
|
||||
|
||||
/* Evaluate a set of tests. A test is an attribute set {expr,
|
||||
expected}, denoting an expression and its expected result. The
|
||||
result is a list of failed tests, each represented as {name,
|
||||
expected, actual}, denoting the attribute name of the failing
|
||||
test and its expected and actual results. Used for regression
|
||||
testing of the functions in lib; see tests.nix for an example.
|
||||
Only tests having names starting with "test" are run.
|
||||
Add attr { tests = ["testName"]; } to run these test only
|
||||
/* Evaluate a set of tests. A test is an attribute set `{expr,
|
||||
expected}`, denoting an expression and its expected result. The
|
||||
result is a list of failed tests, each represented as `{name,
|
||||
expected, actual}`, denoting the attribute name of the failing
|
||||
test and its expected and actual results.
|
||||
|
||||
Used for regression testing of the functions in lib; see
|
||||
tests.nix for an example. Only tests having names starting with
|
||||
"test" are run.
|
||||
|
||||
Add attr { tests = ["testName"]; } to run these tests only.
|
||||
*/
|
||||
runTests = tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
|
||||
runTests =
|
||||
# Tests to run
|
||||
tests: lib.concatLists (lib.attrValues (lib.mapAttrs (name: test:
|
||||
let testsToRun = if tests ? tests then tests.tests else [];
|
||||
in if (substring 0 4 name == "test" || elem name testsToRun)
|
||||
&& ((testsToRun == []) || elem name tests.tests)
|
||||
@ -105,8 +158,11 @@ rec {
|
||||
then [ { inherit name; expected = test.expected; result = test.expr; } ]
|
||||
else [] ) tests));
|
||||
|
||||
# create a test assuming that list elements are true
|
||||
# usage: { testX = allTrue [ true ]; }
|
||||
/* Create a test assuming that list elements are `true`.
|
||||
|
||||
Example:
|
||||
{ testX = allTrue [ true ]; }
|
||||
*/
|
||||
testAllTrue = expr: { inherit expr; expected = map (x: true) expr; };
|
||||
|
||||
|
||||
|
@ -309,6 +309,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||
fullName = "GNU General Public License v2.0 only";
|
||||
};
|
||||
|
||||
gpl2Classpath = {
|
||||
spdxId = "GPL-2.0-with-classpath-exception";
|
||||
fullName = "GNU General Public License v2.0 only (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
};
|
||||
|
||||
gpl2ClasspathPlus = {
|
||||
fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
|
||||
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
|
||||
@ -394,6 +400,10 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||
free = false;
|
||||
};
|
||||
|
||||
jasper = spdx {
|
||||
spdxId = "JasPer-2.0";
|
||||
fullName = "JasPer License";
|
||||
};
|
||||
|
||||
lgpl2 = spdx {
|
||||
spdxId = "LGPL-2.0";
|
||||
|
184
lib/lists.nix
184
lib/lists.nix
@ -1,4 +1,5 @@
|
||||
# General list operations.
|
||||
|
||||
{ lib }:
|
||||
with lib.trivial;
|
||||
let
|
||||
@ -8,21 +9,23 @@ rec {
|
||||
|
||||
inherit (builtins) head tail length isList elemAt concatLists filter elem genList;
|
||||
|
||||
/* Create a list consisting of a single element. `singleton x' is
|
||||
sometimes more convenient with respect to indentation than `[x]'
|
||||
/* Create a list consisting of a single element. `singleton x` is
|
||||
sometimes more convenient with respect to indentation than `[x]`
|
||||
when x spans multiple lines.
|
||||
|
||||
Type: singleton :: a -> [a]
|
||||
|
||||
Example:
|
||||
singleton "foo"
|
||||
=> [ "foo" ]
|
||||
*/
|
||||
singleton = x: [x];
|
||||
|
||||
/* “right fold” a binary function `op' between successive elements of
|
||||
`list' with `nul' as the starting value, i.e.,
|
||||
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))'.
|
||||
Type:
|
||||
foldr :: (a -> b -> b) -> b -> [a] -> b
|
||||
/* “right fold” a binary function `op` between successive elements of
|
||||
`list` with `nul' as the starting value, i.e.,
|
||||
`foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
|
||||
|
||||
Type: foldr :: (a -> b -> b) -> b -> [a] -> b
|
||||
|
||||
Example:
|
||||
concat = foldr (a: b: a + b) "z"
|
||||
@ -42,16 +45,15 @@ rec {
|
||||
else op (elemAt list n) (fold' (n + 1));
|
||||
in fold' 0;
|
||||
|
||||
/* `fold' is an alias of `foldr' for historic reasons */
|
||||
/* `fold` is an alias of `foldr` for historic reasons */
|
||||
# FIXME(Profpatsch): deprecate?
|
||||
fold = foldr;
|
||||
|
||||
|
||||
/* “left fold”, like `foldr', but from the left:
|
||||
/* “left fold”, like `foldr`, but from the left:
|
||||
`foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
|
||||
|
||||
Type:
|
||||
foldl :: (b -> a -> b) -> b -> [a] -> b
|
||||
Type: foldl :: (b -> a -> b) -> b -> [a] -> b
|
||||
|
||||
Example:
|
||||
lconcat = foldl (a: b: a + b) "z"
|
||||
@ -70,16 +72,20 @@ rec {
|
||||
else op (foldl' (n - 1)) (elemAt list n);
|
||||
in foldl' (length list - 1);
|
||||
|
||||
/* Strict version of `foldl'.
|
||||
/* Strict version of `foldl`.
|
||||
|
||||
The difference is that evaluation is forced upon access. Usually used
|
||||
with small whole results (in contract with lazily-generated list or large
|
||||
lists where only a part is consumed.)
|
||||
|
||||
Type: foldl' :: (b -> a -> b) -> b -> [a] -> b
|
||||
*/
|
||||
foldl' = builtins.foldl' or foldl;
|
||||
|
||||
/* Map with index starting from 0
|
||||
|
||||
Type: imap0 :: (int -> a -> b) -> [a] -> [b]
|
||||
|
||||
Example:
|
||||
imap0 (i: v: "${v}-${toString i}") ["a" "b"]
|
||||
=> [ "a-0" "b-1" ]
|
||||
@ -88,6 +94,8 @@ rec {
|
||||
|
||||
/* Map with index starting from 1
|
||||
|
||||
Type: imap1 :: (int -> a -> b) -> [a] -> [b]
|
||||
|
||||
Example:
|
||||
imap1 (i: v: "${v}-${toString i}") ["a" "b"]
|
||||
=> [ "a-1" "b-2" ]
|
||||
@ -96,6 +104,8 @@ rec {
|
||||
|
||||
/* Map and concatenate the result.
|
||||
|
||||
Type: concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
|
||||
Example:
|
||||
concatMap (x: [x] ++ ["z"]) ["a" "b"]
|
||||
=> [ "a" "z" "b" "z" ]
|
||||
@ -118,15 +128,21 @@ rec {
|
||||
|
||||
/* Remove elements equal to 'e' from a list. Useful for buildInputs.
|
||||
|
||||
Type: remove :: a -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
remove 3 [ 1 3 4 3 ]
|
||||
=> [ 1 4 ]
|
||||
*/
|
||||
remove = e: filter (x: x != e);
|
||||
remove =
|
||||
# Element to remove from the list
|
||||
e: filter (x: x != e);
|
||||
|
||||
/* Find the sole element in the list matching the specified
|
||||
predicate, returns `default' if no such element exists, or
|
||||
`multiple' if there are multiple matching elements.
|
||||
predicate, returns `default` if no such element exists, or
|
||||
`multiple` if there are multiple matching elements.
|
||||
|
||||
Type: findSingle :: (a -> bool) -> a -> a -> [a] -> a
|
||||
|
||||
Example:
|
||||
findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
|
||||
@ -136,14 +152,24 @@ rec {
|
||||
findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
|
||||
=> "none"
|
||||
*/
|
||||
findSingle = pred: default: multiple: list:
|
||||
findSingle =
|
||||
# Predicate
|
||||
pred:
|
||||
# Default value to return if element was not found.
|
||||
default:
|
||||
# Default value to return if more than one element was found
|
||||
multiple:
|
||||
# Input list
|
||||
list:
|
||||
let found = filter pred list; len = length found;
|
||||
in if len == 0 then default
|
||||
else if len != 1 then multiple
|
||||
else head found;
|
||||
|
||||
/* Find the first element in the list matching the specified
|
||||
predicate or returns `default' if no such element exists.
|
||||
predicate or return `default` if no such element exists.
|
||||
|
||||
Type: findFirst :: (a -> bool) -> a -> [a] -> a
|
||||
|
||||
Example:
|
||||
findFirst (x: x > 3) 7 [ 1 6 4 ]
|
||||
@ -151,12 +177,20 @@ rec {
|
||||
findFirst (x: x > 9) 7 [ 1 6 4 ]
|
||||
=> 7
|
||||
*/
|
||||
findFirst = pred: default: list:
|
||||
findFirst =
|
||||
# Predicate
|
||||
pred:
|
||||
# Default value to return
|
||||
default:
|
||||
# Input list
|
||||
list:
|
||||
let found = filter pred list;
|
||||
in if found == [] then default else head found;
|
||||
|
||||
/* Return true iff function `pred' returns true for at least element
|
||||
of `list'.
|
||||
/* Return true if function `pred` returns true for at least one
|
||||
element of `list`.
|
||||
|
||||
Type: any :: (a -> bool) -> [a] -> bool
|
||||
|
||||
Example:
|
||||
any isString [ 1 "a" { } ]
|
||||
@ -166,8 +200,10 @@ rec {
|
||||
*/
|
||||
any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
|
||||
|
||||
/* Return true iff function `pred' returns true for all elements of
|
||||
`list'.
|
||||
/* Return true if function `pred` returns true for all elements of
|
||||
`list`.
|
||||
|
||||
Type: all :: (a -> bool) -> [a] -> bool
|
||||
|
||||
Example:
|
||||
all (x: x < 3) [ 1 2 ]
|
||||
@ -177,19 +213,25 @@ rec {
|
||||
*/
|
||||
all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
|
||||
|
||||
/* Count how many times function `pred' returns true for the elements
|
||||
of `list'.
|
||||
/* Count how many elements of `list` match the supplied predicate
|
||||
function.
|
||||
|
||||
Type: count :: (a -> bool) -> [a] -> int
|
||||
|
||||
Example:
|
||||
count (x: x == 3) [ 3 2 3 4 6 ]
|
||||
=> 2
|
||||
*/
|
||||
count = pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
||||
count =
|
||||
# Predicate
|
||||
pred: foldl' (c: x: if pred x then c + 1 else c) 0;
|
||||
|
||||
/* Return a singleton list or an empty list, depending on a boolean
|
||||
value. Useful when building lists with optional elements
|
||||
(e.g. `++ optional (system == "i686-linux") flashplayer').
|
||||
|
||||
Type: optional :: bool -> a -> [a]
|
||||
|
||||
Example:
|
||||
optional true "foo"
|
||||
=> [ "foo" ]
|
||||
@ -200,13 +242,19 @@ rec {
|
||||
|
||||
/* Return a list or an empty list, depending on a boolean value.
|
||||
|
||||
Type: optionals :: bool -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
optionals true [ 2 3 ]
|
||||
=> [ 2 3 ]
|
||||
optionals false [ 2 3 ]
|
||||
=> [ ]
|
||||
*/
|
||||
optionals = cond: elems: if cond then elems else [];
|
||||
optionals =
|
||||
# Condition
|
||||
cond:
|
||||
# List to return if condition is true
|
||||
elems: if cond then elems else [];
|
||||
|
||||
|
||||
/* If argument is a list, return it; else, wrap it in a singleton
|
||||
@ -223,20 +271,28 @@ rec {
|
||||
|
||||
/* Return a list of integers from `first' up to and including `last'.
|
||||
|
||||
Type: range :: int -> int -> [int]
|
||||
|
||||
Example:
|
||||
range 2 4
|
||||
=> [ 2 3 4 ]
|
||||
range 3 2
|
||||
=> [ ]
|
||||
*/
|
||||
range = first: last:
|
||||
range =
|
||||
# First integer in the range
|
||||
first:
|
||||
# Last integer in the range
|
||||
last:
|
||||
if first > last then
|
||||
[]
|
||||
else
|
||||
genList (n: first + n) (last - first + 1);
|
||||
|
||||
/* Splits the elements of a list in two lists, `right' and
|
||||
`wrong', depending on the evaluation of a predicate.
|
||||
/* Splits the elements of a list in two lists, `right` and
|
||||
`wrong`, depending on the evaluation of a predicate.
|
||||
|
||||
Type: (a -> bool) -> [a] -> { right :: [a], wrong :: [a] }
|
||||
|
||||
Example:
|
||||
partition (x: x > 2) [ 5 1 2 3 4 ]
|
||||
@ -252,7 +308,7 @@ rec {
|
||||
/* Splits the elements of a list into many lists, using the return value of a predicate.
|
||||
Predicate should return a string which becomes keys of attrset `groupBy' returns.
|
||||
|
||||
`groupBy'' allows to customise the combining function and initial value
|
||||
`groupBy'` allows to customise the combining function and initial value
|
||||
|
||||
Example:
|
||||
groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
||||
@ -268,10 +324,6 @@ rec {
|
||||
xfce = [ { name = "xfce"; script = "xfce4-session &"; } ];
|
||||
}
|
||||
|
||||
|
||||
groupBy' allows to customise the combining function and initial value
|
||||
|
||||
Example:
|
||||
groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
|
||||
=> { true = 12; false = 3; }
|
||||
*/
|
||||
@ -289,17 +341,27 @@ rec {
|
||||
the merging stops at the shortest. How both lists are merged is defined
|
||||
by the first argument.
|
||||
|
||||
Type: zipListsWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
|
||||
Example:
|
||||
zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
|
||||
=> ["he" "lo"]
|
||||
*/
|
||||
zipListsWith = f: fst: snd:
|
||||
zipListsWith =
|
||||
# Function to zip elements of both lists
|
||||
f:
|
||||
# First list
|
||||
fst:
|
||||
# Second list
|
||||
snd:
|
||||
genList
|
||||
(n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
|
||||
|
||||
/* Merges two lists of the same size together. If the sizes aren't the same
|
||||
the merging stops at the shortest.
|
||||
|
||||
Type: zipLists :: [a] -> [b] -> [{ fst :: a, snd :: b}]
|
||||
|
||||
Example:
|
||||
zipLists [ 1 2 ] [ "a" "b" ]
|
||||
=> [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
|
||||
@ -308,6 +370,8 @@ rec {
|
||||
|
||||
/* Reverse the order of the elements of a list.
|
||||
|
||||
Type: reverseList :: [a] -> [a]
|
||||
|
||||
Example:
|
||||
|
||||
reverseList [ "b" "o" "j" ]
|
||||
@ -321,8 +385,7 @@ rec {
|
||||
`before a b == true` means that `b` depends on `a` (there's an
|
||||
edge from `b` to `a`).
|
||||
|
||||
Examples:
|
||||
|
||||
Example:
|
||||
listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
|
||||
== { minimal = "/"; # minimal element
|
||||
visited = [ "/home/user" ]; # seen elements (in reverse order)
|
||||
@ -336,7 +399,6 @@ rec {
|
||||
rest = [ "/home" "other" ]; # everything else
|
||||
|
||||
*/
|
||||
|
||||
listDfs = stopOnCycles: before: list:
|
||||
let
|
||||
dfs' = us: visited: rest:
|
||||
@ -361,7 +423,7 @@ rec {
|
||||
`before a b == true` means that `b` should be after `a`
|
||||
in the result.
|
||||
|
||||
Examples:
|
||||
Example:
|
||||
|
||||
toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
|
||||
== { result = [ "/" "/home" "/home/user" "other" ]; }
|
||||
@ -376,7 +438,6 @@ rec {
|
||||
toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
|
||||
|
||||
*/
|
||||
|
||||
toposort = before: list:
|
||||
let
|
||||
dfsthis = listDfs true before list;
|
||||
@ -467,26 +528,38 @@ rec {
|
||||
|
||||
/* Return the first (at most) N elements of a list.
|
||||
|
||||
Type: take :: int -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
take 2 [ "a" "b" "c" "d" ]
|
||||
=> [ "a" "b" ]
|
||||
take 2 [ ]
|
||||
=> [ ]
|
||||
*/
|
||||
take = count: sublist 0 count;
|
||||
take =
|
||||
# Number of elements to take
|
||||
count: sublist 0 count;
|
||||
|
||||
/* Remove the first (at most) N elements of a list.
|
||||
|
||||
Type: drop :: int -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
drop 2 [ "a" "b" "c" "d" ]
|
||||
=> [ "c" "d" ]
|
||||
drop 2 [ ]
|
||||
=> [ ]
|
||||
*/
|
||||
drop = count: list: sublist count (length list) list;
|
||||
drop =
|
||||
# Number of elements to drop
|
||||
count:
|
||||
# Input list
|
||||
list: sublist count (length list) list;
|
||||
|
||||
/* Return a list consisting of at most ‘count’ elements of ‘list’,
|
||||
starting at index ‘start’.
|
||||
/* Return a list consisting of at most `count` elements of `list`,
|
||||
starting at index `start`.
|
||||
|
||||
Type: sublist :: int -> int -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
sublist 1 3 [ "a" "b" "c" "d" "e" ]
|
||||
@ -494,7 +567,13 @@ rec {
|
||||
sublist 1 3 [ ]
|
||||
=> [ ]
|
||||
*/
|
||||
sublist = start: count: list:
|
||||
sublist =
|
||||
# Index at which to start the sublist
|
||||
start:
|
||||
# Number of elements to take
|
||||
count:
|
||||
# Input list
|
||||
list:
|
||||
let len = length list; in
|
||||
genList
|
||||
(n: elemAt list (n + start))
|
||||
@ -504,6 +583,10 @@ rec {
|
||||
|
||||
/* Return the last element of a list.
|
||||
|
||||
This function throws an error if the list is empty.
|
||||
|
||||
Type: last :: [a] -> a
|
||||
|
||||
Example:
|
||||
last [ 1 2 3 ]
|
||||
=> 3
|
||||
@ -512,7 +595,11 @@ rec {
|
||||
assert lib.assertMsg (list != []) "lists.last: list must not be empty!";
|
||||
elemAt list (length list - 1);
|
||||
|
||||
/* Return all elements but the last
|
||||
/* Return all elements but the last.
|
||||
|
||||
This function throws an error if the list is empty.
|
||||
|
||||
Type: init :: [a] -> [a]
|
||||
|
||||
Example:
|
||||
init [ 1 2 3 ]
|
||||
@ -523,7 +610,7 @@ rec {
|
||||
take (length list - 1) list;
|
||||
|
||||
|
||||
/* return the image of the cross product of some lists by a function
|
||||
/* Return the image of the cross product of some lists by a function.
|
||||
|
||||
Example:
|
||||
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
|
||||
@ -534,8 +621,9 @@ rec {
|
||||
|
||||
/* Remove duplicate elements from the list. O(n^2) complexity.
|
||||
|
||||
Example:
|
||||
Type: unique :: [a] -> [a]
|
||||
|
||||
Example:
|
||||
unique [ 3 2 3 4 ]
|
||||
=> [ 3 2 4 ]
|
||||
*/
|
||||
|
155
lib/options.nix
155
lib/options.nix
@ -8,61 +8,72 @@ with lib.strings;
|
||||
|
||||
rec {
|
||||
|
||||
# Returns true when the given argument is an option
|
||||
#
|
||||
# Examples:
|
||||
# isOption 1 // => false
|
||||
# isOption (mkOption {}) // => true
|
||||
/* Returns true when the given argument is an option
|
||||
|
||||
Type: isOption :: a -> bool
|
||||
|
||||
Example:
|
||||
isOption 1 // => false
|
||||
isOption (mkOption {}) // => true
|
||||
*/
|
||||
isOption = lib.isType "option";
|
||||
|
||||
# Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
|
||||
#
|
||||
# default: Default value used when no definition is given in the configuration.
|
||||
# defaultText: Textual representation of the default, for in the manual.
|
||||
# example: Example value used in the manual.
|
||||
# description: String describing the option.
|
||||
# type: Option type, providing type-checking and value merging.
|
||||
# apply: Function that converts the option value to something else.
|
||||
# internal: Whether the option is for NixOS developers only.
|
||||
# visible: Whether the option shows up in the manual.
|
||||
# readOnly: Whether the option can be set only once
|
||||
# options: Obsolete, used by types.optionSet.
|
||||
#
|
||||
# All keys default to `null` when not given.
|
||||
#
|
||||
# Examples:
|
||||
# mkOption { } // => { _type = "option"; }
|
||||
# mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
|
||||
/* Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
|
||||
|
||||
All keys default to `null` when not given.
|
||||
|
||||
Example:
|
||||
mkOption { } // => { _type = "option"; }
|
||||
mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
|
||||
*/
|
||||
mkOption =
|
||||
{ default ? null # Default value used when no definition is given in the configuration.
|
||||
, defaultText ? null # Textual representation of the default, for in the manual.
|
||||
, example ? null # Example value used in the manual.
|
||||
, description ? null # String describing the option.
|
||||
, relatedPackages ? null # Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
|
||||
, type ? null # Option type, providing type-checking and value merging.
|
||||
, apply ? null # Function that converts the option value to something else.
|
||||
, internal ? null # Whether the option is for NixOS developers only.
|
||||
, visible ? null # Whether the option shows up in the manual.
|
||||
, readOnly ? null # Whether the option can be set only once
|
||||
, options ? null # Obsolete, used by types.optionSet.
|
||||
{
|
||||
# Default value used when no definition is given in the configuration.
|
||||
default ? null,
|
||||
# Textual representation of the default, for the manual.
|
||||
defaultText ? null,
|
||||
# Example value used in the manual.
|
||||
example ? null,
|
||||
# String describing the option.
|
||||
description ? null,
|
||||
# Related packages used in the manual (see `genRelatedPackages` in ../nixos/doc/manual/default.nix).
|
||||
relatedPackages ? null,
|
||||
# Option type, providing type-checking and value merging.
|
||||
type ? null,
|
||||
# Function that converts the option value to something else.
|
||||
apply ? null,
|
||||
# Whether the option is for NixOS developers only.
|
||||
internal ? null,
|
||||
# Whether the option shows up in the manual.
|
||||
visible ? null,
|
||||
# Whether the option can be set only once
|
||||
readOnly ? null,
|
||||
# Obsolete, used by types.optionSet.
|
||||
options ? null
|
||||
} @ attrs:
|
||||
attrs // { _type = "option"; };
|
||||
|
||||
# Creates a Option attribute set for a boolean value option i.e an option to be toggled on or off:
|
||||
#
|
||||
# Examples:
|
||||
# mkEnableOption "foo" // => { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
|
||||
mkEnableOption = name: mkOption {
|
||||
/* Creates an Option attribute set for a boolean value option i.e an
|
||||
option to be toggled on or off:
|
||||
|
||||
Example:
|
||||
mkEnableOption "foo"
|
||||
=> { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
|
||||
*/
|
||||
mkEnableOption =
|
||||
# Name for the created option
|
||||
name: mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
description = "Whether to enable ${name}.";
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
# This option accept anything, but it does not produce any result. This
|
||||
# is useful for sharing a module across different module sets without
|
||||
# having to implement similar features as long as the value of the options
|
||||
# are not expected.
|
||||
/* This option accepts anything, but it does not produce any result.
|
||||
|
||||
This is useful for sharing a module across different module sets
|
||||
without having to implement similar features as long as the
|
||||
values of the options are not accessed. */
|
||||
mkSinkUndeclaredOptions = attrs: mkOption ({
|
||||
internal = true;
|
||||
visible = false;
|
||||
@ -102,18 +113,24 @@ rec {
|
||||
else
|
||||
val) (head defs).value defs;
|
||||
|
||||
# Extracts values of all "value" keys of the given list
|
||||
#
|
||||
# Examples:
|
||||
# getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
|
||||
# getValues [ ] // => [ ]
|
||||
/* Extracts values of all "value" keys of the given list.
|
||||
|
||||
Type: getValues :: [ { value :: a } ] -> [a]
|
||||
|
||||
Example:
|
||||
getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
|
||||
getValues [ ] // => [ ]
|
||||
*/
|
||||
getValues = map (x: x.value);
|
||||
|
||||
# Extracts values of all "file" keys of the given list
|
||||
#
|
||||
# Examples:
|
||||
# getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
|
||||
# getFiles [ ] // => [ ]
|
||||
/* Extracts values of all "file" keys of the given list
|
||||
|
||||
Type: getFiles :: [ { file :: a } ] -> [a]
|
||||
|
||||
Example:
|
||||
getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
|
||||
getFiles [ ] // => [ ]
|
||||
*/
|
||||
getFiles = map (x: x.file);
|
||||
|
||||
# Generate documentation template from the list of option declaration like
|
||||
@ -146,10 +163,13 @@ rec {
|
||||
|
||||
|
||||
/* This function recursively removes all derivation attributes from
|
||||
`x' except for the `name' attribute. This is to make the
|
||||
generation of `options.xml' much more efficient: the XML
|
||||
representation of derivations is very large (on the order of
|
||||
megabytes) and is not actually used by the manual generator. */
|
||||
`x` except for the `name` attribute.
|
||||
|
||||
This is to make the generation of `options.xml` much more
|
||||
efficient: the XML representation of derivations is very large
|
||||
(on the order of megabytes) and is not actually used by the
|
||||
manual generator.
|
||||
*/
|
||||
scrubOptionValue = x:
|
||||
if isDerivation x then
|
||||
{ type = "derivation"; drvPath = x.name; outPath = x.name; name = x.name; }
|
||||
@ -158,20 +178,21 @@ rec {
|
||||
else x;
|
||||
|
||||
|
||||
/* For use in the ‘example’ option attribute. It causes the given
|
||||
text to be included verbatim in documentation. This is necessary
|
||||
for example values that are not simple values, e.g.,
|
||||
functions. */
|
||||
/* For use in the `example` option attribute. It causes the given
|
||||
text to be included verbatim in documentation. This is necessary
|
||||
for example values that are not simple values, e.g., functions.
|
||||
*/
|
||||
literalExample = text: { _type = "literalExample"; inherit text; };
|
||||
|
||||
# Helper functions.
|
||||
|
||||
/* Helper functions. */
|
||||
/* Convert an option, described as a list of the option parts in to a
|
||||
safe, human readable version.
|
||||
|
||||
# Convert an option, described as a list of the option parts in to a
|
||||
# safe, human readable version. ie:
|
||||
#
|
||||
# (showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
|
||||
# (showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
|
||||
Example:
|
||||
(showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
|
||||
(showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
|
||||
*/
|
||||
showOption = parts: let
|
||||
escapeOptionPart = part:
|
||||
let
|
||||
|
213
lib/strings.nix
213
lib/strings.nix
@ -12,6 +12,8 @@ rec {
|
||||
|
||||
/* Concatenate a list of strings.
|
||||
|
||||
Type: concatStrings :: [string] -> string
|
||||
|
||||
Example:
|
||||
concatStrings ["foo" "bar"]
|
||||
=> "foobar"
|
||||
@ -20,15 +22,19 @@ rec {
|
||||
|
||||
/* Map a function over a list and concatenate the resulting strings.
|
||||
|
||||
Type: concatMapStrings :: (a -> string) -> [a] -> string
|
||||
|
||||
Example:
|
||||
concatMapStrings (x: "a" + x) ["foo" "bar"]
|
||||
=> "afooabar"
|
||||
*/
|
||||
concatMapStrings = f: list: concatStrings (map f list);
|
||||
|
||||
/* Like `concatMapStrings' except that the f functions also gets the
|
||||
/* Like `concatMapStrings` except that the f functions also gets the
|
||||
position as a parameter.
|
||||
|
||||
Type: concatImapStrings :: (int -> a -> string) -> [a] -> string
|
||||
|
||||
Example:
|
||||
concatImapStrings (pos: x: "${toString pos}-${x}") ["foo" "bar"]
|
||||
=> "1-foo2-bar"
|
||||
@ -37,17 +43,25 @@ rec {
|
||||
|
||||
/* Place an element between each element of a list
|
||||
|
||||
Type: intersperse :: a -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
intersperse "/" ["usr" "local" "bin"]
|
||||
=> ["usr" "/" "local" "/" "bin"].
|
||||
*/
|
||||
intersperse = separator: list:
|
||||
intersperse =
|
||||
# Separator to add between elements
|
||||
separator:
|
||||
# Input list
|
||||
list:
|
||||
if list == [] || length list == 1
|
||||
then list
|
||||
else tail (lib.concatMap (x: [separator x]) list);
|
||||
|
||||
/* Concatenate a list of strings with a separator between each element
|
||||
|
||||
Type: concatStringsSep :: string -> [string] -> string
|
||||
|
||||
Example:
|
||||
concatStringsSep "/" ["usr" "local" "bin"]
|
||||
=> "usr/local/bin"
|
||||
@ -55,43 +69,77 @@ rec {
|
||||
concatStringsSep = builtins.concatStringsSep or (separator: list:
|
||||
concatStrings (intersperse separator list));
|
||||
|
||||
/* First maps over the list and then concatenates it.
|
||||
/* Maps a function over a list of strings and then concatenates the
|
||||
result with the specified separator interspersed between
|
||||
elements.
|
||||
|
||||
Type: concatMapStringsSep :: string -> (string -> string) -> [string] -> string
|
||||
|
||||
Example:
|
||||
concatMapStringsSep "-" (x: toUpper x) ["foo" "bar" "baz"]
|
||||
=> "FOO-BAR-BAZ"
|
||||
*/
|
||||
concatMapStringsSep = sep: f: list: concatStringsSep sep (map f list);
|
||||
concatMapStringsSep =
|
||||
# Separator to add between elements
|
||||
sep:
|
||||
# Function to map over the list
|
||||
f:
|
||||
# List of input strings
|
||||
list: concatStringsSep sep (map f list);
|
||||
|
||||
/* First imaps over the list and then concatenates it.
|
||||
/* Same as `concatMapStringsSep`, but the mapping function
|
||||
additionally receives the position of its argument.
|
||||
|
||||
Type: concatMapStringsSep :: string -> (int -> string -> string) -> [string] -> string
|
||||
|
||||
Example:
|
||||
|
||||
concatImapStringsSep "-" (pos: x: toString (x / pos)) [ 6 6 6 ]
|
||||
=> "6-3-2"
|
||||
*/
|
||||
concatImapStringsSep = sep: f: list: concatStringsSep sep (lib.imap1 f list);
|
||||
concatImapStringsSep =
|
||||
# Separator to add between elements
|
||||
sep:
|
||||
# Function that receives elements and their positions
|
||||
f:
|
||||
# List of input strings
|
||||
list: concatStringsSep sep (lib.imap1 f list);
|
||||
|
||||
/* Construct a Unix-style search path consisting of each `subDir"
|
||||
directory of the given list of packages.
|
||||
/* Construct a Unix-style, colon-separated search path consisting of
|
||||
the given `subDir` appended to each of the given paths.
|
||||
|
||||
Type: makeSearchPath :: string -> [string] -> string
|
||||
|
||||
Example:
|
||||
makeSearchPath "bin" ["/root" "/usr" "/usr/local"]
|
||||
=> "/root/bin:/usr/bin:/usr/local/bin"
|
||||
makeSearchPath "bin" ["/"]
|
||||
=> "//bin"
|
||||
makeSearchPath "bin" [""]
|
||||
=> "/bin"
|
||||
*/
|
||||
makeSearchPath = subDir: packages:
|
||||
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) packages));
|
||||
makeSearchPath =
|
||||
# Directory name to append
|
||||
subDir:
|
||||
# List of base paths
|
||||
paths:
|
||||
concatStringsSep ":" (map (path: path + "/" + subDir) (builtins.filter (x: x != null) paths));
|
||||
|
||||
/* Construct a Unix-style search path, using given package output.
|
||||
If no output is found, fallback to `.out` and then to the default.
|
||||
/* Construct a Unix-style search path by appending the given
|
||||
`subDir` to the specified `output` of each of the packages. If no
|
||||
output by the given name is found, fallback to `.out` and then to
|
||||
the default.
|
||||
|
||||
Type: string -> string -> [package] -> string
|
||||
|
||||
Example:
|
||||
makeSearchPathOutput "dev" "bin" [ pkgs.openssl pkgs.zlib ]
|
||||
=> "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev/bin:/nix/store/wwh7mhwh269sfjkm6k5665b5kgp7jrk2-zlib-1.2.8/bin"
|
||||
*/
|
||||
makeSearchPathOutput = output: subDir: pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs);
|
||||
makeSearchPathOutput =
|
||||
# Package output to use
|
||||
output:
|
||||
# Directory name to append
|
||||
subDir:
|
||||
# List of packages
|
||||
pkgs: makeSearchPath subDir (map (lib.getOutput output) pkgs);
|
||||
|
||||
/* Construct a library search path (such as RPATH) containing the
|
||||
libraries for a set of packages
|
||||
@ -117,13 +165,12 @@ rec {
|
||||
|
||||
/* Construct a perl search path (such as $PERL5LIB)
|
||||
|
||||
FIXME(zimbatm): this should be moved in perl-specific code
|
||||
|
||||
Example:
|
||||
pkgs = import <nixpkgs> { }
|
||||
makePerlPath [ pkgs.perlPackages.libnet ]
|
||||
=> "/nix/store/n0m1fk9c960d8wlrs62sncnadygqqc6y-perl-Net-SMTP-1.25/lib/perl5/site_perl"
|
||||
*/
|
||||
# FIXME(zimbatm): this should be moved in perl-specific code
|
||||
makePerlPath = makeSearchPathOutput "lib" "lib/perl5/site_perl";
|
||||
|
||||
/* Construct a perl search path recursively including all dependencies (such as $PERL5LIB)
|
||||
@ -138,34 +185,51 @@ rec {
|
||||
/* Depending on the boolean `cond', return either the given string
|
||||
or the empty string. Useful to concatenate against a bigger string.
|
||||
|
||||
Type: optionalString :: bool -> string -> string
|
||||
|
||||
Example:
|
||||
optionalString true "some-string"
|
||||
=> "some-string"
|
||||
optionalString false "some-string"
|
||||
=> ""
|
||||
*/
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
optionalString =
|
||||
# Condition
|
||||
cond:
|
||||
# String to return if condition is true
|
||||
string: if cond then string else "";
|
||||
|
||||
/* Determine whether a string has given prefix.
|
||||
|
||||
Type: hasPrefix :: string -> string -> bool
|
||||
|
||||
Example:
|
||||
hasPrefix "foo" "foobar"
|
||||
=> true
|
||||
hasPrefix "foo" "barfoo"
|
||||
=> false
|
||||
*/
|
||||
hasPrefix = pref: str:
|
||||
substring 0 (stringLength pref) str == pref;
|
||||
hasPrefix =
|
||||
# Prefix to check for
|
||||
pref:
|
||||
# Input string
|
||||
str: substring 0 (stringLength pref) str == pref;
|
||||
|
||||
/* Determine whether a string has given suffix.
|
||||
|
||||
Type: hasSuffix :: string -> string -> bool
|
||||
|
||||
Example:
|
||||
hasSuffix "foo" "foobar"
|
||||
=> false
|
||||
hasSuffix "foo" "barfoo"
|
||||
=> true
|
||||
*/
|
||||
hasSuffix = suffix: content:
|
||||
hasSuffix =
|
||||
# Suffix to check for
|
||||
suffix:
|
||||
# Input string
|
||||
content:
|
||||
let
|
||||
lenContent = stringLength content;
|
||||
lenSuffix = stringLength suffix;
|
||||
@ -180,6 +244,8 @@ rec {
|
||||
Also note that Nix treats strings as a list of bytes and thus doesn't
|
||||
handle unicode.
|
||||
|
||||
Type: stringtoCharacters :: string -> [string]
|
||||
|
||||
Example:
|
||||
stringToCharacters ""
|
||||
=> [ ]
|
||||
@ -194,18 +260,25 @@ rec {
|
||||
/* Manipulate a string character by character and replace them by
|
||||
strings before concatenating the results.
|
||||
|
||||
Type: stringAsChars :: (string -> string) -> string -> string
|
||||
|
||||
Example:
|
||||
stringAsChars (x: if x == "a" then "i" else x) "nax"
|
||||
=> "nix"
|
||||
*/
|
||||
stringAsChars = f: s:
|
||||
concatStrings (
|
||||
stringAsChars =
|
||||
# Function to map over each individual character
|
||||
f:
|
||||
# Input string
|
||||
s: concatStrings (
|
||||
map f (stringToCharacters s)
|
||||
);
|
||||
|
||||
/* Escape occurrence of the elements of ‘list’ in ‘string’ by
|
||||
/* Escape occurrence of the elements of `list` in `string` by
|
||||
prefixing it with a backslash.
|
||||
|
||||
Type: escape :: [string] -> string -> string
|
||||
|
||||
Example:
|
||||
escape ["(" ")"] "(foo)"
|
||||
=> "\\(foo\\)"
|
||||
@ -214,6 +287,8 @@ rec {
|
||||
|
||||
/* Quote string to be used safely within the Bourne shell.
|
||||
|
||||
Type: escapeShellArg :: string -> string
|
||||
|
||||
Example:
|
||||
escapeShellArg "esc'ape\nme"
|
||||
=> "'esc'\\''ape\nme'"
|
||||
@ -222,6 +297,8 @@ rec {
|
||||
|
||||
/* Quote all arguments to be safely passed to the Bourne shell.
|
||||
|
||||
Type: escapeShellArgs :: [string] -> string
|
||||
|
||||
Example:
|
||||
escapeShellArgs ["one" "two three" "four'five"]
|
||||
=> "'one' 'two three' 'four'\\''five'"
|
||||
@ -230,13 +307,15 @@ rec {
|
||||
|
||||
/* Turn a string into a Nix expression representing that string
|
||||
|
||||
Type: string -> string
|
||||
|
||||
Example:
|
||||
escapeNixString "hello\${}\n"
|
||||
=> "\"hello\\\${}\\n\""
|
||||
*/
|
||||
escapeNixString = s: escape ["$"] (builtins.toJSON s);
|
||||
|
||||
/* Obsolete - use replaceStrings instead. */
|
||||
# Obsolete - use replaceStrings instead.
|
||||
replaceChars = builtins.replaceStrings or (
|
||||
del: new: s:
|
||||
let
|
||||
@ -256,6 +335,8 @@ rec {
|
||||
|
||||
/* Converts an ASCII string to lower-case.
|
||||
|
||||
Type: toLower :: string -> string
|
||||
|
||||
Example:
|
||||
toLower "HOME"
|
||||
=> "home"
|
||||
@ -264,6 +345,8 @@ rec {
|
||||
|
||||
/* Converts an ASCII string to upper-case.
|
||||
|
||||
Type: toUpper :: string -> string
|
||||
|
||||
Example:
|
||||
toUpper "home"
|
||||
=> "HOME"
|
||||
@ -273,7 +356,7 @@ rec {
|
||||
/* Appends string context from another string. This is an implementation
|
||||
detail of Nix.
|
||||
|
||||
Strings in Nix carry an invisible `context' which is a list of strings
|
||||
Strings in Nix carry an invisible `context` which is a list of strings
|
||||
representing store paths. If the string is later used in a derivation
|
||||
attribute, the derivation will properly populate the inputDrvs and
|
||||
inputSrcs.
|
||||
@ -319,8 +402,9 @@ rec {
|
||||
in
|
||||
recurse 0 0;
|
||||
|
||||
/* Return the suffix of the second argument if the first argument matches
|
||||
its prefix.
|
||||
/* Return a string without the specified prefix, if the prefix matches.
|
||||
|
||||
Type: string -> string -> string
|
||||
|
||||
Example:
|
||||
removePrefix "foo." "foo.bar.baz"
|
||||
@ -328,18 +412,23 @@ rec {
|
||||
removePrefix "xxx" "foo.bar.baz"
|
||||
=> "foo.bar.baz"
|
||||
*/
|
||||
removePrefix = pre: s:
|
||||
removePrefix =
|
||||
# Prefix to remove if it matches
|
||||
prefix:
|
||||
# Input string
|
||||
str:
|
||||
let
|
||||
preLen = stringLength pre;
|
||||
sLen = stringLength s;
|
||||
preLen = stringLength prefix;
|
||||
sLen = stringLength str;
|
||||
in
|
||||
if hasPrefix pre s then
|
||||
substring preLen (sLen - preLen) s
|
||||
if hasPrefix prefix str then
|
||||
substring preLen (sLen - preLen) str
|
||||
else
|
||||
s;
|
||||
str;
|
||||
|
||||
/* Return the prefix of the second argument if the first argument matches
|
||||
its suffix.
|
||||
/* Return a string without the specified suffix, if the suffix matches.
|
||||
|
||||
Type: string -> string -> string
|
||||
|
||||
Example:
|
||||
removeSuffix "front" "homefront"
|
||||
@ -347,17 +436,21 @@ rec {
|
||||
removeSuffix "xxx" "homefront"
|
||||
=> "homefront"
|
||||
*/
|
||||
removeSuffix = suf: s:
|
||||
removeSuffix =
|
||||
# Suffix to remove if it matches
|
||||
suffix:
|
||||
# Input string
|
||||
str:
|
||||
let
|
||||
sufLen = stringLength suf;
|
||||
sLen = stringLength s;
|
||||
sufLen = stringLength suffix;
|
||||
sLen = stringLength str;
|
||||
in
|
||||
if sufLen <= sLen && suf == substring (sLen - sufLen) sufLen s then
|
||||
substring 0 (sLen - sufLen) s
|
||||
if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str then
|
||||
substring 0 (sLen - sufLen) str
|
||||
else
|
||||
s;
|
||||
str;
|
||||
|
||||
/* Return true iff string v1 denotes a version older than v2.
|
||||
/* Return true if string v1 denotes a version older than v2.
|
||||
|
||||
Example:
|
||||
versionOlder "1.1" "1.2"
|
||||
@ -367,7 +460,7 @@ rec {
|
||||
*/
|
||||
versionOlder = v1: v2: builtins.compareVersions v2 v1 == 1;
|
||||
|
||||
/* Return true iff string v1 denotes a version equal to or newer than v2.
|
||||
/* Return true if string v1 denotes a version equal to or newer than v2.
|
||||
|
||||
Example:
|
||||
versionAtLeast "1.1" "1.0"
|
||||
@ -459,6 +552,11 @@ rec {
|
||||
/* Create a fixed width string with additional prefix to match
|
||||
required width.
|
||||
|
||||
This function will fail if the input string is longer than the
|
||||
requested length.
|
||||
|
||||
Type: fixedWidthString :: int -> string -> string
|
||||
|
||||
Example:
|
||||
fixedWidthString 5 "0" (toString 15)
|
||||
=> "00015"
|
||||
@ -502,12 +600,16 @@ rec {
|
||||
=> false
|
||||
*/
|
||||
isStorePath = x:
|
||||
isCoercibleToString x
|
||||
&& builtins.substring 0 1 (toString x) == "/"
|
||||
&& dirOf x == builtins.storeDir;
|
||||
if isCoercibleToString x then
|
||||
let str = toString x; in
|
||||
builtins.substring 0 1 str == "/"
|
||||
&& dirOf str == builtins.storeDir
|
||||
else
|
||||
false;
|
||||
|
||||
/* Convert string to int
|
||||
Obviously, it is a bit hacky to use fromJSON that way.
|
||||
/* Parse a string string as an int.
|
||||
|
||||
Type: string -> int
|
||||
|
||||
Example:
|
||||
toInt "1337"
|
||||
@ -517,17 +619,18 @@ rec {
|
||||
toInt "3.14"
|
||||
=> error: floating point JSON numbers are not supported
|
||||
*/
|
||||
# Obviously, it is a bit hacky to use fromJSON this way.
|
||||
toInt = str:
|
||||
let may_be_int = builtins.fromJSON str; in
|
||||
if builtins.isInt may_be_int
|
||||
then may_be_int
|
||||
else throw "Could not convert ${str} to int.";
|
||||
|
||||
/* Read a list of paths from `file', relative to the `rootPath'. Lines
|
||||
beginning with `#' are treated as comments and ignored. Whitespace
|
||||
is significant.
|
||||
/* Read a list of paths from `file`, relative to the `rootPath`.
|
||||
Lines beginning with `#` are treated as comments and ignored.
|
||||
Whitespace is significant.
|
||||
|
||||
NOTE: this function is not performant and should be avoided
|
||||
NOTE: This function is not performant and should be avoided.
|
||||
|
||||
Example:
|
||||
readPathsFromFile /prefix
|
||||
@ -549,6 +652,8 @@ rec {
|
||||
|
||||
/* Read the contents of a file removing the trailing \n
|
||||
|
||||
Type: fileContents :: path -> string
|
||||
|
||||
Example:
|
||||
$ echo "1.0" > ./version
|
||||
|
||||
|
@ -32,6 +32,7 @@ rec {
|
||||
else if final.isUClibc then "uclibc"
|
||||
else if final.isAndroid then "bionic"
|
||||
else if final.isLinux /* default */ then "glibc"
|
||||
else if final.isAvr then "avrlibc"
|
||||
# TODO(@Ericson2314) think more about other operating systems
|
||||
else "native/impure";
|
||||
extensions = {
|
||||
|
@ -99,6 +99,34 @@ rec {
|
||||
riscv64 = riscv "64";
|
||||
riscv32 = riscv "32";
|
||||
|
||||
avr = {
|
||||
config = "avr";
|
||||
};
|
||||
|
||||
arm-embedded = {
|
||||
config = "arm-none-eabi";
|
||||
libc = "newlib";
|
||||
};
|
||||
|
||||
aarch64-embedded = {
|
||||
config = "aarch64-none-elf";
|
||||
libc = "newlib";
|
||||
};
|
||||
|
||||
ppc-embedded = {
|
||||
config = "powerpc-none-eabi";
|
||||
libc = "newlib";
|
||||
};
|
||||
|
||||
i686-embedded = {
|
||||
config = "i686-elf";
|
||||
libc = "newlib";
|
||||
};
|
||||
|
||||
x86_64-embedded = {
|
||||
config = "x86_64-elf";
|
||||
libc = "newlib";
|
||||
};
|
||||
|
||||
#
|
||||
# Darwin
|
||||
|
@ -19,6 +19,7 @@ rec {
|
||||
isRiscV = { cpu = { family = "riscv"; }; };
|
||||
isSparc = { cpu = { family = "sparc"; }; };
|
||||
isWasm = { cpu = { family = "wasm"; }; };
|
||||
isAvr = { cpu = { family = "avr"; }; };
|
||||
|
||||
is32bit = { cpu = { bits = 32; }; };
|
||||
is64bit = { cpu = { bits = 64; }; };
|
||||
|
@ -101,6 +101,8 @@ rec {
|
||||
|
||||
wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
|
||||
wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
|
||||
|
||||
avr = { bits = 8; family = "avr"; };
|
||||
};
|
||||
|
||||
################################################################################
|
||||
@ -117,6 +119,7 @@ rec {
|
||||
apple = {};
|
||||
pc = {};
|
||||
|
||||
none = {};
|
||||
unknown = {};
|
||||
};
|
||||
|
||||
@ -200,6 +203,7 @@ rec {
|
||||
cygnus = {};
|
||||
msvc = {};
|
||||
eabi = {};
|
||||
elf = {};
|
||||
|
||||
androideabi = {};
|
||||
android = {
|
||||
@ -255,9 +259,16 @@ rec {
|
||||
setType "system" components;
|
||||
|
||||
mkSkeletonFromList = l: {
|
||||
"1" = if elemAt l 0 == "avr"
|
||||
then { cpu = elemAt l 0; kernel = "none"; abi = "unknown"; }
|
||||
else throw "Target specification with 1 components is ambiguous";
|
||||
"2" = # We only do 2-part hacks for things Nix already supports
|
||||
if elemAt l 1 == "cygwin"
|
||||
then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
|
||||
else if (elemAt l 1 == "eabi")
|
||||
then { cpu = elemAt l 0; vendor = "none"; kernel = "none"; abi = elemAt l 1; }
|
||||
else if (elemAt l 1 == "elf")
|
||||
then { cpu = elemAt l 0; vendor = "none"; kernel = "none"; abi = elemAt l 1; }
|
||||
else { cpu = elemAt l 0; kernel = elemAt l 1; };
|
||||
"3" = # Awkwards hacks, beware!
|
||||
if elemAt l 1 == "apple"
|
||||
@ -268,6 +279,10 @@ rec {
|
||||
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; abi = "gnu"; }
|
||||
else if hasPrefix "netbsd" (elemAt l 2)
|
||||
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; }
|
||||
else if (elemAt l 2 == "eabi")
|
||||
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "none"; abi = elemAt l 2; }
|
||||
else if (elemAt l 2 == "elf")
|
||||
then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "none"; abi = elemAt l 2; }
|
||||
else throw "Target specification with 3 components is ambiguous";
|
||||
"4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
|
||||
}.${toString (length l)}
|
||||
|
@ -471,6 +471,7 @@ rec {
|
||||
"x86_64-linux" = pc64;
|
||||
"armv5tel-linux" = sheevaplug;
|
||||
"armv6l-linux" = raspberrypi;
|
||||
"armv7a-linux" = armv7l-hf-multiplatform;
|
||||
"armv7l-linux" = armv7l-hf-multiplatform;
|
||||
"aarch64-linux" = aarch64-multiplatform;
|
||||
"mipsel-linux" = fuloong2f_n32;
|
||||
|
@ -112,7 +112,7 @@ runTests {
|
||||
storePathAppendix = isStorePath
|
||||
"${goodPath}/bin/python";
|
||||
nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
|
||||
asPath = isStorePath goodPath;
|
||||
asPath = isStorePath (/. + goodPath);
|
||||
otherPath = isStorePath "/something/else";
|
||||
otherVals = {
|
||||
attrset = isStorePath {};
|
||||
|
117
lib/trivial.nix
117
lib/trivial.nix
@ -9,23 +9,37 @@ rec {
|
||||
|
||||
Type: id :: a -> a
|
||||
*/
|
||||
id = x: x;
|
||||
id =
|
||||
# The value to return
|
||||
x: x;
|
||||
|
||||
/* The constant function
|
||||
Ignores the second argument.
|
||||
Or: Construct a function that always returns a static value.
|
||||
|
||||
Ignores the second argument. If called with only one argument,
|
||||
constructs a function that always returns a static value.
|
||||
|
||||
Type: const :: a -> b -> a
|
||||
Example:
|
||||
let f = const 5; in f 10
|
||||
=> 5
|
||||
*/
|
||||
const = x: y: x;
|
||||
const =
|
||||
# Value to return
|
||||
x:
|
||||
# Value to ignore
|
||||
y: x;
|
||||
|
||||
|
||||
## Named versions corresponding to some builtin operators.
|
||||
|
||||
/* Concatenate two lists */
|
||||
/* Concatenate two lists
|
||||
|
||||
Type: concat :: [a] -> [a] -> [a]
|
||||
|
||||
Example:
|
||||
concat [ 1 2 ] [ 3 4 ]
|
||||
=> [ 1 2 3 4 ]
|
||||
*/
|
||||
concat = x: y: x ++ y;
|
||||
|
||||
/* boolean “or” */
|
||||
@ -53,27 +67,40 @@ rec {
|
||||
bitNot = builtins.sub (-1);
|
||||
|
||||
/* Convert a boolean to a string.
|
||||
Note that toString on a bool returns "1" and "".
|
||||
|
||||
This function uses the strings "true" and "false" to represent
|
||||
boolean values. Calling `toString` on a bool instead returns "1"
|
||||
and "" (sic!).
|
||||
|
||||
Type: boolToString :: bool -> string
|
||||
*/
|
||||
boolToString = b: if b then "true" else "false";
|
||||
|
||||
/* Merge two attribute sets shallowly, right side trumps left
|
||||
|
||||
mergeAttrs :: attrs -> attrs -> attrs
|
||||
|
||||
Example:
|
||||
mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
|
||||
=> { a = 1; b = 3; c = 4; }
|
||||
*/
|
||||
mergeAttrs = x: y: x // y;
|
||||
mergeAttrs =
|
||||
# Left attribute set
|
||||
x:
|
||||
# Right attribute set (higher precedence for equal keys)
|
||||
y: x // y;
|
||||
|
||||
/* Flip the order of the arguments of a binary function.
|
||||
|
||||
Type: flip :: (a -> b -> c) -> (b -> a -> c)
|
||||
|
||||
Example:
|
||||
flip concat [1] [2]
|
||||
=> [ 2 1 ]
|
||||
*/
|
||||
flip = f: a: b: f b a;
|
||||
|
||||
/* Apply function if argument is non-null.
|
||||
/* Apply function if the supplied argument is non-null.
|
||||
|
||||
Example:
|
||||
mapNullable (x: x+1) null
|
||||
@ -81,7 +108,11 @@ rec {
|
||||
mapNullable (x: x+1) 22
|
||||
=> 23
|
||||
*/
|
||||
mapNullable = f: a: if isNull a then a else f a;
|
||||
mapNullable =
|
||||
# Function to call
|
||||
f:
|
||||
# Argument to check for null before passing it to `f`
|
||||
a: if isNull a then a else f a;
|
||||
|
||||
# Pull in some builtins not included elsewhere.
|
||||
inherit (builtins)
|
||||
@ -92,21 +123,27 @@ rec {
|
||||
|
||||
## nixpks version strings
|
||||
|
||||
# The current full nixpkgs version number.
|
||||
/* Returns the current full nixpkgs version number. */
|
||||
version = release + versionSuffix;
|
||||
|
||||
# The current nixpkgs version number as string.
|
||||
/* Returns the current nixpkgs release number as string. */
|
||||
release = lib.strings.fileContents ../.version;
|
||||
|
||||
# The current nixpkgs version suffix as string.
|
||||
/* Returns the current nixpkgs version suffix as string. */
|
||||
versionSuffix =
|
||||
let suffixFile = ../.version-suffix;
|
||||
in if pathExists suffixFile
|
||||
then lib.strings.fileContents suffixFile
|
||||
else "pre-git";
|
||||
|
||||
# Attempt to get the revision nixpkgs is from
|
||||
revisionWithDefault = default:
|
||||
/* Attempts to return the the current revision of nixpkgs and
|
||||
returns the supplied default value otherwise.
|
||||
|
||||
Type: revisionWithDefault :: string -> string
|
||||
*/
|
||||
revisionWithDefault =
|
||||
# Default value to return if revision can not be determined
|
||||
default:
|
||||
let
|
||||
revisionFile = "${toString ./..}/.git-revision";
|
||||
gitRepo = "${toString ./..}/.git";
|
||||
@ -117,14 +154,20 @@ rec {
|
||||
|
||||
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
|
||||
|
||||
# Whether we're being called by nix-shell.
|
||||
/* Determine whether the function is being called from inside a Nix
|
||||
shell.
|
||||
|
||||
Type: inNixShell :: bool
|
||||
*/
|
||||
inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
|
||||
|
||||
|
||||
## Integer operations
|
||||
|
||||
# Return minimum/maximum of two numbers.
|
||||
/* Return minimum of two numbers. */
|
||||
min = x: y: if x < y then x else y;
|
||||
|
||||
/* Return maximum of two numbers. */
|
||||
max = x: y: if x > y then x else y;
|
||||
|
||||
/* Integer modulus
|
||||
@ -158,8 +201,9 @@ rec {
|
||||
second subtype, compare elements of a single subtype with `yes`
|
||||
and `no` respectively.
|
||||
|
||||
Example:
|
||||
Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
|
||||
|
||||
Example:
|
||||
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
|
||||
|
||||
cmp "a" "z" => -1
|
||||
@ -170,31 +214,44 @@ rec {
|
||||
# while
|
||||
compare "fooa" "a" => 1
|
||||
*/
|
||||
splitByAndCompare = p: yes: no: a: b:
|
||||
splitByAndCompare =
|
||||
# Predicate
|
||||
p:
|
||||
# Comparison function if predicate holds for both values
|
||||
yes:
|
||||
# Comparison function if predicate holds for neither value
|
||||
no:
|
||||
# First value to compare
|
||||
a:
|
||||
# Second value to compare
|
||||
b:
|
||||
if p a
|
||||
then if p b then yes a b else -1
|
||||
else if p b then 1 else no a b;
|
||||
|
||||
|
||||
/* Reads a JSON file. */
|
||||
/* Reads a JSON file.
|
||||
|
||||
Type :: path -> any
|
||||
*/
|
||||
importJSON = path:
|
||||
builtins.fromJSON (builtins.readFile path);
|
||||
|
||||
|
||||
## Warnings
|
||||
|
||||
/* See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
|
||||
to expand to Nix builtins that carry metadata so that Nix can filter out
|
||||
the INFO messages without parsing the message string.
|
||||
# See https://github.com/NixOS/nix/issues/749. Eventually we'd like these
|
||||
# to expand to Nix builtins that carry metadata so that Nix can filter out
|
||||
# the INFO messages without parsing the message string.
|
||||
#
|
||||
# Usage:
|
||||
# {
|
||||
# foo = lib.warn "foo is deprecated" oldFoo;
|
||||
# }
|
||||
#
|
||||
# TODO: figure out a clever way to integrate location information from
|
||||
# something like __unsafeGetAttrPos.
|
||||
|
||||
Usage:
|
||||
{
|
||||
foo = lib.warn "foo is deprecated" oldFoo;
|
||||
}
|
||||
|
||||
TODO: figure out a clever way to integrate location information from
|
||||
something like __unsafeGetAttrPos.
|
||||
*/
|
||||
warn = msg: builtins.trace "WARNING: ${msg}";
|
||||
info = msg: builtins.trace "INFO: ${msg}";
|
||||
|
||||
|
@ -143,6 +143,11 @@
|
||||
github = "ahmedtd";
|
||||
name = "Taahir Ahmed";
|
||||
};
|
||||
ahuzik = {
|
||||
email = "ales.guzik@gmail.com";
|
||||
github = "alesguzik";
|
||||
name = "Ales Huzik";
|
||||
};
|
||||
aij = {
|
||||
email = "aij+git@mrph.org";
|
||||
github = "aij";
|
||||
@ -401,6 +406,11 @@
|
||||
github = "AveryLychee";
|
||||
name = "Avery Lychee";
|
||||
};
|
||||
averelld = {
|
||||
email = "averell+nixos@rxd4.com";
|
||||
github = "averelld";
|
||||
name = "averelld";
|
||||
};
|
||||
avnik = {
|
||||
email = "avn@avnik.info";
|
||||
github = "avnik";
|
||||
@ -495,6 +505,11 @@
|
||||
github = "bennofs";
|
||||
name = "Benno Fünfstück";
|
||||
};
|
||||
benpye = {
|
||||
email = "ben@curlybracket.co.uk";
|
||||
github = "benpye";
|
||||
name = "Ben Pye";
|
||||
};
|
||||
benwbooth = {
|
||||
email = "benwbooth@gmail.com";
|
||||
github = "benwbooth";
|
||||
@ -2967,6 +2982,11 @@
|
||||
github = "nequissimus";
|
||||
name = "Tim Steinbach";
|
||||
};
|
||||
nikitavoloboev = {
|
||||
email = "nikita.voloboev@gmail.com";
|
||||
github = "nikitavoloboev";
|
||||
name = "Nikita Voloboev";
|
||||
};
|
||||
nfjinjing = {
|
||||
email = "nfjinjing@gmail.com";
|
||||
github = "nfjinjing";
|
||||
@ -3895,6 +3915,11 @@
|
||||
github = "sjagoe";
|
||||
name = "Simon Jagoe";
|
||||
};
|
||||
sjau = {
|
||||
email = "nixos@sjau.ch";
|
||||
github = "sjau";
|
||||
name = "Stephan Jau";
|
||||
};
|
||||
sjmackenzie = {
|
||||
email = "setori88@gmail.com";
|
||||
github = "sjmackenzie";
|
||||
@ -4143,6 +4168,11 @@
|
||||
github = "taku0";
|
||||
name = "Takuo Yonezawa";
|
||||
};
|
||||
talyz = {
|
||||
email = "kim.lindberger@gmail.com";
|
||||
github = "talyz";
|
||||
name = "Kim Lindberger";
|
||||
};
|
||||
tari = {
|
||||
email = "peter@taricorp.net";
|
||||
github = "tari";
|
||||
@ -4618,6 +4648,11 @@
|
||||
github = "wucke13";
|
||||
name = "Wucke";
|
||||
};
|
||||
wykurz = {
|
||||
email = "wykurz@gmail.com";
|
||||
github = "wykurz";
|
||||
name = "Mateusz Wykurz";
|
||||
};
|
||||
wyvie = {
|
||||
email = "elijahrum@gmail.com";
|
||||
github = "wyvie";
|
||||
|
@ -15,7 +15,7 @@ containers.database =
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ <xref linkend="opt-services.postgresql.enable"/> = true;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql96;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_6;
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
@ -197,10 +197,10 @@ swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
|
||||
pkgs.emacs
|
||||
];
|
||||
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql90;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_10;
|
||||
</programlisting>
|
||||
The latter option definition changes the default PostgreSQL package used
|
||||
by NixOS’s PostgreSQL service to 9.0. For more information on packages,
|
||||
by NixOS’s PostgreSQL service to 10.x. For more information on packages,
|
||||
including how to add new ones, see <xref linkend="sec-custom-packages"/>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
@ -34,13 +34,4 @@
|
||||
Similarly, UDP port ranges can be opened through
|
||||
<xref linkend="opt-networking.firewall.allowedUDPPortRanges"/>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Also of interest is
|
||||
<programlisting>
|
||||
<xref linkend="opt-networking.firewall.allowPing"/> = true;
|
||||
</programlisting>
|
||||
to allow the machine to respond to ping requests. (ICMPv6 pings are always
|
||||
allowed.)
|
||||
</para>
|
||||
</section>
|
||||
|
@ -637,6 +637,11 @@ $ nix-instantiate -E '(import <nixpkgsunstable> {}).gitFull'
|
||||
anyways for clarity.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Groups <literal>kvm</literal> and <literal>render</literal> are introduced now, as systemd requires them.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
@ -97,6 +97,16 @@
|
||||
start org.nixos.nix-daemon</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The Syncthing state and configuration data has been moved from
|
||||
<varname>services.syncthing.dataDir</varname> to the newly defined
|
||||
<varname>services.syncthing.configDir</varname>, which default to
|
||||
<literal>/var/lib/syncthing/.config/syncthing</literal>.
|
||||
This change makes possible to share synced directories using ACLs
|
||||
without Syncthing resetting the permission on every start.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -145,6 +155,56 @@
|
||||
lib.mkForce [];</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
OpenSMTPD has been upgraded to version 6.4.0p1. This release makes
|
||||
backwards-incompatible changes to the configuration file format. See
|
||||
<command>man smtpd.conf</command> for more information on the new file
|
||||
format.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The versioned <varname>postgresql</varname> have been renamed to use
|
||||
underscore number seperators. For example, <varname>postgresql96</varname>
|
||||
has been renamed to <varname>postgresql_9_6</varname>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Package <literal>consul-ui</literal> and passthrough <literal>consul.ui</literal> have been removed.
|
||||
The package <literal>consul</literal> now uses upstream releases that vendor the UI into the binary.
|
||||
See <link xlink:href="https://github.com/NixOS/nixpkgs/pull/48714#issuecomment-433454834">#48714</link>
|
||||
for details.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Slurm introduces the new option
|
||||
<literal>services.slurm.stateSaveLocation</literal>,
|
||||
which is now set to <literal>/var/spool/slurm</literal> by default
|
||||
(instead of <literal>/var/spool</literal>).
|
||||
Make sure to move all files to the new directory or to set the option accordingly.
|
||||
</para>
|
||||
<para>
|
||||
The slurmctld now runs as user <literal>slurm</literal> instead of <literal>root</literal>.
|
||||
If you want to keep slurmctld running as <literal>root</literal>, set
|
||||
<literal>services.slurm.user = root</literal>.
|
||||
</para>
|
||||
<para>
|
||||
The options <literal>services.slurm.nodeName</literal> and
|
||||
<literal>services.slurm.partitionName</literal> are now sets of
|
||||
strings to correctly reflect that fact that each of these
|
||||
options can occour more than once in the configuration.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>solr</literal> package has been upgraded from 4.10.3 to 7.5.0 and has undergone
|
||||
some major changes. The <literal>services.solr</literal> module has been updated to reflect
|
||||
these changes. Please review http://lucene.apache.org/solr/ carefully before upgrading.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
@ -163,6 +223,15 @@
|
||||
Matomo version.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The deprecated <literal>truecrypt</literal> package has been removed
|
||||
and <literal>truecrypt</literal> attribute is now an alias for
|
||||
<literal>veracrypt</literal>. VeraCrypt is backward-compatible with
|
||||
TrueCrypt volumes. Note that <literal>cryptsetup</literal> also
|
||||
supports loading TrueCrypt volumes.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -53,7 +53,8 @@ in rec {
|
||||
inherit prefix check;
|
||||
modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ];
|
||||
args = extraArgs;
|
||||
specialArgs = { modulesPath = ../modules; } // specialArgs;
|
||||
specialArgs =
|
||||
{ modulesPath = builtins.toString ../modules; } // specialArgs;
|
||||
}) config options;
|
||||
|
||||
# These are the extra arguments passed to every module. In
|
||||
|
@ -250,7 +250,8 @@ sub connect {
|
||||
$self->start;
|
||||
|
||||
local $SIG{ALRM} = sub { die "timed out waiting for the VM to connect\n"; };
|
||||
alarm 300;
|
||||
# 50 minutes -- increased as a test, see #49441
|
||||
alarm 3000;
|
||||
readline $self->{socket} or die "the VM quit before connecting\n";
|
||||
alarm 0;
|
||||
|
||||
|
@ -16,6 +16,13 @@ let
|
||||
resolvconfOptions = cfg.resolvconfOptions
|
||||
++ optional cfg.dnsSingleRequest "single-request"
|
||||
++ optional cfg.dnsExtensionMechanism "edns0";
|
||||
|
||||
|
||||
localhostMapped4 = cfg.hosts ? "127.0.0.1" && elem "localhost" cfg.hosts."127.0.0.1";
|
||||
localhostMapped6 = cfg.hosts ? "::1" && elem "localhost" cfg.hosts."::1";
|
||||
|
||||
localhostMultiple = any (elem "localhost") (attrValues (removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]));
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
@ -23,8 +30,7 @@ in
|
||||
options = {
|
||||
|
||||
networking.hosts = lib.mkOption {
|
||||
type = types.attrsOf ( types.listOf types.str );
|
||||
default = {};
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
example = literalExample ''
|
||||
{
|
||||
"127.0.0.1" = [ "foo.bar.baz" ];
|
||||
@ -192,6 +198,29 @@ in
|
||||
|
||||
config = {
|
||||
|
||||
assertions = [{
|
||||
assertion = localhostMapped4;
|
||||
message = ''`networking.hosts` doesn't map "127.0.0.1" to "localhost"'';
|
||||
} {
|
||||
assertion = !cfg.enableIPv6 || localhostMapped6;
|
||||
message = ''`networking.hosts` doesn't map "::1" to "localhost"'';
|
||||
} {
|
||||
assertion = !localhostMultiple;
|
||||
message = ''
|
||||
`networking.hosts` maps "localhost" to something other than "127.0.0.1"
|
||||
or "::1". This will break some applications. Please use
|
||||
`networking.extraHosts` if you really want to add such a mapping.
|
||||
'';
|
||||
}];
|
||||
|
||||
networking.hosts = {
|
||||
"127.0.0.1" = [ "localhost" ];
|
||||
} // optionalAttrs (cfg.hostName != "") {
|
||||
"127.0.1.1" = [ cfg.hostName ];
|
||||
} // optionalAttrs cfg.enableIPv6 {
|
||||
"::1" = [ "localhost" ];
|
||||
};
|
||||
|
||||
environment.etc =
|
||||
{ # /etc/services: TCP/UDP port assignments.
|
||||
"services".source = pkgs.iana-etc + "/etc/services";
|
||||
@ -199,29 +228,14 @@ in
|
||||
# /etc/protocols: IP protocol numbers.
|
||||
"protocols".source = pkgs.iana-etc + "/etc/protocols";
|
||||
|
||||
# /etc/rpc: RPC program numbers.
|
||||
"rpc".source = pkgs.glibc.out + "/etc/rpc";
|
||||
|
||||
# /etc/hosts: Hostname-to-IP mappings.
|
||||
"hosts".text =
|
||||
let oneToString = set : ip : ip + " " + concatStringsSep " " ( getAttr ip set );
|
||||
allToString = set : concatMapStringsSep "\n" ( oneToString set ) ( attrNames set );
|
||||
userLocalHosts = optionalString
|
||||
( builtins.hasAttr "127.0.0.1" cfg.hosts )
|
||||
( concatStringsSep " " ( remove "localhost" cfg.hosts."127.0.0.1" ));
|
||||
userLocalHosts6 = optionalString
|
||||
( builtins.hasAttr "::1" cfg.hosts )
|
||||
( concatStringsSep " " ( remove "localhost" cfg.hosts."::1" ));
|
||||
otherHosts = allToString ( removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]);
|
||||
in
|
||||
''
|
||||
127.0.0.1 ${userLocalHosts} localhost
|
||||
${optionalString cfg.enableIPv6 ''
|
||||
::1 ${userLocalHosts6} localhost
|
||||
''}
|
||||
${otherHosts}
|
||||
${cfg.extraHosts}
|
||||
'';
|
||||
"hosts".text = let
|
||||
oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip};
|
||||
allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set);
|
||||
in ''
|
||||
${allToString cfg.hosts}
|
||||
${cfg.extraHosts}
|
||||
'';
|
||||
|
||||
# /etc/host.conf: resolver configuration file
|
||||
"host.conf".text = cfg.hostConf;
|
||||
@ -251,6 +265,9 @@ in
|
||||
"resolv.conf".source = "${pkgs.systemd}/lib/systemd/resolv.conf";
|
||||
} // optionalAttrs (config.services.resolved.enable && dnsmasqResolve) {
|
||||
"dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
|
||||
} // optionalAttrs (pkgs.stdenv.hostPlatform.libc == "glibc") {
|
||||
# /etc/rpc: RPC program numbers.
|
||||
"rpc".source = pkgs.glibc.out + "/etc/rpc";
|
||||
};
|
||||
|
||||
networking.proxy.envVars =
|
||||
@ -296,4 +313,4 @@ in
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ let
|
||||
pkgs.diffutils
|
||||
pkgs.findutils
|
||||
pkgs.gawk
|
||||
pkgs.glibc # for ldd, getent
|
||||
pkgs.stdenv.cc.libc
|
||||
pkgs.getent
|
||||
pkgs.getconf
|
||||
pkgs.gnugrep
|
||||
pkgs.gnupatch
|
||||
pkgs.gnused
|
||||
|
@ -7,4 +7,6 @@
|
||||
imports =
|
||||
[ ./installation-cd-base.nix
|
||||
];
|
||||
|
||||
fonts.fontconfig.enable = false;
|
||||
}
|
||||
|
@ -22,4 +22,42 @@ with lib;
|
||||
|
||||
powerManagement.enable = false;
|
||||
system.stateVersion = mkDefault "18.03";
|
||||
|
||||
installer.cloneConfigExtra = ''
|
||||
# Let demo build as a trusted user.
|
||||
# nix.trustedUsers = [ "demo" ];
|
||||
|
||||
# Mount a VirtualBox shared folder.
|
||||
# This is configurable in the VirtualBox menu at
|
||||
# Machine / Settings / Shared Folders.
|
||||
# fileSystems."/mnt" = {
|
||||
# fsType = "vboxsf";
|
||||
# device = "nameofdevicetomount";
|
||||
# options = [ "rw" ];
|
||||
# };
|
||||
|
||||
# By default, the NixOS VirtualBox demo image includes SDDM and Plasma.
|
||||
# If you prefer another desktop manager or display manager, you may want
|
||||
# to disable the default.
|
||||
# services.xserver.desktopManager.plasma5.enable = lib.mkForce false;
|
||||
# services.xserver.displayManager.sddm.enable = lib.mkForce false;
|
||||
|
||||
# Enable GDM/GNOME by uncommenting above two lines and two lines below.
|
||||
# services.xserver.displayManager.gdm.enable = true;
|
||||
# services.xserver.desktopManager.gnome3.enable = true;
|
||||
|
||||
# Set your time zone.
|
||||
# time.timeZone = "Europe/Amsterdam";
|
||||
|
||||
# List packages installed in system profile. To search, run:
|
||||
# \$ nix search wget
|
||||
# environment.systemPackages = with pkgs; [
|
||||
# wget vim
|
||||
# ];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
# services.openssh.enable = true;
|
||||
|
||||
system.stateVersion = mkDefault "18.03";
|
||||
'';
|
||||
}
|
||||
|
@ -331,6 +331,9 @@
|
||||
zeronet = 304;
|
||||
lirc = 305;
|
||||
lidarr = 306;
|
||||
slurm = 307;
|
||||
kapacitor = 308;
|
||||
solr = 309;
|
||||
|
||||
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
|
||||
|
||||
@ -622,6 +625,9 @@
|
||||
zeronet = 304;
|
||||
lirc = 305;
|
||||
lidarr = 306;
|
||||
slurm = 307;
|
||||
kapacitor = 308;
|
||||
solr = 309;
|
||||
|
||||
# When adding a gid, make sure it doesn't match an existing
|
||||
# uid. Users and groups with the same name should have equal
|
||||
|
@ -126,6 +126,7 @@
|
||||
./programs/udevil.nix
|
||||
./programs/venus.nix
|
||||
./programs/vim.nix
|
||||
./programs/wavemon.nix
|
||||
./programs/way-cooler.nix
|
||||
./programs/wireshark.nix
|
||||
./programs/xfs_quota.nix
|
||||
@ -432,6 +433,7 @@
|
||||
./services/monitoring/hdaps.nix
|
||||
./services/monitoring/heapster.nix
|
||||
./services/monitoring/incron.nix
|
||||
./services/monitoring/kapacitor.nix
|
||||
./services/monitoring/longview.nix
|
||||
./services/monitoring/monit.nix
|
||||
./services/monitoring/munin.nix
|
||||
|
@ -7,7 +7,7 @@
|
||||
# Include some utilities that are useful for installing or repairing
|
||||
# the system.
|
||||
environment.systemPackages = [
|
||||
pkgs.w3m-nox # needed for the manual anyway
|
||||
pkgs.w3m-nographics # needed for the manual anyway
|
||||
pkgs.testdisk # useful for repairing boot problems
|
||||
pkgs.ms-sys # for writing Microsoft boot sectors / MBRs
|
||||
pkgs.efibootmgr
|
||||
@ -19,6 +19,9 @@
|
||||
pkgs.cryptsetup # needed for dm-crypt volumes
|
||||
pkgs.mkpasswd # for generating password files
|
||||
|
||||
# Some text editors.
|
||||
pkgs.vim
|
||||
|
||||
# Some networking tools.
|
||||
pkgs.fuse
|
||||
pkgs.fuse3
|
||||
|
@ -48,6 +48,8 @@ let
|
||||
|
||||
{
|
||||
imports = [ ${toString config.installer.cloneConfigIncludes} ];
|
||||
|
||||
${config.installer.cloneConfigExtra}
|
||||
}
|
||||
'';
|
||||
|
||||
@ -73,6 +75,13 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
installer.cloneConfigExtra = mkOption {
|
||||
default = "";
|
||||
description = ''
|
||||
Extra text to include in the cloned configuration.nix included in this
|
||||
installer.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
@ -63,7 +63,7 @@ with lib;
|
||||
# Tell the Nix evaluator to garbage collect more aggressively.
|
||||
# This is desirable in memory-constrained environments that don't
|
||||
# (yet) have swap set up.
|
||||
environment.variables.GC_INITIAL_HEAP_SIZE = "100000";
|
||||
environment.variables.GC_INITIAL_HEAP_SIZE = "1M";
|
||||
|
||||
# Make the installer more likely to succeed in low memory
|
||||
# environments. The kernel's overcommit heustistics bite us
|
||||
@ -87,9 +87,6 @@ with lib;
|
||||
# console less cumbersome if the machine has a public IP.
|
||||
networking.firewall.logRefusedConnections = mkDefault false;
|
||||
|
||||
environment.systemPackages = [ pkgs.vim ];
|
||||
|
||||
|
||||
# Allow the user to log in as root without a password.
|
||||
users.users.root.initialHashedPassword = "";
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ let
|
||||
# programmable completion. If we do, enable all modules installed in
|
||||
# the system and user profile in obsolete /etc/bash_completion.d/
|
||||
# directories. Bash loads completions in all
|
||||
# $XDG_DATA_DIRS/share/bash-completion/completions/
|
||||
# $XDG_DATA_DIRS/bash-completion/completions/
|
||||
# on demand, so they do not need to be sourced here.
|
||||
if shopt -q progcomp &>/dev/null; then
|
||||
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
|
||||
|
@ -13,7 +13,7 @@ with lib;
|
||||
# Set up the per-user profile.
|
||||
mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR"
|
||||
if [ "$(stat --printf '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then
|
||||
echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR, should be $(id -u)" >&2
|
||||
echo "WARNING: the per-user profile dir $NIX_USER_PROFILE_DIR should belong to user id $(id -u)" >&2
|
||||
fi
|
||||
|
||||
if [ -w "$HOME" ]; then
|
||||
@ -35,7 +35,7 @@ with lib;
|
||||
NIX_USER_GCROOTS_DIR="/nix/var/nix/gcroots/per-user/$USER"
|
||||
mkdir -m 0755 -p "$NIX_USER_GCROOTS_DIR"
|
||||
if [ "$(stat --printf '%u' "$NIX_USER_GCROOTS_DIR")" != "$(id -u)" ]; then
|
||||
echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR, should be $(id -u)" >&2
|
||||
echo "WARNING: the per-user gcroots dir $NIX_USER_GCROOTS_DIR should belong to user id $(id -u)" >&2
|
||||
fi
|
||||
|
||||
# Set up a default Nix expression from which to install stuff.
|
||||
|
@ -5,6 +5,15 @@ with lib;
|
||||
let
|
||||
cfg = config.programs.sway-beta;
|
||||
swayPackage = cfg.package;
|
||||
|
||||
swayWrapped = pkgs.writeShellScriptBin "sway" ''
|
||||
${cfg.extraSessionCommands}
|
||||
exec ${pkgs.dbus.dbus-launch} --exit-with-session ${swayPackage}/bin/sway
|
||||
'';
|
||||
swayJoined = pkgs.symlinkJoin {
|
||||
name = "sway-joined";
|
||||
paths = [ swayWrapped swayPackage ];
|
||||
};
|
||||
in {
|
||||
options.programs.sway-beta = {
|
||||
enable = mkEnableOption ''
|
||||
@ -20,13 +29,30 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
extraSessionCommands = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
# needs qt5.qtwayland in systemPackages
|
||||
export QT_QPA_PLATFORM=wayland
|
||||
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
|
||||
# Fix for some Java AWT applications (e.g. Android Studio),
|
||||
# use this if they aren't displayed properly:
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
'';
|
||||
description = ''
|
||||
Shell commands executed just before Sway is started.
|
||||
'';
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = with pkgs; [
|
||||
xwayland dmenu
|
||||
xwayland rxvt_unicode dmenu
|
||||
];
|
||||
defaultText = literalExample ''
|
||||
with pkgs; [ xwayland dmenu ];
|
||||
with pkgs; [ xwayland rxvt_unicode dmenu ];
|
||||
'';
|
||||
example = literalExample ''
|
||||
with pkgs; [
|
||||
@ -42,7 +68,7 @@ in {
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ swayPackage ] ++ cfg.extraPackages;
|
||||
environment.systemPackages = [ swayJoined ] ++ cfg.extraPackages;
|
||||
security.pam.services.swaylock = {};
|
||||
hardware.opengl.enable = mkDefault true;
|
||||
fonts.enableDefaultFonts = mkDefault true;
|
||||
@ -51,4 +77,3 @@ in {
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ gnidorah primeos colemickens ];
|
||||
}
|
||||
|
||||
|
28
nixos/modules/programs/wavemon.nix
Normal file
28
nixos/modules/programs/wavemon.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.wavemon;
|
||||
in {
|
||||
options = {
|
||||
programs.wavemon = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to add wavemon to the global environment and configure a
|
||||
setcap wrapper for it.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [ wavemon ];
|
||||
security.wrappers.wavemon = {
|
||||
source = "${pkgs.wavemon}/bin/wavemon";
|
||||
capabilities = "cap_net_admin+ep";
|
||||
};
|
||||
};
|
||||
}
|
@ -28,7 +28,10 @@ with lib;
|
||||
(config:
|
||||
let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config;
|
||||
in if enabled then [ pkgs.gutenprint ] else [ ]))
|
||||
(mkRenamedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ])
|
||||
(mkChangedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ]
|
||||
(config:
|
||||
let value = getAttrFromPath [ "services" "ddclient" "domain" ] config;
|
||||
in if value != "" then [ value ] else []))
|
||||
(mkRemovedOptionModule [ "services" "ddclient" "homeDir" ] "")
|
||||
(mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
|
||||
(mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
|
||||
|
@ -28,7 +28,7 @@ with lib;
|
||||
capability setuid,
|
||||
network inet raw,
|
||||
|
||||
${pkgs.glibc.out}/lib/*.so mr,
|
||||
${pkgs.stdenv.cc.libc.out}/lib/*.so mr,
|
||||
${pkgs.libcap.lib}/lib/libcap.so* mr,
|
||||
${pkgs.attr.out}/lib/libattr.so* mr,
|
||||
|
||||
|
@ -170,4 +170,6 @@ in {
|
||||
'';
|
||||
}) cfg.params;
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ ekleog ];
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ with lib;
|
||||
KERNEL=="random", TAG+="systemd"
|
||||
SUBSYSTEM=="cpu", ENV{MODALIAS}=="cpu:type:x86,*feature:*009E*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"
|
||||
KERNEL=="hw_random", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"
|
||||
${if config.services.tcsd.enable then "" else ''KERNEL=="tpm0", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"''}
|
||||
'';
|
||||
|
||||
systemd.services.rngd = {
|
||||
@ -30,8 +29,7 @@ with lib;
|
||||
|
||||
description = "Hardware RNG Entropy Gatherer Daemon";
|
||||
|
||||
serviceConfig.ExecStart = "${pkgs.rng-tools}/sbin/rngd -f -v" +
|
||||
(if config.services.tcsd.enable then " --no-tpm=1" else "");
|
||||
serviceConfig.ExecStart = "${pkgs.rng-tools}/sbin/rngd -f -v";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -53,6 +53,9 @@ in
|
||||
Type = "notify";
|
||||
NotifyAccess = "all";
|
||||
};
|
||||
restartTriggers = [
|
||||
config.environment.etc."salt/master".source
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,6 @@ let
|
||||
# Default is in /etc/salt/pki/minion
|
||||
pki_dir = "/var/lib/salt/pki/minion";
|
||||
} cfg.configuration;
|
||||
configDir = pkgs.writeTextDir "minion" (builtins.toJSON fullConfig);
|
||||
|
||||
in
|
||||
|
||||
@ -28,15 +27,24 @@ in
|
||||
default = {};
|
||||
description = ''
|
||||
Salt minion configuration as Nix attribute set.
|
||||
See <link xlink:href="https://docs.saltstack.com/en/latest/ref/configuration/minion.html"/>
|
||||
for details.
|
||||
See <link xlink:href="https://docs.saltstack.com/en/latest/ref/configuration/minion.html"/>
|
||||
for details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [ salt ];
|
||||
environment = {
|
||||
# Set this up in /etc/salt/minion so `salt-call`, etc. work.
|
||||
# The alternatives are
|
||||
# - passing --config-dir to all salt commands, not just the minion unit,
|
||||
# - setting aglobal environment variable.
|
||||
etc."salt/minion".source = pkgs.writeText "minion" (
|
||||
builtins.toJSON fullConfig
|
||||
);
|
||||
systemPackages = with pkgs; [ salt ];
|
||||
};
|
||||
systemd.services.salt-minion = {
|
||||
description = "Salt Minion";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@ -45,11 +53,14 @@ in
|
||||
utillinux
|
||||
];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.salt}/bin/salt-minion --config-dir=${configDir}";
|
||||
ExecStart = "${pkgs.salt}/bin/salt-minion";
|
||||
LimitNOFILE = 8192;
|
||||
Type = "notify";
|
||||
NotifyAccess = "all";
|
||||
};
|
||||
restartTriggers = [
|
||||
config.environment.etc."salt/minion".source
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -6,13 +6,18 @@ let
|
||||
|
||||
cfg = config.services.slurm;
|
||||
# configuration file can be generated by http://slurm.schedmd.com/configurator.html
|
||||
|
||||
defaultUser = "slurm";
|
||||
|
||||
configFile = pkgs.writeTextDir "slurm.conf"
|
||||
''
|
||||
ClusterName=${cfg.clusterName}
|
||||
StateSaveLocation=${cfg.stateSaveLocation}
|
||||
SlurmUser=${cfg.user}
|
||||
${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''}
|
||||
${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
|
||||
${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''}
|
||||
${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''}
|
||||
${toString (map (x: "NodeName=${x}\n") cfg.nodeName)}
|
||||
${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)}
|
||||
PlugStackConfig=${plugStackConfig}
|
||||
ProctrackType=${cfg.procTrackType}
|
||||
${cfg.extraConfig}
|
||||
@ -24,12 +29,19 @@ let
|
||||
${cfg.extraPlugstackConfig}
|
||||
'';
|
||||
|
||||
|
||||
cgroupConfig = pkgs.writeTextDir "cgroup.conf"
|
||||
''
|
||||
${cfg.extraCgroupConfig}
|
||||
'';
|
||||
|
||||
slurmdbdConf = pkgs.writeTextDir "slurmdbd.conf"
|
||||
''
|
||||
DbdHost=${cfg.dbdserver.dbdHost}
|
||||
SlurmUser=${cfg.user}
|
||||
StorageType=accounting_storage/mysql
|
||||
${cfg.dbdserver.extraConfig}
|
||||
'';
|
||||
|
||||
# slurm expects some additional config files to be
|
||||
# in the same directory as slurm.conf
|
||||
etcSlurm = pkgs.symlinkJoin {
|
||||
@ -43,6 +55,8 @@ in
|
||||
|
||||
###### interface
|
||||
|
||||
meta.maintainers = [ maintainers.markuskowa ];
|
||||
|
||||
options = {
|
||||
|
||||
services.slurm = {
|
||||
@ -60,6 +74,27 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
dbdserver = {
|
||||
enable = mkEnableOption "SlurmDBD service";
|
||||
|
||||
dbdHost = mkOption {
|
||||
type = types.str;
|
||||
default = config.networking.hostName;
|
||||
description = ''
|
||||
Hostname of the machine where <literal>slurmdbd</literal>
|
||||
is running (i.e. name returned by <literal>hostname -s</literal>).
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra configuration for <literal>slurmdbd.conf</literal>
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
client = {
|
||||
enable = mkEnableOption "slurm client daemon";
|
||||
};
|
||||
@ -116,9 +151,9 @@ in
|
||||
};
|
||||
|
||||
nodeName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "linux[1-32] CPUs=1 State=UNKNOWN";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = literalExample ''[ "linux[1-32] CPUs=1 State=UNKNOWN" ];'';
|
||||
description = ''
|
||||
Name that SLURM uses to refer to a node (or base partition for BlueGene
|
||||
systems). Typically this would be the string that "/bin/hostname -s"
|
||||
@ -127,9 +162,9 @@ in
|
||||
};
|
||||
|
||||
partitionName = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP";
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = literalExample ''[ "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP" ];'';
|
||||
description = ''
|
||||
Name by which the partition may be referenced. Note that now you have
|
||||
to write the partition's parameters after the name.
|
||||
@ -150,7 +185,7 @@ in
|
||||
};
|
||||
|
||||
procTrackType = mkOption {
|
||||
type = types.string;
|
||||
type = types.str;
|
||||
default = "proctrack/linuxproc";
|
||||
description = ''
|
||||
Plugin to be used for process tracking on a job step basis.
|
||||
@ -159,6 +194,25 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
stateSaveLocation = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/spool/slurmctld";
|
||||
description = ''
|
||||
Directory into which the Slurm controller, slurmctld, saves its state.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
description = ''
|
||||
Set this option when you want to run the slurmctld daemon
|
||||
as something else than the default slurm user "slurm".
|
||||
Note that the UID of this user needs to be the same
|
||||
on all nodes.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
@ -184,6 +238,8 @@ in
|
||||
used when <literal>procTrackType=proctrack/cgroup</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
@ -220,12 +276,24 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
in mkIf (cfg.enableStools || cfg.client.enable || cfg.server.enable) {
|
||||
in mkIf ( cfg.enableStools ||
|
||||
cfg.client.enable ||
|
||||
cfg.server.enable ||
|
||||
cfg.dbdserver.enable ) {
|
||||
|
||||
environment.systemPackages = [ wrappedSlurm ];
|
||||
|
||||
services.munge.enable = mkDefault true;
|
||||
|
||||
# use a static uid as default to ensure it is the same on all nodes
|
||||
users.users.slurm = mkIf (cfg.user == defaultUser) {
|
||||
name = defaultUser;
|
||||
group = "slurm";
|
||||
uid = config.ids.uids.slurm;
|
||||
};
|
||||
|
||||
users.groups.slurm.gid = config.ids.uids.slurm;
|
||||
|
||||
systemd.services.slurmd = mkIf (cfg.client.enable) {
|
||||
path = with pkgs; [ wrappedSlurm coreutils ]
|
||||
++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
|
||||
@ -261,6 +329,29 @@ in
|
||||
PIDFile = "/run/slurmctld.pid";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
mkdir -p ${cfg.stateSaveLocation}
|
||||
chown -R ${cfg.user}:slurm ${cfg.stateSaveLocation}
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.slurmdbd = mkIf (cfg.dbdserver.enable) {
|
||||
path = with pkgs; [ wrappedSlurm munge coreutils ];
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "munged.service" "mysql.service" ];
|
||||
requires = [ "munged.service" "mysql.service" ];
|
||||
|
||||
# slurm strips the last component off the path
|
||||
environment.SLURM_CONF = "${slurmdbdConf}/slurm.conf";
|
||||
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${cfg.package}/bin/slurmdbd";
|
||||
PIDFile = "/run/slurmdbd.pid";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -55,7 +55,7 @@ in
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
example = literalExample "pkgs.postgresql96";
|
||||
example = literalExample "pkgs.postgresql_9_6";
|
||||
description = ''
|
||||
PostgreSQL package to use.
|
||||
'';
|
||||
@ -118,7 +118,7 @@ in
|
||||
extraPlugins = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql94; }) ]";
|
||||
example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql_9_4; }) ]";
|
||||
description = ''
|
||||
When this list contains elements a new store path is created.
|
||||
PostgreSQL and the elements are symlinked into it. Then pg_config,
|
||||
@ -167,9 +167,9 @@ in
|
||||
# Note: when changing the default, make it conditional on
|
||||
# ‘system.stateVersion’ to maintain compatibility with existing
|
||||
# systems!
|
||||
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql96
|
||||
else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql95
|
||||
else pkgs.postgresql94);
|
||||
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql_9_6
|
||||
else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql_9_5
|
||||
else pkgs.postgresql_9_4);
|
||||
|
||||
services.postgresql.dataDir =
|
||||
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}"
|
||||
@ -271,5 +271,5 @@ in
|
||||
};
|
||||
|
||||
meta.doc = ./postgresql.xml;
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ thoughtpolice ];
|
||||
}
|
||||
|
@ -27,12 +27,12 @@
|
||||
<filename>configuration.nix</filename>:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.postgresql.enable"/> = true;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql94;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_4;
|
||||
</programlisting>
|
||||
Note that you are required to specify the desired version of PostgreSQL
|
||||
(e.g. <literal>pkgs.postgresql94</literal>). Since upgrading your PostgreSQL
|
||||
version requires a database dump and reload (see below), NixOS cannot
|
||||
provide a default value for
|
||||
(e.g. <literal>pkgs.postgresql_9_4</literal>). Since upgrading your
|
||||
PostgreSQL version requires a database dump and reload (see below), NixOS
|
||||
cannot provide a default value for
|
||||
<xref linkend="opt-services.postgresql.package"/> such as the most recent
|
||||
release of PostgreSQL.
|
||||
</para>
|
||||
|
@ -56,6 +56,32 @@ in
|
||||
{ Type = "dbus";
|
||||
BusName = "org.freedesktop.UPower";
|
||||
ExecStart = "@${cfg.package}/libexec/upowerd upowerd";
|
||||
Restart = "on-failure";
|
||||
# Upstream lockdown:
|
||||
# Filesystem lockdown
|
||||
ProtectSystem = "strict";
|
||||
# Needed by keyboard backlight support
|
||||
ProtectKernelTunables = false;
|
||||
ProtectControlGroups = true;
|
||||
ReadWritePaths = "/var/lib/upower";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
|
||||
# Network
|
||||
# PrivateNetwork=true would block udev's netlink socket
|
||||
RestrictAddressFamilies = "AF_UNIX AF_NETLINK";
|
||||
|
||||
# Execute Mappings
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
||||
# Modules
|
||||
ProtectKernelModules = true;
|
||||
|
||||
# Real-time
|
||||
RestrictRealtime = true;
|
||||
|
||||
# Privilege escalation
|
||||
NoNewPrivileges = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -176,4 +176,6 @@ in
|
||||
}
|
||||
) cfg.instances);
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ ekleog ];
|
||||
}
|
||||
|
@ -115,4 +115,6 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ ekleog ];
|
||||
}
|
||||
|
@ -127,11 +127,15 @@ let
|
||||
options {
|
||||
pidfile = "$RUNDIR/rspamd.pid";
|
||||
.include "$CONFDIR/options.inc"
|
||||
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/options.inc"
|
||||
.include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/options.inc"
|
||||
}
|
||||
|
||||
logging {
|
||||
type = "syslog";
|
||||
.include "$CONFDIR/logging.inc"
|
||||
.include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/logging.inc"
|
||||
.include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/logging.inc"
|
||||
}
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (name: value: ''
|
||||
@ -149,6 +153,41 @@ let
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
rspamdDir = pkgs.linkFarm "etc-rspamd-dir" (
|
||||
(mapAttrsToList (name: file: { name = "local.d/${name}"; path = file.source; }) cfg.locals) ++
|
||||
(mapAttrsToList (name: file: { name = "override.d/${name}"; path = file.source; }) cfg.overrides) ++
|
||||
(optional (cfg.localLuaRules != null) { name = "rspamd.local.lua"; path = cfg.localLuaRules; }) ++
|
||||
[ { name = "rspamd.conf"; path = rspamdConfFile; } ]
|
||||
);
|
||||
|
||||
configFileModule = prefix: { name, config, ... }: {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether this file ${prefix} should be generated. This
|
||||
option allows specific ${prefix} files to be disabled.
|
||||
'';
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.lines;
|
||||
description = "Text of the file.";
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
type = types.path;
|
||||
description = "Path of the source file.";
|
||||
};
|
||||
};
|
||||
config = {
|
||||
source = mkIf (config.text != null) (
|
||||
let name' = "rspamd-${prefix}-" + baseNameOf name;
|
||||
in mkDefault (pkgs.writeText name' config.text));
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
@ -167,6 +206,41 @@ in
|
||||
description = "Whether to run the rspamd daemon in debug mode.";
|
||||
};
|
||||
|
||||
locals = mkOption {
|
||||
type = with types; loaOf (submodule (configFileModule "locals"));
|
||||
default = {};
|
||||
description = ''
|
||||
Local configuration files, written into <filename>/etc/rspamd/local.d/{name}</filename>.
|
||||
'';
|
||||
example = literalExample ''
|
||||
{ "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
|
||||
"arc.conf".text = "allow_envfrom_empty = true;";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
overrides = mkOption {
|
||||
type = with types; loaOf (submodule (configFileModule "overrides"));
|
||||
default = {};
|
||||
description = ''
|
||||
Overridden configuration files, written into <filename>/etc/rspamd/override.d/{name}</filename>.
|
||||
'';
|
||||
example = literalExample ''
|
||||
{ "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
|
||||
"arc.conf".text = "allow_envfrom_empty = true;";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
localLuaRules = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
description = ''
|
||||
Path of file to link to <filename>/etc/rspamd/rspamd.local.lua</filename> for local
|
||||
rules written in Lua
|
||||
'';
|
||||
};
|
||||
|
||||
workers = mkOption {
|
||||
type = with types; attrsOf (submodule workerOpts);
|
||||
description = ''
|
||||
@ -242,16 +316,17 @@ in
|
||||
gid = config.ids.gids.rspamd;
|
||||
};
|
||||
|
||||
environment.etc."rspamd.conf".source = rspamdConfFile;
|
||||
environment.etc."rspamd".source = rspamdDir;
|
||||
|
||||
systemd.services.rspamd = {
|
||||
description = "Rspamd Service";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
restartTriggers = [ rspamdDir ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
|
||||
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c /etc/rspamd/rspamd.conf -f";
|
||||
Restart = "always";
|
||||
RuntimeDirectory = "rspamd";
|
||||
PrivateTmp = true;
|
||||
|
@ -14,15 +14,16 @@ let
|
||||
pathUrlQuote = url: replaceStrings ["/"] ["%2F"] url;
|
||||
pgSuperUser = config.services.postgresql.superUser;
|
||||
|
||||
databaseYml = ''
|
||||
production:
|
||||
adapter: postgresql
|
||||
database: ${cfg.databaseName}
|
||||
host: ${cfg.databaseHost}
|
||||
password: ${cfg.databasePassword}
|
||||
username: ${cfg.databaseUsername}
|
||||
encoding: utf8
|
||||
'';
|
||||
databaseConfig = {
|
||||
production = {
|
||||
adapter = "postgresql";
|
||||
database = cfg.databaseName;
|
||||
host = cfg.databaseHost;
|
||||
password = cfg.databasePassword;
|
||||
username = cfg.databaseUsername;
|
||||
encoding = "utf8";
|
||||
};
|
||||
};
|
||||
|
||||
gitalyToml = pkgs.writeText "gitaly.toml" ''
|
||||
socket_path = "${lib.escape ["\""] gitalySocket}"
|
||||
@ -45,35 +46,31 @@ let
|
||||
'') gitlabConfig.production.repositories.storages))}
|
||||
'';
|
||||
|
||||
gitlabShellYml = ''
|
||||
user: ${cfg.user}
|
||||
gitlab_url: "http+unix://${pathUrlQuote gitlabSocket}"
|
||||
http_settings:
|
||||
self_signed_cert: false
|
||||
repos_path: "${cfg.statePath}/repositories"
|
||||
secret_file: "${cfg.statePath}/config/gitlab_shell_secret"
|
||||
log_file: "${cfg.statePath}/log/gitlab-shell.log"
|
||||
custom_hooks_dir: "${cfg.statePath}/custom_hooks"
|
||||
redis:
|
||||
bin: ${pkgs.redis}/bin/redis-cli
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
database: 0
|
||||
namespace: resque:gitlab
|
||||
'';
|
||||
gitlabShellConfig = {
|
||||
user = cfg.user;
|
||||
gitlab_url = "http+unix://${pathUrlQuote gitlabSocket}";
|
||||
http_settings.self_signed_cert = false;
|
||||
repos_path = "${cfg.statePath}/repositories";
|
||||
secret_file = "${cfg.statePath}/config/gitlab_shell_secret";
|
||||
log_file = "${cfg.statePath}/log/gitlab-shell.log";
|
||||
custom_hooks_dir = "${cfg.statePath}/custom_hooks";
|
||||
redis = {
|
||||
bin = "${pkgs.redis}/bin/redis-cli";
|
||||
host = "127.0.0.1";
|
||||
port = 6379;
|
||||
database = 0;
|
||||
namespace = "resque:gitlab";
|
||||
};
|
||||
};
|
||||
|
||||
redisYml = ''
|
||||
production:
|
||||
url: redis://localhost:6379/
|
||||
'';
|
||||
redisConfig.production.url = "redis://localhost:6379/";
|
||||
|
||||
secretsYml = ''
|
||||
production:
|
||||
secret_key_base: ${cfg.secrets.secret}
|
||||
otp_key_base: ${cfg.secrets.otp}
|
||||
db_key_base: ${cfg.secrets.db}
|
||||
openid_connect_signing_key: ${builtins.toJSON cfg.secrets.jws}
|
||||
'';
|
||||
secretsConfig.production = {
|
||||
secret_key_base = cfg.secrets.secret;
|
||||
otp_key_base = cfg.secrets.otp;
|
||||
db_key_base = cfg.secrets.db;
|
||||
openid_connect_signing_key = cfg.secrets.jws;
|
||||
};
|
||||
|
||||
gitlabConfig = {
|
||||
# These are the default settings from config/gitlab.example.yml
|
||||
@ -115,12 +112,8 @@ let
|
||||
upload_pack = true;
|
||||
receive_pack = true;
|
||||
};
|
||||
workhorse = {
|
||||
secret_file = "${cfg.statePath}/.gitlab_workhorse_secret";
|
||||
};
|
||||
git = {
|
||||
bin_path = "git";
|
||||
};
|
||||
workhorse.secret_file = "${cfg.statePath}/.gitlab_workhorse_secret";
|
||||
git.bin_path = "git";
|
||||
monitoring = {
|
||||
ip_whitelist = [ "127.0.0.0/8" "::1/128" ];
|
||||
sidekiq_exporter = {
|
||||
@ -138,7 +131,7 @@ let
|
||||
HOME = "${cfg.statePath}/home";
|
||||
UNICORN_PATH = "${cfg.statePath}/";
|
||||
GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/";
|
||||
GITLAB_STATE_PATH = "${cfg.statePath}";
|
||||
GITLAB_STATE_PATH = cfg.statePath;
|
||||
GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads";
|
||||
SCHEMA = "${cfg.statePath}/db/schema.rb";
|
||||
GITLAB_LOG_PATH = "${cfg.statePath}/log";
|
||||
@ -146,13 +139,11 @@ let
|
||||
GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/shell/config.yml";
|
||||
GITLAB_SHELL_SECRET_PATH = "${cfg.statePath}/config/gitlab_shell_secret";
|
||||
GITLAB_SHELL_HOOKS_PATH = "${cfg.statePath}/shell/hooks";
|
||||
GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "gitlab-redis.yml" redisYml;
|
||||
GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "redis.yml" (builtins.toJSON redisConfig);
|
||||
prometheus_multiproc_dir = "/run/gitlab";
|
||||
RAILS_ENV = "production";
|
||||
};
|
||||
|
||||
unicornConfig = builtins.readFile ./defaultUnicornConfig.rb;
|
||||
|
||||
gitlab-rake = pkgs.stdenv.mkDerivation rec {
|
||||
name = "gitlab-rake";
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
@ -162,7 +153,6 @@ let
|
||||
mkdir -p $out/bin
|
||||
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 pkgs.coreutils pkgs.procps ]}:$PATH' \
|
||||
--set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \
|
||||
--run 'cd ${cfg.packages.gitlab}/share/gitlab'
|
||||
@ -306,7 +296,6 @@ in {
|
||||
|
||||
initialRootPassword = mkOption {
|
||||
type = types.str;
|
||||
default = "UseNixOS!";
|
||||
description = ''
|
||||
Initial password of the root account if this is a new install.
|
||||
'';
|
||||
@ -461,10 +450,30 @@ in {
|
||||
}
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /run/gitlab 0755 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabEnv.HOME} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.backupPath} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/builds 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/config 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/db 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/log 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/repositories 2770 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/shell 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/tmp/pids 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/tmp/sockets 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/uploads 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/pre-receive.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/post-receive.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/update.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/artifacts 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/lfs-objects 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/pages 0750 ${cfg.user} ${cfg.group} -"
|
||||
];
|
||||
|
||||
systemd.services.gitlab-sidekiq = {
|
||||
after = [ "network.target" "redis.service" ];
|
||||
after = [ "network.target" "redis.service" "gitlab.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
partOf = [ "gitlab.service" ];
|
||||
environment = gitlabEnv;
|
||||
path = with pkgs; [
|
||||
config.services.postgresql.package
|
||||
@ -486,10 +495,8 @@ in {
|
||||
};
|
||||
|
||||
systemd.services.gitaly = {
|
||||
after = [ "network.target" "gitlab.service" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.HOME = gitlabEnv.HOME;
|
||||
environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH;
|
||||
path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv cfg.packages.gitaly.rubyEnv.wrappedRuby ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
@ -505,8 +512,6 @@ in {
|
||||
systemd.services.gitlab-workhorse = {
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.HOME = gitlabEnv.HOME;
|
||||
environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH;
|
||||
path = with pkgs; [
|
||||
gitAndTools.git
|
||||
gnutar
|
||||
@ -514,10 +519,6 @@ in {
|
||||
openssh
|
||||
gitlab-workhorse
|
||||
];
|
||||
preStart = ''
|
||||
mkdir -p /run/gitlab
|
||||
chown ${cfg.user}:${cfg.group} /run/gitlab
|
||||
'';
|
||||
serviceConfig = {
|
||||
PermissionsStartOnly = true; # preStart must be run as root
|
||||
Type = "simple";
|
||||
@ -538,7 +539,7 @@ in {
|
||||
};
|
||||
|
||||
systemd.services.gitlab = {
|
||||
after = [ "network.target" "postgresql.service" "redis.service" ];
|
||||
after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "postgresql.service" "redis.service" ];
|
||||
requires = [ "gitlab-sidekiq.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment = gitlabEnv;
|
||||
@ -551,102 +552,76 @@ in {
|
||||
gnupg
|
||||
];
|
||||
preStart = ''
|
||||
mkdir -p ${cfg.backupPath}
|
||||
mkdir -p ${cfg.statePath}/builds
|
||||
mkdir -p ${cfg.statePath}/repositories
|
||||
mkdir -p ${gitlabConfig.production.shared.path}/artifacts
|
||||
mkdir -p ${gitlabConfig.production.shared.path}/lfs-objects
|
||||
mkdir -p ${gitlabConfig.production.shared.path}/pages
|
||||
mkdir -p ${cfg.statePath}/log
|
||||
mkdir -p ${cfg.statePath}/tmp/pids
|
||||
mkdir -p ${cfg.statePath}/tmp/sockets
|
||||
mkdir -p ${cfg.statePath}/shell
|
||||
mkdir -p ${cfg.statePath}/db
|
||||
mkdir -p ${cfg.statePath}/uploads
|
||||
mkdir -p ${cfg.statePath}/custom_hooks/pre-receive.d
|
||||
mkdir -p ${cfg.statePath}/custom_hooks/post-receive.d
|
||||
mkdir -p ${cfg.statePath}/custom_hooks/update.d
|
||||
|
||||
rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks
|
||||
mkdir -p ${cfg.statePath}/config
|
||||
|
||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${cfg.statePath}/config/gitlab_shell_secret
|
||||
|
||||
mkdir -p /run/gitlab
|
||||
mkdir -p ${cfg.statePath}/log
|
||||
[ -d /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log
|
||||
[ -d /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp
|
||||
[ -d /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads
|
||||
ln -sf $GITLAB_SHELL_CONFIG_PATH /run/gitlab/shell-config.yml
|
||||
chown -R ${cfg.user}:${cfg.group} /run/gitlab
|
||||
|
||||
# Prepare home directory
|
||||
mkdir -p ${gitlabEnv.HOME}/.ssh
|
||||
touch ${gitlabEnv.HOME}/.ssh/authorized_keys
|
||||
chown -R ${cfg.user}:${cfg.group} ${gitlabEnv.HOME}/
|
||||
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/db/* ${cfg.statePath}/db
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config
|
||||
${optionalString cfg.smtp.enable ''
|
||||
ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb
|
||||
''}
|
||||
ln -sf ${cfg.statePath}/config /run/gitlab/config
|
||||
rm -rf ${cfg.statePath}/config
|
||||
mkdir ${cfg.statePath}/config
|
||||
if [ -e ${cfg.statePath}/lib ]; then
|
||||
rm ${cfg.statePath}/lib
|
||||
fi
|
||||
ln -sf ${pkgs.gitlab}/share/gitlab/lib ${cfg.statePath}/lib
|
||||
|
||||
ln -sf ${cfg.packages.gitlab}/share/gitlab/lib ${cfg.statePath}/lib
|
||||
[ -L /run/gitlab/config ] || ln -sf ${cfg.statePath}/config /run/gitlab/config
|
||||
[ -L /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log
|
||||
[ -L /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp
|
||||
[ -L /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads
|
||||
${optionalString cfg.smtp.enable ''
|
||||
ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb
|
||||
''}
|
||||
cp ${cfg.packages.gitlab}/share/gitlab/VERSION ${cfg.statePath}/VERSION
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config
|
||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${cfg.statePath}/config/gitlab_shell_secret
|
||||
|
||||
# JSON is a subset of YAML
|
||||
ln -fs ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)} ${cfg.statePath}/config/gitlab.yml
|
||||
ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.statePath}/config/database.yml
|
||||
ln -fs ${pkgs.writeText "secrets.yml" secretsYml} ${cfg.statePath}/config/secrets.yml
|
||||
ln -fs ${pkgs.writeText "unicorn.rb" unicornConfig} ${cfg.statePath}/config/unicorn.rb
|
||||
ln -sf ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)} ${cfg.statePath}/config/gitlab.yml
|
||||
ln -sf ${pkgs.writeText "database.yml" (builtins.toJSON databaseConfig)} ${cfg.statePath}/config/database.yml
|
||||
ln -sf ${pkgs.writeText "secrets.yml" (builtins.toJSON secretsConfig)} ${cfg.statePath}/config/secrets.yml
|
||||
ln -sf ${./defaultUnicornConfig.rb} ${cfg.statePath}/config/unicorn.rb
|
||||
|
||||
# Install the shell required to push repositories
|
||||
ln -sf ${pkgs.writeText "config.yml" (builtins.toJSON gitlabShellConfig)} /run/gitlab/shell-config.yml
|
||||
[ -L ${cfg.statePath}/shell/hooks ] || ln -sf ${cfg.packages.gitlab-shell}/hooks ${cfg.statePath}/shell/hooks
|
||||
${cfg.packages.gitlab-shell}/bin/install
|
||||
|
||||
chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}/
|
||||
chmod -R ug+rwX,o-rwx+X ${cfg.statePath}/
|
||||
chown -R ${cfg.user}:${cfg.group} /run/gitlab
|
||||
|
||||
# Install the shell required to push repositories
|
||||
ln -fs ${pkgs.writeText "config.yml" gitlabShellYml} "$GITLAB_SHELL_CONFIG_PATH"
|
||||
ln -fs ${cfg.packages.gitlab-shell}/hooks "$GITLAB_SHELL_HOOKS_PATH"
|
||||
${cfg.packages.gitlab-shell}/bin/install
|
||||
|
||||
if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
|
||||
if ! test -e "${cfg.statePath}/db-created"; then
|
||||
if ! test -e "${cfg.statePath}/db-created"; then
|
||||
if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql postgres -c "CREATE ROLE ${cfg.databaseUsername} WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'"
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} ${config.services.postgresql.package}/bin/createdb --owner ${cfg.databaseUsername} ${cfg.databaseName}
|
||||
touch "${cfg.statePath}/db-created"
|
||||
|
||||
# enable required pg_trgm extension for gitlab
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql ${cfg.databaseName} -c "CREATE EXTENSION IF NOT EXISTS pg_trgm"
|
||||
fi
|
||||
|
||||
# enable required pg_trgm extension for gitlab
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql ${cfg.databaseName} -c "CREATE EXTENSION IF NOT EXISTS pg_trgm"
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake db:schema:load
|
||||
|
||||
touch "${cfg.statePath}/db-created"
|
||||
fi
|
||||
|
||||
# Always do the db migrations just to be sure the database is up-to-date
|
||||
${gitlab-rake}/bin/gitlab-rake db:migrate RAILS_ENV=production
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake db:migrate
|
||||
|
||||
# The gitlab:setup task is horribly broken somehow, the db:migrate
|
||||
# task above and the db:seed_fu below will do the same for setting
|
||||
# up the initial database
|
||||
if ! test -e "${cfg.statePath}/db-seeded"; then
|
||||
${gitlab-rake}/bin/gitlab-rake db:seed_fu RAILS_ENV=production \
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} ${gitlab-rake}/bin/gitlab-rake db:seed_fu \
|
||||
GITLAB_ROOT_PASSWORD='${cfg.initialRootPassword}' GITLAB_ROOT_EMAIL='${cfg.initialRootEmail}'
|
||||
touch "${cfg.statePath}/db-seeded"
|
||||
fi
|
||||
|
||||
# The gitlab:shell:setup regenerates the authorized_keys file so that
|
||||
# the store path to the gitlab-shell in it gets updated
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} force=yes ${gitlab-rake}/bin/gitlab-rake gitlab:shell:setup RAILS_ENV=production
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H force=yes ${gitlab-rake}/bin/gitlab-rake gitlab:shell:setup
|
||||
|
||||
# The gitlab:shell:create_hooks task seems broken for fixing links
|
||||
# so we instead delete all the hooks and create them anew
|
||||
rm -f ${cfg.statePath}/repositories/**/*.git/hooks
|
||||
${gitlab-rake}/bin/gitlab-rake gitlab:shell:create_hooks RAILS_ENV=production
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake gitlab:shell:create_hooks
|
||||
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${pkgs.git}/bin/git config --global core.autocrlf "input"
|
||||
|
||||
# Change permissions in the last step because some of the
|
||||
# intermediary scripts like to create directories as root.
|
||||
chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}
|
||||
chmod -R ug+rwX,o-rwx+X ${cfg.statePath}
|
||||
chmod -R u+rwX,go-rwx+X ${gitlabEnv.HOME}
|
||||
chmod -R ug+rwX,o-rwx ${cfg.statePath}/repositories
|
||||
chmod -R ug-s ${cfg.statePath}/repositories
|
||||
|
@ -157,6 +157,7 @@ in {
|
||||
Restart = "on-failure";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = "${cfg.configDir}";
|
||||
KillSignal = "SIGINT";
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
};
|
||||
|
154
nixos/modules/services/monitoring/kapacitor.nix
Normal file
154
nixos/modules/services/monitoring/kapacitor.nix
Normal file
@ -0,0 +1,154 @@
|
||||
{ options, config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.kapacitor;
|
||||
|
||||
kapacitorConf = pkgs.writeTextFile {
|
||||
name = "kapacitord.conf";
|
||||
text = ''
|
||||
hostname="${config.networking.hostName}"
|
||||
data_dir="${cfg.dataDir}"
|
||||
|
||||
[http]
|
||||
bind-address = "${cfg.bind}:${toString cfg.port}"
|
||||
log-enabled = false
|
||||
auth-enabled = false
|
||||
|
||||
[task]
|
||||
dir = "${cfg.dataDir}/tasks"
|
||||
snapshot-interval = "${cfg.taskSnapshotInterval}"
|
||||
|
||||
[replay]
|
||||
dir = "${cfg.dataDir}/replay"
|
||||
|
||||
[storage]
|
||||
boltdb = "${cfg.dataDir}/kapacitor.db"
|
||||
|
||||
${optionalString (cfg.loadDirectory != null) ''
|
||||
[load]
|
||||
enabled = true
|
||||
dir = "${cfg.loadDirectory}"
|
||||
''}
|
||||
|
||||
${optionalString (cfg.defaultDatabase.enable) ''
|
||||
[[influxdb]]
|
||||
name = "default"
|
||||
enabled = true
|
||||
default = true
|
||||
urls = [ "${cfg.defaultDatabase.url}" ]
|
||||
username = "${cfg.defaultDatabase.username}"
|
||||
password = "${cfg.defaultDatabase.password}"
|
||||
''}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.kapacitor = {
|
||||
enable = mkEnableOption "kapacitor";
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
example = "/var/lib/kapacitor";
|
||||
default = "/var/lib/kapacitor";
|
||||
description = "Location where Kapacitor stores its state";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9092;
|
||||
description = "Port of Kapacitor";
|
||||
};
|
||||
|
||||
bind = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = literalExample "0.0.0.0";
|
||||
description = "Address to bind to. The default is to bind to all addresses";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
description = "These lines go into kapacitord.conf verbatim.";
|
||||
default = "";
|
||||
type = types.lines;
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "kapacitor";
|
||||
description = "User account under which Kapacitor runs";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "kapacitor";
|
||||
description = "Group under which Kapacitor runs";
|
||||
};
|
||||
|
||||
taskSnapshotInterval = mkOption {
|
||||
type = types.str;
|
||||
description = "Specifies how often to snapshot the task state (in InfluxDB time units)";
|
||||
default = "1m0s";
|
||||
example = "1m0s";
|
||||
};
|
||||
|
||||
loadDirectory = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
description = "Directory where to load services from, such as tasks, templates and handlers (or null to disable service loading on startup)";
|
||||
default = null;
|
||||
};
|
||||
|
||||
defaultDatabase = {
|
||||
enable = mkEnableOption "kapacitor.defaultDatabase";
|
||||
|
||||
url = mkOption {
|
||||
description = "The URL to an InfluxDB server that serves as the default database";
|
||||
example = "http://localhost:8086";
|
||||
type = types.string;
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
description = "The username to connect to the remote InfluxDB server";
|
||||
type = types.string;
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
description = "The password to connect to the remote InfluxDB server";
|
||||
type = types.string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.kapacitor ];
|
||||
|
||||
systemd.services.kapacitor = {
|
||||
description = "Kapacitor Real-Time Stream Processing Engine";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "networking.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.kapacitor}/bin/kapacitord -config ${kapacitorConf}";
|
||||
User = "kapacitor";
|
||||
Group = "kapacitor";
|
||||
PermissionsStartOnly = true;
|
||||
};
|
||||
preStart = ''
|
||||
mkdir -p ${cfg.dataDir}
|
||||
chown ${cfg.user}:${cfg.group} ${cfg.dataDir}
|
||||
'';
|
||||
};
|
||||
|
||||
users.users.kapacitor = {
|
||||
uid = config.ids.uids.kapacitor;
|
||||
description = "Kapacitor user";
|
||||
home = cfg.dataDir;
|
||||
};
|
||||
|
||||
users.groups.kapacitor = {
|
||||
gid = config.ids.gids.kapacitor;
|
||||
};
|
||||
};
|
||||
}
|
@ -33,7 +33,7 @@ let
|
||||
|
||||
purple_plugin_path =
|
||||
lib.concatMapStringsSep ":"
|
||||
(plugin: "${plugin}/lib/pidgin/")
|
||||
(plugin: "${plugin}/lib/pidgin/:${plugin}/lib/purple-2/")
|
||||
cfg.libpurple_plugins
|
||||
;
|
||||
|
||||
|
@ -93,6 +93,8 @@ in
|
||||
|
||||
services.timesyncd.enable = mkForce false;
|
||||
|
||||
systemd.services.systemd-timedated.environment = { SYSTEMD_TIMEDATED_NTP_SERVICES = "chronyd.service"; };
|
||||
|
||||
systemd.services.chronyd =
|
||||
{ description = "chrony NTP daemon";
|
||||
|
||||
|
@ -6,9 +6,10 @@ let
|
||||
dataDir = "/var/lib/consul";
|
||||
cfg = config.services.consul;
|
||||
|
||||
configOptions = { data_dir = dataDir; } //
|
||||
(if cfg.webUi then { ui_dir = "${cfg.package.ui}"; } else { }) //
|
||||
cfg.extraConfig;
|
||||
configOptions = {
|
||||
data_dir = dataDir;
|
||||
ui = cfg.webUi;
|
||||
} // cfg.extraConfig;
|
||||
|
||||
configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
|
||||
++ cfg.extraConfigFiles;
|
||||
|
@ -67,6 +67,8 @@ in
|
||||
environment.systemPackages = [ pkgs.ntp ];
|
||||
services.timesyncd.enable = mkForce false;
|
||||
|
||||
systemd.services.systemd-timedated.environment = { SYSTEMD_TIMEDATED_NTP_SERVICES = "ntpd.service"; };
|
||||
|
||||
users.users = singleton
|
||||
{ name = ntpUser;
|
||||
uid = config.ids.uids.ntp;
|
||||
|
@ -267,4 +267,6 @@ in
|
||||
"ip46tables -t nat -D OUTPUT -p tcp ${redCond block} -j ${chain} 2>/dev/null || true"
|
||||
) cfg.redsocks;
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ ekleog ];
|
||||
}
|
||||
|
@ -62,9 +62,21 @@ in {
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/syncthing";
|
||||
description = ''
|
||||
Path where synced directories will exist.
|
||||
'';
|
||||
};
|
||||
|
||||
configDir = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path where the settings and keys will exist.
|
||||
'';
|
||||
default =
|
||||
let
|
||||
nixos = config.system.stateVersion;
|
||||
cond = versionAtLeast nixos "19.03";
|
||||
in cfg.dataDir + (optionalString cond "/.config/syncthing");
|
||||
};
|
||||
|
||||
openDefaultPorts = mkOption {
|
||||
@ -144,7 +156,7 @@ in {
|
||||
${cfg.package}/bin/syncthing \
|
||||
-no-browser \
|
||||
-gui-address=${cfg.guiAddress} \
|
||||
-home=${cfg.dataDir}
|
||||
-home=${cfg.configDir}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
@ -39,7 +39,8 @@ in
|
||||
systemd.services.zerotierone = {
|
||||
description = "ZeroTierOne";
|
||||
path = [ cfg.package ];
|
||||
after = [ "network.target" ];
|
||||
bindsTo = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
preStart = ''
|
||||
mkdir -p /var/lib/zerotier-one/networks.d
|
||||
|
@ -6,142 +6,105 @@ let
|
||||
|
||||
cfg = config.services.solr;
|
||||
|
||||
# Assemble all jars needed for solr
|
||||
solrJars = pkgs.stdenv.mkDerivation {
|
||||
name = "solr-jars";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
url = http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.36/bin/apache-tomcat-5.5.36.tar.gz;
|
||||
sha256 = "01mzvh53wrs1p2ym765jwd00gl6kn8f9k3nhdrnhdqr8dhimfb2p";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/lib
|
||||
cp common/lib/*.jar $out/lib/
|
||||
ln -s ${pkgs.ant}/lib/ant/lib/ant.jar $out/lib/
|
||||
ln -s ${cfg.solrPackage}/lib/ext/* $out/lib/
|
||||
ln -s ${pkgs.jdk.home}/lib/tools.jar $out/lib/
|
||||
'' + optionalString (cfg.extraJars != []) ''
|
||||
for f in ${concatStringsSep " " cfg.extraJars}; do
|
||||
cp $f $out/lib
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
in {
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
services.solr = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enables the solr service.
|
||||
'';
|
||||
};
|
||||
enable = mkEnableOption "Enables the solr service.";
|
||||
|
||||
javaPackage = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.jre;
|
||||
defaultText = "pkgs.jre";
|
||||
description = ''
|
||||
Which Java derivation to use for running solr.
|
||||
'';
|
||||
};
|
||||
|
||||
solrPackage = mkOption {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.solr;
|
||||
defaultText = "pkgs.solr";
|
||||
description = ''
|
||||
Which solr derivation to use for running solr.
|
||||
'';
|
||||
description = "Which Solr package to use.";
|
||||
};
|
||||
|
||||
extraJars = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
description = ''
|
||||
List of paths pointing to jars. Jars are copied to commonLibFolder to be available to java/solr.
|
||||
'';
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8983;
|
||||
description = "Port on which Solr is ran.";
|
||||
};
|
||||
|
||||
log4jConfiguration = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
log4j.rootLogger=INFO, stdout
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.Target=System.out
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
|
||||
'';
|
||||
description = ''
|
||||
Contents of the <literal>log4j.properties</literal> used. By default,
|
||||
everything is logged to stdout (picked up by systemd) with level INFO.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The user that should run the solr process and.
|
||||
the working directories.
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The group that will own the working directory.
|
||||
'';
|
||||
};
|
||||
|
||||
solrHome = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The solr home directory. It is your own responsibility to
|
||||
make sure this directory contains a working solr configuration,
|
||||
and is writeable by the the user running the solr service.
|
||||
Failing to do so, the solr will not start properly.
|
||||
'';
|
||||
stateDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/solr";
|
||||
description = "The solr home directory containing config, data, and logging files.";
|
||||
};
|
||||
|
||||
extraJavaOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra command line options given to the java process running
|
||||
solr.
|
||||
'';
|
||||
description = "Extra command line options given to the java process running Solr.";
|
||||
};
|
||||
|
||||
extraWinstoneOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Extra command line options given to the Winstone, which is
|
||||
the servlet container hosting solr.
|
||||
'';
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "solr";
|
||||
description = "User under which Solr is ran.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "solr";
|
||||
description = "Group under which Solr is ran.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.winstone.solr = {
|
||||
serviceName = "solr";
|
||||
inherit (cfg) user group javaPackage;
|
||||
warFile = "${cfg.solrPackage}/lib/solr.war";
|
||||
extraOptions = [
|
||||
"--commonLibFolder=${solrJars}/lib"
|
||||
"--useJasper"
|
||||
] ++ cfg.extraWinstoneOptions;
|
||||
extraJavaOptions = [
|
||||
"-Dsolr.solr.home=${cfg.solrHome}"
|
||||
"-Dlog4j.configuration=file://${pkgs.writeText "log4j.properties" cfg.log4jConfiguration}"
|
||||
] ++ cfg.extraJavaOptions;
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
systemd.services.solr = {
|
||||
after = [ "network.target" "remote-fs.target" "nss-lookup.target" "systemd-journald-dev-log.socket" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = {
|
||||
SOLR_HOME = "${cfg.stateDir}/data";
|
||||
LOG4J_PROPS = "${cfg.stateDir}/log4j2.xml";
|
||||
SOLR_LOGS_DIR = "${cfg.stateDir}/logs";
|
||||
SOLR_PORT = "${toString cfg.port}";
|
||||
};
|
||||
path = with pkgs; [
|
||||
gawk
|
||||
procps
|
||||
];
|
||||
preStart = ''
|
||||
mkdir -p "${cfg.stateDir}/data";
|
||||
mkdir -p "${cfg.stateDir}/logs";
|
||||
|
||||
if ! test -e "${cfg.stateDir}/data/solr.xml"; then
|
||||
install -D -m0640 ${cfg.package}/server/solr/solr.xml "${cfg.stateDir}/data/solr.xml"
|
||||
install -D -m0640 ${cfg.package}/server/solr/zoo.cfg "${cfg.stateDir}/data/zoo.cfg"
|
||||
fi
|
||||
|
||||
if ! test -e "${cfg.stateDir}/log4j2.xml"; then
|
||||
install -D -m0640 ${cfg.package}/server/resources/log4j2.xml "${cfg.stateDir}/log4j2.xml"
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart="${cfg.package}/bin/solr start -f -a \"${concatStringsSep " " cfg.extraJavaOptions}\"";
|
||||
ExecStop="${cfg.package}/bin/solr stop";
|
||||
};
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (cfg.user == "solr") (singleton
|
||||
{ name = "solr";
|
||||
group = cfg.group;
|
||||
home = cfg.stateDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.solr;
|
||||
});
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == "solr") (singleton
|
||||
{ name = "solr";
|
||||
gid = config.ids.gids.solr;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ let
|
||||
|
||||
configFile = pkgs.writeText "nginx.conf" ''
|
||||
user ${cfg.user} ${cfg.group};
|
||||
error_log stderr;
|
||||
error_log ${cfg.logError};
|
||||
daemon off;
|
||||
|
||||
${cfg.config}
|
||||
@ -341,6 +341,35 @@ in
|
||||
";
|
||||
};
|
||||
|
||||
logError = mkOption {
|
||||
default = "stderr";
|
||||
description = "
|
||||
Configures logging.
|
||||
The first parameter defines a file that will store the log. The
|
||||
special value stderr selects the standard error file. Logging to
|
||||
syslog can be configured by specifying the “syslog:” prefix.
|
||||
The second parameter determines the level of logging, and can be
|
||||
one of the following: debug, info, notice, warn, error, crit,
|
||||
alert, or emerg. Log levels above are listed in the order of
|
||||
increasing severity. Setting a certain log level will cause all
|
||||
messages of the specified and more severe log levels to be logged.
|
||||
If this parameter is omitted then error is used.
|
||||
";
|
||||
};
|
||||
|
||||
preStart = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
test -d ${cfg.stateDir}/logs || mkdir -m 750 -p ${cfg.stateDir}/logs
|
||||
test `stat -c %a ${cfg.stateDir}` = "750" || chmod 750 ${cfg.stateDir}
|
||||
test `stat -c %a ${cfg.stateDir}/logs` = "750" || chmod 750 ${cfg.stateDir}/logs
|
||||
chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
|
||||
'';
|
||||
description = "
|
||||
Shell commands executed before the service's nginx is started.
|
||||
";
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
default = "";
|
||||
description = "
|
||||
@ -608,9 +637,7 @@ in
|
||||
stopIfChanged = false;
|
||||
preStart =
|
||||
''
|
||||
mkdir -p ${cfg.stateDir}/logs
|
||||
chmod 700 ${cfg.stateDir}
|
||||
chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
|
||||
${cfg.preStart}
|
||||
${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t
|
||||
'';
|
||||
serviceConfig = {
|
||||
|
@ -22,7 +22,7 @@ let
|
||||
# This wrapper ensures that we actually get themes
|
||||
makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \
|
||||
$out/greeter \
|
||||
--prefix PATH : "${pkgs.glibc.bin}/bin" \
|
||||
--prefix PATH : "${lib.getBin pkgs.stdenv.cc.libc}/bin" \
|
||||
--set GDK_PIXBUF_MODULE_FILE "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" \
|
||||
--set GTK_PATH "${theme}:${pkgs.gtk3.out}" \
|
||||
--set GTK_EXE_PREFIX "${theme}" \
|
||||
|
@ -21,7 +21,8 @@ let
|
||||
[ coreutils
|
||||
gnugrep
|
||||
findutils
|
||||
glibc # needed for getent
|
||||
getent
|
||||
stdenv.cc.libc # nscd in update-users-groups.pl
|
||||
shadow
|
||||
nettools # needed for hostname
|
||||
utillinux # needed for mount and mountpoint
|
||||
|
@ -147,7 +147,7 @@ let
|
||||
${config.boot.initrd.extraUtilsCommands}
|
||||
|
||||
# Copy ld manually since it isn't detected correctly
|
||||
cp -pv ${pkgs.glibc.out}/lib/ld*.so.? $out/lib
|
||||
cp -pv ${pkgs.stdenv.cc.libc.out}/lib/ld*.so.? $out/lib
|
||||
|
||||
# Copy all of the needed libraries
|
||||
find $out/bin $out/lib -type f | while read BIN; do
|
||||
|
@ -112,6 +112,7 @@ in {
|
||||
|
||||
environment.etc."systemd/nspawn".source = generateUnits "nspawn" units [] [];
|
||||
|
||||
systemd.targets."multi-user".wants = [ "machines.target "];
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ let
|
||||
|
||||
logindHandlerType = types.enum [
|
||||
"ignore" "poweroff" "reboot" "halt" "kexec" "suspend"
|
||||
"hibernate" "hybrid-sleep" "lock"
|
||||
"hibernate" "hybrid-sleep" "suspend-then-hibernate" "lock"
|
||||
];
|
||||
|
||||
in
|
||||
@ -587,6 +587,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
services.journald.forwardToSyslog = mkOption {
|
||||
default = config.services.rsyslogd.enable || config.services.syslog-ng.enable;
|
||||
defaultText = "config.services.rsyslogd.enable || config.services.syslog-ng.enable";
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to forward log messages to syslog.
|
||||
'';
|
||||
};
|
||||
|
||||
services.logind.extraConfig = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
@ -754,6 +763,9 @@ in
|
||||
ForwardToConsole=yes
|
||||
TTYPath=${config.services.journald.console}
|
||||
''}
|
||||
${optionalString (config.services.journald.forwardToSyslog) ''
|
||||
ForwardToSyslog=yes
|
||||
''}
|
||||
${config.services.journald.extraConfig}
|
||||
'';
|
||||
|
||||
|
@ -53,7 +53,7 @@ let cfg = config.ec2; in
|
||||
# Mount all formatted ephemeral disks and activate all swap devices.
|
||||
# We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options
|
||||
# because the set of devices is dependent on the instance type
|
||||
# (e.g. "m1.large" has one ephemeral filesystem and one swap device,
|
||||
# (e.g. "m1.small" has one ephemeral filesystem and one swap device,
|
||||
# while "m1.large" has two ephemeral filesystems and no swap
|
||||
# devices). Also, put /tmp and /var on /disk0, since it has a lot
|
||||
# more space than the root device. Similarly, "move" /nix to /disk0
|
||||
|
@ -243,6 +243,9 @@ let
|
||||
|
||||
Restart = "on-failure";
|
||||
|
||||
Slice = "machine.slice";
|
||||
Delegate = true;
|
||||
|
||||
# Hack: we don't want to kill systemd-nspawn, since we call
|
||||
# "machinectl poweroff" in preStop to shut down the
|
||||
# container cleanly. But systemd requires sending a signal
|
||||
@ -606,7 +609,7 @@ in
|
||||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql96;
|
||||
services.postgresql.package = pkgs.postgresql_9_6;
|
||||
|
||||
system.stateVersion = "17.03";
|
||||
};
|
||||
@ -657,6 +660,8 @@ in
|
||||
serviceConfig = serviceDirectives dummyConfig;
|
||||
};
|
||||
in {
|
||||
systemd.targets."multi-user".wants = [ "machines.target" ];
|
||||
|
||||
systemd.services = listToAttrs (filter (x: x.value != null) (
|
||||
# The generic container template used by imperative containers
|
||||
[{ name = "container@"; value = unit; }]
|
||||
@ -680,7 +685,7 @@ in
|
||||
} // (
|
||||
if config.autoStart then
|
||||
{
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wantedBy = [ "machines.target" ];
|
||||
wants = [ "network.target" ];
|
||||
after = [ "network.target" ];
|
||||
restartTriggers = [ config.path ];
|
||||
|
135
nixos/modules/virtualisation/docker-preloader.nix
Normal file
135
nixos/modules/virtualisation/docker-preloader.nix
Normal file
@ -0,0 +1,135 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with builtins;
|
||||
|
||||
let
|
||||
cfg = config.virtualisation;
|
||||
|
||||
sanitizeImageName = image: replaceStrings ["/"] ["-"] image.imageName;
|
||||
hash = drv: head (split "-" (baseNameOf drv.outPath));
|
||||
# The label of an ext4 FS is limited to 16 bytes
|
||||
labelFromImage = image: substring 0 16 (hash image);
|
||||
|
||||
# The Docker image is loaded and some files from /var/lib/docker/
|
||||
# are written into a qcow image.
|
||||
preload = image: pkgs.vmTools.runInLinuxVM (
|
||||
pkgs.runCommand "docker-preload-image-${sanitizeImageName image}" {
|
||||
buildInputs = with pkgs; [ docker e2fsprogs utillinux curl kmod ];
|
||||
preVM = pkgs.vmTools.createEmptyImage {
|
||||
size = cfg.dockerPreloader.qcowSize;
|
||||
fullName = "docker-deamon-image.qcow2";
|
||||
};
|
||||
}
|
||||
''
|
||||
mkfs.ext4 /dev/vda
|
||||
e2label /dev/vda ${labelFromImage image}
|
||||
mkdir -p /var/lib/docker
|
||||
mount -t ext4 /dev/vda /var/lib/docker
|
||||
|
||||
modprobe overlay
|
||||
|
||||
# from https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
|
||||
mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
|
||||
cd /sys/fs/cgroup
|
||||
for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
|
||||
mkdir -p $sys
|
||||
if ! mountpoint -q $sys; then
|
||||
if ! mount -n -t cgroup -o $sys cgroup $sys; then
|
||||
rmdir $sys || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
dockerd -H tcp://127.0.0.1:5555 -H unix:///var/run/docker.sock &
|
||||
|
||||
until $(curl --output /dev/null --silent --connect-timeout 2 http://127.0.0.1:5555); do
|
||||
printf '.'
|
||||
sleep 1
|
||||
done
|
||||
|
||||
docker load -i ${image}
|
||||
|
||||
kill %1
|
||||
find /var/lib/docker/ -maxdepth 1 -mindepth 1 -not -name "image" -not -name "overlay2" | xargs rm -rf
|
||||
'');
|
||||
|
||||
preloadedImages = map preload cfg.dockerPreloader.images;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.virtualisation.dockerPreloader = {
|
||||
images = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.package;
|
||||
description =
|
||||
''
|
||||
A list of Docker images to preload (in the /var/lib/docker directory).
|
||||
'';
|
||||
};
|
||||
qcowSize = mkOption {
|
||||
default = 1024;
|
||||
type = types.int;
|
||||
description =
|
||||
''
|
||||
The size (MB) of qcow files.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
assertions = [{
|
||||
# If docker.storageDriver is null, Docker choose the storage
|
||||
# driver. So, in this case, we cannot be sure overlay2 is used.
|
||||
assertion = cfg.dockerPreloader.images == []
|
||||
|| cfg.docker.storageDriver == "overlay2"
|
||||
|| cfg.docker.storageDriver == "overlay"
|
||||
|| cfg.docker.storageDriver == null;
|
||||
message = "The Docker image Preloader only works with overlay2 storage driver!";
|
||||
}];
|
||||
|
||||
virtualisation.qemu.options =
|
||||
map (path: "-drive if=virtio,file=${path}/disk-image.qcow2,readonly,media=cdrom,format=qcow2")
|
||||
preloadedImages;
|
||||
|
||||
|
||||
# All attached QCOW files are mounted and their contents are linked
|
||||
# to /var/lib/docker/ in order to make image available.
|
||||
systemd.services.docker-preloader = {
|
||||
description = "Preloaded Docker images";
|
||||
wantedBy = ["docker.service"];
|
||||
after = ["network.target"];
|
||||
path = with pkgs; [ mount rsync jq ];
|
||||
script = ''
|
||||
mkdir -p /var/lib/docker/overlay2/l /var/lib/docker/image/overlay2
|
||||
echo '{}' > /tmp/repositories.json
|
||||
|
||||
for i in ${concatStringsSep " " (map labelFromImage cfg.dockerPreloader.images)}; do
|
||||
mkdir -p /mnt/docker-images/$i
|
||||
|
||||
# The ext4 label is limited to 16 bytes
|
||||
mount /dev/disk/by-label/$(echo $i | cut -c1-16) -o ro,noload /mnt/docker-images/$i
|
||||
|
||||
find /mnt/docker-images/$i/overlay2/ -maxdepth 1 -mindepth 1 -not -name l\
|
||||
-exec ln -s '{}' /var/lib/docker/overlay2/ \;
|
||||
cp -P /mnt/docker-images/$i/overlay2/l/* /var/lib/docker/overlay2/l/
|
||||
|
||||
rsync -a /mnt/docker-images/$i/image/ /var/lib/docker/image/
|
||||
|
||||
# Accumulate image definitions
|
||||
cp /tmp/repositories.json /tmp/repositories.json.tmp
|
||||
jq -s '.[0] * .[1]' \
|
||||
/tmp/repositories.json.tmp \
|
||||
/mnt/docker-images/$i/image/overlay2/repositories.json \
|
||||
> /tmp/repositories.json
|
||||
done
|
||||
|
||||
mv /tmp/repositories.json /var/lib/docker/image/overlay2/repositories.json
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -144,7 +144,6 @@ in
|
||||
path = with pkgs; [ iproute ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${gce}/bin/google_network_daemon --debug";
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -196,6 +196,8 @@ in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [ coreutils libvirt gawk ];
|
||||
restartIfChanged = false;
|
||||
|
||||
environment.ON_SHUTDOWN = "${cfg.onShutdown}";
|
||||
};
|
||||
|
||||
systemd.sockets.virtlogd = {
|
||||
|
@ -185,7 +185,10 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
imports = [ ../profiles/qemu-guest.nix ];
|
||||
imports = [
|
||||
../profiles/qemu-guest.nix
|
||||
./docker-preloader.nix
|
||||
];
|
||||
|
||||
options = {
|
||||
|
||||
|
@ -12,7 +12,7 @@ in {
|
||||
virtualbox = {
|
||||
baseImageSize = mkOption {
|
||||
type = types.int;
|
||||
default = 10 * 1024;
|
||||
default = 50 * 1024;
|
||||
description = ''
|
||||
The size of the VirtualBox base image in MiB.
|
||||
'';
|
||||
@ -61,7 +61,7 @@ in {
|
||||
export HOME=$PWD
|
||||
export PATH=${pkgs.virtualbox}/bin:$PATH
|
||||
|
||||
echo "creating VirtualBox pass-through disk wrapper (no copying invovled)..."
|
||||
echo "creating VirtualBox pass-through disk wrapper (no copying involved)..."
|
||||
VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage
|
||||
|
||||
echo "creating VirtualBox VM..."
|
||||
@ -72,9 +72,9 @@ in {
|
||||
--memory ${toString cfg.memorySize} --acpi on --vram 32 \
|
||||
${optionalString (pkgs.stdenv.hostPlatform.system == "i686-linux") "--pae on"} \
|
||||
--nictype1 virtio --nic1 nat \
|
||||
--audiocontroller ac97 --audio alsa \
|
||||
--audiocontroller ac97 --audio alsa --audioout on \
|
||||
--rtcuseutc on \
|
||||
--usb on --mouse usbtablet
|
||||
--usb on --usbehci on --mouse usbtablet
|
||||
VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on
|
||||
VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \
|
||||
--medium disk.vmdk
|
||||
@ -82,7 +82,7 @@ in {
|
||||
echo "exporting VirtualBox VM..."
|
||||
mkdir -p $out
|
||||
fn="$out/${cfg.vmFileName}"
|
||||
VBoxManage export "$vmName" --output "$fn"
|
||||
VBoxManage export "$vmName" --output "$fn" --options manifest
|
||||
|
||||
rm -v $diskImage
|
||||
|
||||
|
@ -283,6 +283,7 @@ in rec {
|
||||
tests.docker-tools = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-tools.nix {};
|
||||
tests.docker-tools-overlay = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-tools-overlay.nix {};
|
||||
tests.docker-edge = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-edge.nix {};
|
||||
tests.docker-preloader = callTestOnMatchingSystems ["x86_64-linux"] tests/docker-preloader.nix {};
|
||||
tests.docker-registry = callTest tests/docker-registry.nix {};
|
||||
tests.dovecot = callTest tests/dovecot.nix {};
|
||||
tests.dnscrypt-proxy = callTestOnMatchingSystems ["x86_64-linux"] tests/dnscrypt-proxy.nix {};
|
||||
@ -300,7 +301,7 @@ in rec {
|
||||
tests.fsck = callTest tests/fsck.nix {};
|
||||
tests.fwupd = callTest tests/fwupd.nix {};
|
||||
tests.gdk-pixbuf = callTest tests/gdk-pixbuf.nix {};
|
||||
#tests.gitlab = callTest tests/gitlab.nix {};
|
||||
tests.gitlab = callTest tests/gitlab.nix {};
|
||||
tests.gitolite = callTest tests/gitolite.nix {};
|
||||
tests.gjs = callTest tests/gjs.nix {};
|
||||
tests.gocd-agent = callTest tests/gocd-agent.nix {};
|
||||
@ -399,6 +400,7 @@ in rec {
|
||||
tests.radicale = callTest tests/radicale.nix {};
|
||||
tests.redmine = callTest tests/redmine.nix {};
|
||||
tests.rspamd = callSubTests tests/rspamd.nix {};
|
||||
tests.rsyslogd = callSubTests tests/rsyslogd.nix {};
|
||||
tests.runInMachine = callTest tests/run-in-machine.nix {};
|
||||
tests.rxe = callTest tests/rxe.nix {};
|
||||
tests.samba = callTest tests/samba.nix {};
|
||||
@ -408,6 +410,7 @@ in rec {
|
||||
tests.slurm = callTest tests/slurm.nix {};
|
||||
tests.smokeping = callTest tests/smokeping.nix {};
|
||||
tests.snapper = callTest tests/snapper.nix {};
|
||||
tests.solr = callTest tests/solr.nix {};
|
||||
#tests.statsd = callTest tests/statsd.nix {}; # statsd is broken: #45946
|
||||
tests.strongswan-swanctl = callTest tests/strongswan-swanctl.nix {};
|
||||
tests.sudo = callTest tests/sudo.nix {};
|
||||
@ -467,7 +470,7 @@ in rec {
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.org";
|
||||
services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql93;
|
||||
services.postgresql.package = pkgs.postgresql_9_3;
|
||||
environment.systemPackages = [ pkgs.php ];
|
||||
});
|
||||
};
|
||||
|
@ -10,9 +10,8 @@ import ./make-test.nix ({pkgs, ...}: rec {
|
||||
emptyDiskImages = [ 20480 20480 ];
|
||||
vlans = [ 1 ];
|
||||
};
|
||||
|
||||
|
||||
networking = {
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
|
||||
{ address = "192.168.1.1"; prefixLength = 24; }
|
||||
@ -54,7 +53,7 @@ import ./make-test.nix ({pkgs, ...}: rec {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
testScript = { ... }: ''
|
||||
startAll;
|
||||
|
||||
@ -83,7 +82,7 @@ import ./make-test.nix ({pkgs, ...}: rec {
|
||||
|
||||
# Can't check ceph status until a mon is up
|
||||
$aio->succeed("ceph -s | grep 'mon: 1 daemons'");
|
||||
|
||||
|
||||
# Start the ceph-mgr daemon, it has no deps and hardly any setup
|
||||
$aio->mustSucceed(
|
||||
"ceph auth get-or-create mgr.aio mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-aio/keyring",
|
||||
|
@ -12,8 +12,10 @@ with pkgs.lib;
|
||||
|
||||
mapAttrs (channel: chromiumPkg: makeTest rec {
|
||||
name = "chromium-${channel}";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ aszlig ];
|
||||
meta = {
|
||||
maintainers = with maintainers; [ aszlig ];
|
||||
# https://github.com/NixOS/hydra/issues/591#issuecomment-435125621
|
||||
inherit (chromiumPkg.meta) timeout;
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
@ -166,7 +168,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec {
|
||||
|
||||
my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o");
|
||||
die "sandbox not working properly: $clipboard"
|
||||
unless $clipboard =~ /namespace sandbox.*yes/mi
|
||||
unless $clipboard =~ /layer 1 sandbox.*namespace/mi
|
||||
&& $clipboard =~ /pid namespaces.*yes/mi
|
||||
&& $clipboard =~ /network namespaces.*yes/mi
|
||||
&& $clipboard =~ /seccomp.*sandbox.*yes/mi
|
||||
@ -184,7 +186,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec {
|
||||
|
||||
my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o");
|
||||
die "copying twice in a row does not work properly: $clipboard"
|
||||
unless $clipboard =~ /namespace sandbox.*yes/mi
|
||||
unless $clipboard =~ /layer 1 sandbox.*namespace/mi
|
||||
&& $clipboard =~ /pid namespaces.*yes/mi
|
||||
&& $clipboard =~ /network namespaces.*yes/mi
|
||||
&& $clipboard =~ /seccomp.*sandbox.*yes/mi
|
||||
|
@ -13,9 +13,6 @@ let
|
||||
|
||||
# CJDNS output is incompatible with the XML log.
|
||||
systemd.services.cjdns.serviceConfig.StandardOutput = "null";
|
||||
#networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = true;
|
||||
#networking.firewall.rejectPackets = true;
|
||||
};
|
||||
|
||||
in
|
||||
|
@ -42,7 +42,6 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.org";
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,6 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
config =
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,6 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.org";
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
system.stateVersion = "18.03";
|
||||
};
|
||||
};
|
||||
|
@ -25,7 +25,6 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.org";
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,6 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
{ services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.org";
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,6 @@ let
|
||||
hostBridge = "br0";
|
||||
config = {
|
||||
networking.firewall.enable = false;
|
||||
networking.firewall.allowPing = true;
|
||||
networking.interfaces.eth0.ipv4.addresses = [
|
||||
{ address = "192.168.1.122"; prefixLength = 24; }
|
||||
];
|
||||
|
27
nixos/tests/docker-preloader.nix
Normal file
27
nixos/tests/docker-preloader.nix
Normal file
@ -0,0 +1,27 @@
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
name = "docker-preloader";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ lewo ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
docker =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
virtualisation.docker.enable = true;
|
||||
virtualisation.dockerPreloader.images = [ pkgs.dockerTools.examples.nix pkgs.dockerTools.examples.bash ];
|
||||
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "yes";
|
||||
services.openssh.extraConfig = "PermitEmptyPasswords yes";
|
||||
users.extraUsers.root.password = "";
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
startAll;
|
||||
|
||||
$docker->waitForUnit("sockets.target");
|
||||
$docker->succeed("docker run nix nix-store --version");
|
||||
$docker->succeed("docker run bash bash --version");
|
||||
'';
|
||||
})
|
@ -1,14 +1,18 @@
|
||||
# This test runs gitlab and checks if it works
|
||||
|
||||
import ./make-test.nix ({ pkgs, ...} : {
|
||||
import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
|
||||
name = "gitlab";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ domenkozar offline ];
|
||||
maintainers = [ globin ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
gitlab = { ... }: {
|
||||
virtualisation.memorySize = 768;
|
||||
virtualisation.memorySize = 4096;
|
||||
systemd.services.gitlab.serviceConfig.Restart = mkForce "no";
|
||||
systemd.services.gitlab-workhorse.serviceConfig.Restart = mkForce "no";
|
||||
systemd.services.gitaly.serviceConfig.Restart = mkForce "no";
|
||||
systemd.services.gitlab-sidekiq.serviceConfig.Restart = mkForce "no";
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
@ -19,10 +23,10 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.gitlab.serviceConfig.TimeoutStartSec = "10min";
|
||||
services.gitlab = {
|
||||
enable = true;
|
||||
databasePassword = "dbPassword";
|
||||
initialRootPassword = "notproduction";
|
||||
secrets = {
|
||||
secret = "secret";
|
||||
otp = "otpsecret";
|
||||
@ -65,8 +69,12 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
|
||||
testScript = ''
|
||||
$gitlab->start();
|
||||
$gitlab->waitForUnit("gitaly.service");
|
||||
$gitlab->waitForUnit("gitlab-workhorse.service");
|
||||
$gitlab->waitForUnit("gitlab.service");
|
||||
$gitlab->waitForUnit("gitlab-sidekiq.service");
|
||||
$gitlab->waitUntilSucceeds("curl http://localhost:80/users/sign_in");
|
||||
$gitlab->waitForFile("/var/gitlab/state/tmp/sockets/gitlab.socket");
|
||||
$gitlab->waitUntilSucceeds("curl -sSf http://localhost/users/sign_in");
|
||||
$gitlab->succeed("${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2")
|
||||
'';
|
||||
})
|
||||
|
@ -74,7 +74,6 @@ in {
|
||||
print "$log\n";
|
||||
|
||||
# Check that no errors were logged
|
||||
# The timer can get out of sync due to Hydra's load, so this error is ignored
|
||||
$hass->fail("cat ${configDir}/home-assistant.log | grep -vF 'Timer got out of sync' | grep -qF ERROR");
|
||||
$hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR");
|
||||
'';
|
||||
})
|
||||
|
@ -11,7 +11,6 @@ import ./make-test.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false,
|
||||
lib.mkMerge [
|
||||
{ virtualisation.vlans = [ 2 1 ];
|
||||
networking.firewall.enable = withFirewall;
|
||||
networking.firewall.allowPing = true;
|
||||
networking.nat.internalIPs = [ "192.168.1.0/24" ];
|
||||
networking.nat.externalInterface = "eth1";
|
||||
}
|
||||
@ -33,7 +32,6 @@ import ./make-test.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false,
|
||||
{ pkgs, nodes, ... }:
|
||||
lib.mkMerge [
|
||||
{ virtualisation.vlans = [ 1 ];
|
||||
networking.firewall.allowPing = true;
|
||||
networking.defaultGateway =
|
||||
(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address;
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ let
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
firewall.checkReversePath = true;
|
||||
firewall.allowedUDPPorts = [ 547 ];
|
||||
interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
|
||||
@ -86,7 +85,6 @@ let
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
defaultGateway = "192.168.1.1";
|
||||
interfaces.eth1.ipv4.addresses = mkOverride 0 [
|
||||
@ -139,7 +137,6 @@ let
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = true;
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = mkOverride 0 [ ];
|
||||
@ -194,7 +191,6 @@ let
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
interfaces.eth1 = {
|
||||
ipv4.addresses = mkOverride 0 [ ];
|
||||
@ -234,7 +230,6 @@ let
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
bonds.bond = {
|
||||
interfaces = [ "eth1" "eth2" ];
|
||||
@ -271,7 +266,6 @@ let
|
||||
virtualisation.vlans = [ vlan ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
interfaces.eth1.ipv4.addresses = mkOverride 0
|
||||
[ { inherit address; prefixLength = 24; } ];
|
||||
@ -285,7 +279,6 @@ let
|
||||
virtualisation.vlans = [ 1 2 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
bridges.bridge.interfaces = [ "eth1" "eth2" ];
|
||||
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
|
||||
@ -329,7 +322,6 @@ let
|
||||
# reverse path filtering rules for the macvlan interface seem
|
||||
# to be incorrect, causing the test to fail. Disable temporarily.
|
||||
firewall.checkReversePath = false;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = true;
|
||||
macvlans.macvlan.interface = "eth1";
|
||||
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
|
||||
@ -415,7 +407,6 @@ let
|
||||
#virtualisation.vlans = [ 1 ];
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
firewall.allowPing = true;
|
||||
useDHCP = false;
|
||||
vlans.vlan = {
|
||||
id = 1;
|
||||
|
@ -17,11 +17,12 @@ import ./make-test.nix {
|
||||
extraServerArgs = [ "-v" ];
|
||||
serverConfiguration = ''
|
||||
listen on 0.0.0.0
|
||||
action do_relay relay
|
||||
# DO NOT DO THIS IN PRODUCTION!
|
||||
# Setting up authentication requires a certificate which is painful in
|
||||
# a test environment, but THIS WOULD BE DANGEROUS OUTSIDE OF A
|
||||
# WELL-CONTROLLED ENVIRONMENT!
|
||||
accept from any for any relay
|
||||
match from any for any action do_relay
|
||||
'';
|
||||
};
|
||||
};
|
||||
@ -41,8 +42,9 @@ import ./make-test.nix {
|
||||
extraServerArgs = [ "-v" ];
|
||||
serverConfiguration = ''
|
||||
listen on 0.0.0.0
|
||||
accept from any for local deliver to mda \
|
||||
action dovecot_deliver mda \
|
||||
"${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}"
|
||||
match from any for local action dovecot_deliver
|
||||
'';
|
||||
};
|
||||
services.dovecot2 = {
|
||||
|
@ -26,31 +26,20 @@ import ./make-test.nix ({ pkgs, ...} :
|
||||
services.xserver.displayManager.sddm.theme = "breeze-ocr-theme";
|
||||
services.xserver.desktopManager.plasma5.enable = true;
|
||||
services.xserver.desktopManager.default = "plasma5";
|
||||
services.xserver.displayManager.sddm.autoLogin = {
|
||||
enable = true;
|
||||
user = "alice";
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
environment.systemPackages = [ sddm_theme ];
|
||||
|
||||
# fontconfig-penultimate-0.3.3 -> 0.3.4 broke OCR apparently, but no idea why.
|
||||
nixpkgs.config.packageOverrides = superPkgs: {
|
||||
fontconfig-penultimate = superPkgs.fontconfig-penultimate.override {
|
||||
version = "0.3.3";
|
||||
sha256 = "1z76jbkb0nhf4w7fy647yyayqr4q02fgk6w58k0yi700p0m3h4c9";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
||||
testScript = { nodes, ... }: let
|
||||
user = nodes.machine.config.users.users.alice;
|
||||
xdo = "${pkgs.xdotool}/bin/xdotool";
|
||||
in ''
|
||||
startAll;
|
||||
# Wait for display manager to start
|
||||
$machine->waitForText(qr/${user.description}/);
|
||||
$machine->screenshot("sddm");
|
||||
|
||||
# Log in
|
||||
$machine->sendChars("${user.password}\n");
|
||||
# wait for log in
|
||||
$machine->waitForFile("/home/alice/.Xauthority");
|
||||
$machine->succeed("xauth merge ~alice/.Xauthority");
|
||||
|
||||
|
@ -9,7 +9,7 @@ import ./make-test.nix ({ pkgs, ...} : {
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
services.postgresql = let mypg = pkgs.postgresql100; in {
|
||||
services.postgresql = let mypg = pkgs.postgresql_11; in {
|
||||
enable = true;
|
||||
package = mypg;
|
||||
extraPlugins = [ (pkgs.postgis.override { postgresql = mypg; }) ];
|
||||
|
@ -66,7 +66,6 @@ import ./make-test.nix ({ pkgs, ... }:
|
||||
virtualisation.vlans = [ 3 ];
|
||||
networking.defaultGateway = ifAddr nodes.router2 "eth1";
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowPing = true;
|
||||
services.httpd.enable = true;
|
||||
services.httpd.adminAddr = "foo@example.com";
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ let
|
||||
$machine->succeed("id \"rspamd\" >/dev/null");
|
||||
${checkSocket "/run/rspamd/rspamd.sock" "rspamd" "rspamd" "660" }
|
||||
sleep 10;
|
||||
$machine->log($machine->succeed("cat /etc/rspamd.conf"));
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
|
||||
$machine->log($machine->succeed("systemctl cat rspamd.service"));
|
||||
$machine->log($machine->succeed("curl http://localhost:11334/auth"));
|
||||
$machine->log($machine->succeed("curl http://127.0.0.1:11334/auth"));
|
||||
@ -55,7 +55,7 @@ in
|
||||
$machine->waitForFile("/run/rspamd.sock");
|
||||
${checkSocket "/run/rspamd.sock" "root" "root" "600" }
|
||||
${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
|
||||
$machine->log($machine->succeed("cat /etc/rspamd.conf"));
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
|
||||
$machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
|
||||
$machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
|
||||
'';
|
||||
@ -86,9 +86,80 @@ in
|
||||
$machine->waitForFile("/run/rspamd.sock");
|
||||
${checkSocket "/run/rspamd.sock" "root" "root" "600" }
|
||||
${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
|
||||
$machine->log($machine->succeed("cat /etc/rspamd.conf"));
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
|
||||
$machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
|
||||
$machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
|
||||
'';
|
||||
};
|
||||
customLuaRules = makeTest {
|
||||
name = "rspamd-custom-lua-rules";
|
||||
machine = {
|
||||
environment.etc."tests/no-muh.eml".text = ''
|
||||
From: Sheep1<bah@example.com>
|
||||
To: Sheep2<mah@example.com>
|
||||
Subject: Evil cows
|
||||
|
||||
I find cows to be evil don't you?
|
||||
'';
|
||||
environment.etc."tests/muh.eml".text = ''
|
||||
From: Cow<cow@example.com>
|
||||
To: Sheep2<mah@example.com>
|
||||
Subject: Evil cows
|
||||
|
||||
Cows are majestic creatures don't Muh agree?
|
||||
'';
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
locals."groups.conf".text = ''
|
||||
group "cows" {
|
||||
symbol {
|
||||
NO_MUH = {
|
||||
weight = 1.0;
|
||||
description = "Mails should not muh";
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
localLuaRules = pkgs.writeText "rspamd.local.lua" ''
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
rspamd_config.NO_MUH = {
|
||||
callback = function (task)
|
||||
local parts = task:get_text_parts()
|
||||
if parts then
|
||||
for _,part in ipairs(parts) do
|
||||
local content = tostring(part:get_content())
|
||||
rspamd_logger.infox(rspamd_config, 'Found content %s', content)
|
||||
local found = string.find(content, "Muh");
|
||||
rspamd_logger.infox(rspamd_config, 'Found muh %s', tostring(found))
|
||||
if found then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
score = 5.0,
|
||||
description = 'Allow no cows',
|
||||
group = "cows",
|
||||
}
|
||||
rspamd_logger.infox(rspamd_config, 'Work dammit!!!')
|
||||
'';
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
$machine->waitForOpenPort(11334);
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/rspamd.local.lua"));
|
||||
$machine->log($machine->succeed("cat /etc/rspamd/local.d/groups.conf"));
|
||||
${checkSocket "/run/rspamd/rspamd.sock" "rspamd" "rspamd" "660" }
|
||||
$machine->log($machine->succeed("curl --unix-socket /run/rspamd/rspamd.sock http://localhost/ping"));
|
||||
$machine->log($machine->succeed("rspamc -h 127.0.0.1:11334 stat"));
|
||||
$machine->log($machine->succeed("cat /etc/tests/no-muh.eml | rspamc -h 127.0.0.1:11334"));
|
||||
$machine->log($machine->succeed("cat /etc/tests/muh.eml | rspamc -h 127.0.0.1:11334 symbols"));
|
||||
$machine->waitUntilSucceeds("journalctl -u rspamd | grep -i muh >&2");
|
||||
$machine->log($machine->fail("cat /etc/tests/no-muh.eml | rspamc -h 127.0.0.1:11334 symbols | grep NO_MUH"));
|
||||
$machine->log($machine->succeed("cat /etc/tests/muh.eml | rspamc -h 127.0.0.1:11334 symbols | grep NO_MUH"));
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
38
nixos/tests/rsyslogd.nix
Normal file
38
nixos/tests/rsyslogd.nix
Normal file
@ -0,0 +1,38 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with pkgs.lib;
|
||||
{
|
||||
test1 = makeTest {
|
||||
name = "rsyslogd-test1";
|
||||
meta.maintainers = [ maintainers.aanderse ];
|
||||
|
||||
machine =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.rsyslogd.enable = true;
|
||||
services.journald.forwardToSyslog = false;
|
||||
};
|
||||
|
||||
# ensure rsyslogd isn't receiving messages from journald if explicitly disabled
|
||||
testScript = ''
|
||||
$machine->waitForUnit("default.target");
|
||||
$machine->fail("test -f /var/log/messages");
|
||||
'';
|
||||
};
|
||||
|
||||
test2 = makeTest {
|
||||
name = "rsyslogd-test2";
|
||||
meta.maintainers = [ maintainers.aanderse ];
|
||||
|
||||
machine =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.rsyslogd.enable = true;
|
||||
};
|
||||
|
||||
# ensure rsyslogd is receiving messages from journald
|
||||
testScript = ''
|
||||
$machine->waitForUnit("default.target");
|
||||
$machine->succeed("test -f /var/log/messages");
|
||||
'';
|
||||
};
|
||||
}
|
@ -1,22 +1,27 @@
|
||||
import ./make-test.nix ({ ... }:
|
||||
let mungekey = "mungeverryweakkeybuteasytointegratoinatest";
|
||||
import ./make-test.nix ({ lib, ... }:
|
||||
let
|
||||
mungekey = "mungeverryweakkeybuteasytointegratoinatest";
|
||||
|
||||
slurmconfig = {
|
||||
controlMachine = "control";
|
||||
nodeName = ''
|
||||
control
|
||||
NodeName=node[1-3] CPUs=1 State=UNKNOWN
|
||||
nodeName = [ "node[1-3] CPUs=1 State=UNKNOWN" ];
|
||||
partitionName = [ "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP" ];
|
||||
extraConfig = ''
|
||||
AccountingStorageHost=dbd
|
||||
AccountingStorageType=accounting_storage/slurmdbd
|
||||
'';
|
||||
partitionName = "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP";
|
||||
};
|
||||
in {
|
||||
name = "slurm";
|
||||
|
||||
meta.maintainers = [ lib.maintainers.markuskowa ];
|
||||
|
||||
nodes =
|
||||
let
|
||||
computeNode =
|
||||
{ ...}:
|
||||
{
|
||||
# TODO slrumd port and slurmctld port should be configurations and
|
||||
# TODO slurmd port and slurmctld port should be configurations and
|
||||
# automatically allowed by the firewall.
|
||||
networking.firewall.enable = false;
|
||||
services.slurm = {
|
||||
@ -43,6 +48,24 @@ in {
|
||||
} // slurmconfig;
|
||||
};
|
||||
|
||||
dbd =
|
||||
{ pkgs, ... } :
|
||||
{
|
||||
networking.firewall.enable = false;
|
||||
services.slurm.dbdserver = {
|
||||
enable = true;
|
||||
};
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mysql;
|
||||
ensureDatabases = [ "slurm_acct_db" ];
|
||||
ensureUsers = [{
|
||||
ensurePermissions = { "slurm_acct_db.*" = "ALL PRIVILEGES"; };
|
||||
name = "slurm";
|
||||
}];
|
||||
};
|
||||
};
|
||||
|
||||
node1 = computeNode;
|
||||
node2 = computeNode;
|
||||
node3 = computeNode;
|
||||
@ -54,7 +77,7 @@ in {
|
||||
startAll;
|
||||
|
||||
# Set up authentification across the cluster
|
||||
foreach my $node (($submit,$control,$node1,$node2,$node3))
|
||||
foreach my $node (($submit,$control,$dbd,$node1,$node2,$node3))
|
||||
{
|
||||
$node->waitForUnit("default.target");
|
||||
|
||||
@ -63,10 +86,22 @@ in {
|
||||
$node->succeed("chmod 0400 /etc/munge/munge.key");
|
||||
$node->succeed("chown munge:munge /etc/munge/munge.key");
|
||||
$node->succeed("systemctl restart munged");
|
||||
}
|
||||
|
||||
$node->waitForUnit("munged");
|
||||
};
|
||||
|
||||
# Restart the services since they have probably failed due to the munge init
|
||||
# failure
|
||||
subtest "can_start_slurmdbd", sub {
|
||||
$dbd->succeed("systemctl restart slurmdbd");
|
||||
$dbd->waitForUnit("slurmdbd.service");
|
||||
};
|
||||
|
||||
# there needs to be an entry for the current
|
||||
# cluster in the database before slurmctld is restarted
|
||||
subtest "add_account", sub {
|
||||
$control->succeed("sacctmgr -i add cluster default");
|
||||
};
|
||||
|
||||
subtest "can_start_slurmctld", sub {
|
||||
$control->succeed("systemctl restart slurmctld");
|
||||
@ -81,12 +116,17 @@ in {
|
||||
}
|
||||
};
|
||||
|
||||
# Test that the cluster work and can distribute jobs;
|
||||
# Test that the cluster works and can distribute jobs;
|
||||
|
||||
subtest "run_distributed_command", sub {
|
||||
# Run `hostname` on 3 nodes of the partition (so on all the 3 nodes).
|
||||
# The output must contain the 3 different names
|
||||
$submit->succeed("srun -N 3 hostname | sort | uniq | wc -l | xargs test 3 -eq");
|
||||
};
|
||||
|
||||
subtest "check_slurm_dbd", sub {
|
||||
# find the srun job from above in the database
|
||||
$submit->succeed("sacct | grep hostname");
|
||||
};
|
||||
'';
|
||||
})
|
||||
|
47
nixos/tests/solr.nix
Normal file
47
nixos/tests/solr.nix
Normal file
@ -0,0 +1,47 @@
|
||||
import ./make-test.nix ({ pkgs, lib, ... }:
|
||||
{
|
||||
name = "solr";
|
||||
meta.maintainers = [ lib.maintainers.aanderse ];
|
||||
|
||||
machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
# Ensure the virtual machine has enough memory for Solr to avoid the following error:
|
||||
#
|
||||
# OpenJDK 64-Bit Server VM warning:
|
||||
# INFO: os::commit_memory(0x00000000e8000000, 402653184, 0)
|
||||
# failed; error='Cannot allocate memory' (errno=12)
|
||||
#
|
||||
# There is insufficient memory for the Java Runtime Environment to continue.
|
||||
# Native memory allocation (mmap) failed to map 402653184 bytes for committing reserved memory.
|
||||
virtualisation.memorySize = 2000;
|
||||
|
||||
services.solr.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
|
||||
$machine->waitForUnit('solr.service');
|
||||
$machine->waitForOpenPort('8983');
|
||||
$machine->succeed('curl --fail http://localhost:8983/solr/');
|
||||
|
||||
# adapted from pkgs.solr/examples/films/README.txt
|
||||
$machine->succeed('sudo -u solr solr create -c films');
|
||||
$machine->succeed(q(curl http://localhost:8983/solr/films/schema -X POST -H 'Content-type:application/json' --data-binary '{
|
||||
"add-field" : {
|
||||
"name":"name",
|
||||
"type":"text_general",
|
||||
"multiValued":false,
|
||||
"stored":true
|
||||
},
|
||||
"add-field" : {
|
||||
"name":"initial_release_date",
|
||||
"type":"pdate",
|
||||
"stored":true
|
||||
}
|
||||
}')) =~ /"status":0/ or die;
|
||||
$machine->succeed('sudo -u solr post -c films ${pkgs.solr}/example/films/films.json');
|
||||
$machine->succeed('curl http://localhost:8983/solr/films/query?q=name:batman') =~ /"name":"Batman Begins"/ or die;
|
||||
'';
|
||||
})
|
@ -90,5 +90,5 @@ rec {
|
||||
parity-beta = callPackage ./parity/beta.nix { };
|
||||
parity-ui = callPackage ./parity-ui { };
|
||||
|
||||
particl-core = callPackage ./particl/particl-core.nix { boost = boost165; miniupnpc = miniupnpc_2; };
|
||||
particl-core = callPackage ./particl/particl-core.nix { miniupnpc = miniupnpc_2; };
|
||||
}
|
||||
|
@ -11,13 +11,13 @@ with stdenv.lib;
|
||||
stdenv.mkDerivation rec {
|
||||
|
||||
name = "litecoin" + (toString (optional (!withGui) "d")) + "-" + version;
|
||||
version = "0.16.2";
|
||||
version = "0.16.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "litecoin-project";
|
||||
repo = "litecoin";
|
||||
rev = "v${version}";
|
||||
sha256 = "0xfwh7cxxz6w8kgr4kl48w3zm81n1hv8fxb5l9zx3460im1ffgy6";
|
||||
sha256 = "0vc184qfdkjky1qffa7309k6973k4197bkzwcmffc9r5sdfhrhkp";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkgconfig autoreconfHook ];
|
||||
|
@ -10,31 +10,40 @@
|
||||
, zeromq
|
||||
, zlib
|
||||
, unixtools
|
||||
, python3
|
||||
}:
|
||||
|
||||
with stdenv.lib;
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "particl-core-${version}";
|
||||
version = "0.16.2.0";
|
||||
version = "0.17.0.2";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/particl/particl-core/archive/v${version}.tar.gz";
|
||||
sha256 = "1d2vvg7avlhsg0rcpd5pbzafnk1w51a2y29xjjkpafi6iqs2l617";
|
||||
sha256 = "0bkxdayl0jrfhgz8qzqqpwzv0yavz3nwsn6c8k003jnbcw65fkhx";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkgconfig autoreconfHook ];
|
||||
buildInputs = [
|
||||
openssl db48 boost zlib miniupnpc libevent zeromq
|
||||
unixtools.hexdump
|
||||
buildInputs = [ openssl db48 boost zlib miniupnpc libevent zeromq unixtools.hexdump python3 ];
|
||||
|
||||
configureFlags = [
|
||||
"--disable-bench"
|
||||
"--with-boost-libdir=${boost.out}/lib"
|
||||
] ++ optionals (!doCheck) [
|
||||
"--enable-tests=no"
|
||||
];
|
||||
|
||||
configureFlags = [ "--with-boost-libdir=${boost.out}/lib" ];
|
||||
# Always check during Hydra builds
|
||||
doCheck = true;
|
||||
preCheck = "patchShebangs test";
|
||||
enableParallelBuilding = true;
|
||||
|
||||
meta = {
|
||||
description = "Privacy-Focused Marketplace & Decentralized Application Platform";
|
||||
longDescription= ''
|
||||
An open source, decentralized privacy platform built for global person to person eCommerce.
|
||||
RPC daemon and CLI client only.
|
||||
'';
|
||||
homepage = https://particl.io/;
|
||||
maintainers = with maintainers; [ demyanrogozhin ];
|
||||
|
30
pkgs/applications/audio/avldrums-lv2/default.nix
Normal file
30
pkgs/applications/audio/avldrums-lv2/default.nix
Normal file
@ -0,0 +1,30 @@
|
||||
{ stdenv, fetchFromGitHub, pkgconfig, pango, cairo, libGLU, lv2 }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "${pname}-${version}";
|
||||
pname = "avldrums.lv2";
|
||||
version = "0.3.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "x42";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "0w51gdshq2i5bix2x5l3g3gnycy84nlzf5sj0jkrw0zrnbk6ghwg";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
installFlags = "PREFIX=$(out)";
|
||||
|
||||
nativeBuildInputs = [ pkgconfig ];
|
||||
buildInputs = [
|
||||
pango cairo libGLU lv2
|
||||
];
|
||||
|
||||
meta = with stdenv.lib; {
|
||||
description = "Dedicated AVLDrumkits LV2 Plugin";
|
||||
homepage = http://x42-plugins.com/x42/x42-avldrums;
|
||||
license = licenses.gpl2;
|
||||
maintainers = [ maintainers.magnetophon ];
|
||||
platforms = [ "i686-linux" "x86_64-linux" ];
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user