Merge branch 'master' into add_vim_plugins
This commit is contained in:
commit
cbd14de2c0
@ -253,8 +253,19 @@
|
||||
or also with <varname>crossSystem</varname>, in which case packages run on the latter, but all building happens on the former.
|
||||
Both parameters take the same schema as the 3 (build, host, and target) platforms defined in the previous section.
|
||||
As mentioned above, <literal>lib.systems.examples</literal> has some platforms which are used as arguments for these parameters in practice.
|
||||
You can use them programmatically, or on the command line like <command>nix-build <nixpkgs> --arg crossSystem '(import <nixpkgs/lib>).systems.examples.fooBarBaz'</command>.
|
||||
You can use them programmatically, or on the command line: <programlisting>
|
||||
nix-build <nixpkgs> --arg crossSystem '(import <nixpkgs/lib>).systems.examples.fooBarBaz' -A whatever</programlisting>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Eventually we would like to make these platform examples an unnecessary convenience so that <programlisting>
|
||||
nix-build <nixpkgs> --arg crossSystem.config '<arch>-<os>-<vendor>-<abi>' -A whatever</programlisting>
|
||||
works in the vast majority of cases.
|
||||
The problem today is dependencies on other sorts of configuration which aren't given proper defaults.
|
||||
We rely on the examples to crudely to set those configuration parameters in some vaguely sane manner on the users behalf.
|
||||
Issue <link xlink:href="https://github.com/NixOS/nixpkgs/issues/34274">#34274</link> tracks this inconvenience along with its root cause in crufty configuration options.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
While one is free to pass both parameters in full, there's a lot of logic to fill in missing fields.
|
||||
As discussed in the previous section, only one of <varname>system</varname>, <varname>config</varname>, and <varname>parsed</varname> is needed to infer the other two.
|
||||
|
@ -334,14 +334,10 @@ navigate there.
|
||||
|
||||
Finally, you can run
|
||||
```shell
|
||||
hoogle server -p 8080
|
||||
hoogle server -p 8080 --local
|
||||
```
|
||||
and navigate to http://localhost:8080/ for your own local
|
||||
[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and
|
||||
possibly other browsers disallow navigation from `http:` to `file:` URIs for
|
||||
security reasons, which might be quite an inconvenience. See [this
|
||||
page](http://kb.mozillazine.org/Links_to_local_pages_do_not_work) for
|
||||
workarounds.
|
||||
[Hoogle](https://www.haskell.org/hoogle/).
|
||||
|
||||
### How to build a Haskell project using Stack
|
||||
|
||||
|
@ -79,19 +79,24 @@ an example for a minimal `hello` crate:
|
||||
Now, the file produced by the call to `carnix`, called `hello.nix`, looks like:
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
|
||||
{ lib, buildPlatform, buildRustCrate, fetchgit }:
|
||||
let kernel = buildPlatform.parsed.kernel.name;
|
||||
# ... (content skipped)
|
||||
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "hello";
|
||||
version = "0.1.0";
|
||||
authors = [ "Authorname <user@example.com>" ];
|
||||
src = ./.;
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
in
|
||||
rec {
|
||||
hello_0_1_0 = hello_0_1_0_ rec {};
|
||||
hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; };
|
||||
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "hello";
|
||||
version = "0.1.0";
|
||||
authors = [ "pe@pijul.org <pe@pijul.org>" ];
|
||||
src = ./.;
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {};
|
||||
hello_0_1_0_features = f: updateFeatures f (rec {
|
||||
hello_0_1_0.default = (f.hello_0_1_0.default or true);
|
||||
}) [ ];
|
||||
}
|
||||
```
|
||||
|
||||
@ -103,33 +108,44 @@ dependencies, for instance by adding a single line `libc="*"` to our
|
||||
following nix file:
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
# Generated by carnix 0.6.5: carnix -o hello.nix --src ./. Cargo.lock --standalone
|
||||
{ lib, buildPlatform, buildRustCrate, fetchgit }:
|
||||
let kernel = buildPlatform.parsed.kernel.name;
|
||||
# ... (content skipped)
|
||||
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "hello";
|
||||
version = "0.1.0";
|
||||
authors = [ "Jörg Thalheim <joerg@thalheim.io>" ];
|
||||
src = ./.;
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
libc_0_2_34_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "libc";
|
||||
version = "0.2.34";
|
||||
authors = [ "The Rust Project Developers" ];
|
||||
sha256 = "11jmqdxmv0ka10ay0l8nzx0nl7s2lc3dbrnh1mgbr2grzwdyxi2s";
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
in
|
||||
rec {
|
||||
hello_0_1_0 = hello_0_1_0_ rec {
|
||||
dependencies = [ libc_0_2_34 ];
|
||||
hello = f: hello_0_1_0 { features = hello_0_1_0_features { hello_0_1_0 = f; }; };
|
||||
hello_0_1_0_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "hello";
|
||||
version = "0.1.0";
|
||||
authors = [ "pe@pijul.org <pe@pijul.org>" ];
|
||||
src = ./.;
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
libc_0_2_34_features."default".from_hello_0_1_0__default = true;
|
||||
libc_0_2_34 = libc_0_2_34_ rec {
|
||||
features = mkFeatures libc_0_2_34_features;
|
||||
libc_0_2_36_ = { dependencies?[], buildDependencies?[], features?[] }: buildRustCrate {
|
||||
crateName = "libc";
|
||||
version = "0.2.36";
|
||||
authors = [ "The Rust Project Developers" ];
|
||||
sha256 = "01633h4yfqm0s302fm0dlba469bx8y6cs4nqc8bqrmjqxfxn515l";
|
||||
inherit dependencies buildDependencies features;
|
||||
};
|
||||
libc_0_2_34_features."use_std".self_default = hasDefault libc_0_2_34_features;
|
||||
hello_0_1_0 = { features?(hello_0_1_0_features {}) }: hello_0_1_0_ {
|
||||
dependencies = mapFeatures features ([ libc_0_2_36 ]);
|
||||
};
|
||||
hello_0_1_0_features = f: updateFeatures f (rec {
|
||||
hello_0_1_0.default = (f.hello_0_1_0.default or true);
|
||||
libc_0_2_36.default = true;
|
||||
}) [ libc_0_2_36_features ];
|
||||
libc_0_2_36 = { features?(libc_0_2_36_features {}) }: libc_0_2_36_ {
|
||||
features = mkFeatures (features.libc_0_2_36 or {});
|
||||
};
|
||||
libc_0_2_36_features = f: updateFeatures f (rec {
|
||||
libc_0_2_36.default = (f.libc_0_2_36.default or true);
|
||||
libc_0_2_36.use_std =
|
||||
(f.libc_0_2_36.use_std or false) ||
|
||||
(f.libc_0_2_36.default or false) ||
|
||||
(libc_0_2_36.default or false);
|
||||
}) [];
|
||||
}
|
||||
```
|
||||
|
||||
@ -146,7 +162,7 @@ or build inputs by overriding the hello crate in a seperate file.
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
(import ./hello.nix).hello_0_1_0.override {
|
||||
((import ./hello.nix).hello {}).override {
|
||||
crateOverrides = defaultCrateOverrides // {
|
||||
hello = attrs: { buildInputs = [ openssl ]; };
|
||||
};
|
||||
@ -166,7 +182,7 @@ patches the derivation:
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
(import ./hello.nix).hello_0_1_0.override {
|
||||
((import ./hello.nix).hello {}).override {
|
||||
crateOverrides = defaultCrateOverrides // {
|
||||
hello = attrs: lib.optionalAttrs (lib.versionAtLeast attrs.version "1.0") {
|
||||
postPatch = ''
|
||||
@ -187,7 +203,7 @@ crate, we could do:
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
(import hello.nix).hello_0_1_0.override {
|
||||
((import hello.nix).hello {}).override {
|
||||
crateOverrides = defaultCrateOverrides // {
|
||||
libc = attrs: { buildInputs = []; };
|
||||
};
|
||||
@ -199,23 +215,35 @@ Three more parameters can be overridden:
|
||||
- The version of rustc used to compile the crate:
|
||||
|
||||
```
|
||||
hello_0_1_0.override { rust = pkgs.rust; };
|
||||
(hello {}).override { rust = pkgs.rust; };
|
||||
```
|
||||
|
||||
- Whether to build in release mode or debug mode (release mode by
|
||||
default):
|
||||
|
||||
```
|
||||
hello_0_1_0.override { release = false; };
|
||||
(hello {}).override { release = false; };
|
||||
```
|
||||
|
||||
- Whether to print the commands sent to rustc when building
|
||||
(equivalent to `--verbose` in cargo:
|
||||
|
||||
```
|
||||
hello_0_1_0.override { verbose = false; };
|
||||
(hello {}).override { verbose = false; };
|
||||
```
|
||||
|
||||
One can also supply features switches. For example, if we want to
|
||||
compile `diesel_cli` only with the `postgres` feature, and no default
|
||||
features, we would write:
|
||||
|
||||
```
|
||||
(callPackage ./diesel.nix {}).diesel {
|
||||
default = false;
|
||||
postgres = true;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Using the Rust nightlies overlay
|
||||
|
||||
|
@ -660,6 +660,32 @@ cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el
|
||||
passing <command>-q</command> to the Emacs command.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Sometimes <varname>emacsWithPackages</varname> is not enough, as
|
||||
this package set has some priorities imposed on packages (with
|
||||
the lowest priority assigned to Melpa Unstable, and the highest for
|
||||
packages manually defined in
|
||||
<filename>pkgs/top-level/emacs-packages.nix</filename>). But you
|
||||
can't control this priorities when some package is installed as a
|
||||
dependency. You can override it on per-package-basis, providing all
|
||||
the required dependencies manually - but it's tedious and there is
|
||||
always a possibility that an unwanted dependency will sneak in
|
||||
through some other package. To completely override such a package
|
||||
you can use <varname>overrideScope</varname>.
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
overrides = super: self: rec {
|
||||
haskell-mode = self.melpaPackages.haskell-mode;
|
||||
...
|
||||
};
|
||||
((emacsPackagesNgGen emacs).overrideScope overrides).emacsWithPackages (p: with p; [
|
||||
# here both these package will use haskell-mode of our own choice
|
||||
ghc-mod
|
||||
dante
|
||||
])
|
||||
</screen>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
@ -1802,6 +1802,20 @@ addEnvHooks "$hostOffset" myBashFunction
|
||||
disabled or patched to work with PaX.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>autoPatchelfHook</term>
|
||||
<listitem><para>This is a special setup hook which helps in packaging
|
||||
proprietary software in that it automatically tries to find missing shared
|
||||
library dependencies of ELF files. All packages within the
|
||||
<envar>runtimeDependencies</envar> environment variable are unconditionally
|
||||
added to executables, which is useful for programs that use
|
||||
<citerefentry>
|
||||
<refentrytitle>dlopen</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</citerefentry>
|
||||
to load libraries at runtime.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ lib }:
|
||||
let
|
||||
|
||||
inherit (builtins) attrNames isFunction;
|
||||
inherit (builtins) attrNames;
|
||||
|
||||
in
|
||||
|
||||
@ -72,7 +72,7 @@ rec {
|
||||
makeOverridable = f: origArgs:
|
||||
let
|
||||
ff = f origArgs;
|
||||
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
|
||||
overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
|
||||
in
|
||||
if builtins.isAttrs ff then (ff // {
|
||||
override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
@ -81,7 +81,7 @@ rec {
|
||||
${if ff ? overrideAttrs then "overrideAttrs" else null} = fdrv:
|
||||
makeOverridable (args: (f args).overrideAttrs fdrv) origArgs;
|
||||
})
|
||||
else if builtins.isFunction ff then {
|
||||
else if lib.isFunction ff then {
|
||||
override = newArgs: makeOverridable f (overrideWith newArgs);
|
||||
__functor = self: ff;
|
||||
overrideDerivation = throw "overrideDerivation not yet supported for functors";
|
||||
@ -112,8 +112,8 @@ rec {
|
||||
*/
|
||||
callPackageWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
f = if lib.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
|
||||
in makeOverridable f (auto // args);
|
||||
|
||||
|
||||
@ -122,8 +122,8 @@ rec {
|
||||
individual attributes. */
|
||||
callPackagesWith = autoArgs: fn: args:
|
||||
let
|
||||
f = if builtins.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
|
||||
f = if lib.isFunction fn then fn else import fn;
|
||||
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
|
||||
origArgs = auto // args;
|
||||
pkgs = f origArgs;
|
||||
mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
let
|
||||
|
||||
inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt
|
||||
inherit (builtins) trace attrNamesToStr isAttrs isList isInt
|
||||
isString isBool head substring attrNames;
|
||||
|
||||
inherit (lib) all id mapAttrsFlatten elem;
|
||||
inherit (lib) all id mapAttrsFlatten elem isFunction;
|
||||
|
||||
in
|
||||
|
||||
|
@ -51,12 +51,13 @@ let
|
||||
|
||||
inherit (builtins) add addErrorContext attrNames
|
||||
concatLists deepSeq elem elemAt filter genericClosure genList
|
||||
getAttr hasAttr head isAttrs isBool isFunction isInt isList
|
||||
getAttr hasAttr head isAttrs isBool isInt isList
|
||||
isString length lessThan listToAttrs pathExists readFile
|
||||
replaceStrings seq stringLength sub substring tail;
|
||||
inherit (trivial) id const concat or and boolToString mergeAttrs
|
||||
flip mapNullable inNixShell min max importJSON warn info
|
||||
nixpkgsVersion mod;
|
||||
nixpkgsVersion mod compare splitByAndCompare
|
||||
functionArgs setFunctionArgs isFunction;
|
||||
|
||||
inherit (fixedPoints) fix fix' extends composeExtensions
|
||||
makeExtensible makeExtensibleWithCustomName;
|
||||
@ -71,8 +72,8 @@ let
|
||||
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
|
||||
concatMap flatten remove findSingle findFirst any all count
|
||||
optional optionals toList range partition zipListsWith zipLists
|
||||
reverseList listDfs toposort sort take drop sublist last init
|
||||
crossLists unique intersectLists subtractLists
|
||||
reverseList listDfs toposort sort compareLists take drop sublist
|
||||
last init crossLists unique intersectLists subtractLists
|
||||
mutuallyExclusive;
|
||||
inherit (strings) concatStrings concatMapStrings concatImapStrings
|
||||
intersperse concatStringsSep concatMapStringsSep
|
||||
|
@ -1,6 +1,6 @@
|
||||
{ lib }:
|
||||
let
|
||||
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
|
||||
inherit (builtins) head tail isList isAttrs isInt attrNames;
|
||||
|
||||
in
|
||||
|
||||
@ -53,7 +53,7 @@ rec {
|
||||
f: # the function applied to the arguments
|
||||
initial: # you pass attrs, the functions below are passing a function taking the fix argument
|
||||
let
|
||||
takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
|
||||
takeFixed = if lib.isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
|
||||
tidy = args:
|
||||
let # apply all functions given in "applyPreTidy" in sequence
|
||||
applyPreTidyFun = fold ( n: a: x: n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
|
||||
@ -63,7 +63,7 @@ rec {
|
||||
let args = takeFixed fixed;
|
||||
mergeFun = args.${n};
|
||||
in if isAttrs x then (mergeFun args x)
|
||||
else assert isFunction x;
|
||||
else assert lib.isFunction x;
|
||||
mergeFun args (x ( args // { inherit fixed; }));
|
||||
in overridableDelayableArgs f newArgs;
|
||||
in
|
||||
@ -374,7 +374,7 @@ rec {
|
||||
if isAttrs x then
|
||||
if x ? outPath then "derivation"
|
||||
else "attrs"
|
||||
else if isFunction x then "function"
|
||||
else if lib.isFunction x then "function"
|
||||
else if isList x then "list"
|
||||
else if x == true then "bool"
|
||||
else if x == false then "bool"
|
||||
|
@ -14,6 +14,8 @@ let
|
||||
libAttr = lib.attrsets;
|
||||
|
||||
flipMapAttrs = flip libAttr.mapAttrs;
|
||||
|
||||
inherit (lib) isFunction;
|
||||
in
|
||||
|
||||
rec {
|
||||
@ -110,7 +112,7 @@ rec {
|
||||
else if isString v then "\"" + v + "\""
|
||||
else if null == v then "null"
|
||||
else if isFunction v then
|
||||
let fna = functionArgs v;
|
||||
let fna = lib.functionArgs v;
|
||||
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
|
||||
(name: hasDefVal: if hasDefVal then "(${name})" else name)
|
||||
fna);
|
||||
|
@ -200,6 +200,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||
fullName = "Eclipse Public License 1.0";
|
||||
};
|
||||
|
||||
epl20 = spdx {
|
||||
spdxId = "EPL-2.0";
|
||||
fullName = "Eclipse Public License 2.0";
|
||||
};
|
||||
|
||||
epson = {
|
||||
fullName = "Seiko Epson Corporation Software License Agreement for Linux";
|
||||
url = https://download.ebz.epson.net/dsc/du/02/eula/global/LINUX_EN.html;
|
||||
|
@ -385,6 +385,30 @@ rec {
|
||||
if len < 2 then list
|
||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
|
||||
|
||||
/* Compare two lists element-by-element.
|
||||
|
||||
Example:
|
||||
compareLists compare [] []
|
||||
=> 0
|
||||
compareLists compare [] [ "a" ]
|
||||
=> -1
|
||||
compareLists compare [ "a" ] []
|
||||
=> 1
|
||||
compareLists compare [ "a" "b" ] [ "a" "c" ]
|
||||
=> 1
|
||||
*/
|
||||
compareLists = cmp: a: b:
|
||||
if a == []
|
||||
then if b == []
|
||||
then 0
|
||||
else -1
|
||||
else if b == []
|
||||
then 1
|
||||
else let rel = cmp (head a) (head b); in
|
||||
if rel == 0
|
||||
then compareLists cmp (tail a) (tail b)
|
||||
else rel;
|
||||
|
||||
/* Return the first (at most) N elements of a list.
|
||||
|
||||
Example:
|
||||
@ -440,8 +464,12 @@ rec {
|
||||
init = list: assert list != []; take (length list - 1) list;
|
||||
|
||||
|
||||
/* FIXME(zimbatm) Not used anywhere
|
||||
*/
|
||||
/* 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]]
|
||||
=> [ "13" "14" "23" "24" ]
|
||||
*/
|
||||
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
||||
|
||||
|
||||
|
@ -225,12 +225,14 @@
|
||||
ertes = "Ertugrul Söylemez <esz@posteo.de>";
|
||||
ethercrow = "Dmitry Ivanov <ethercrow@gmail.com>";
|
||||
etu = "Elis Hirwing <elis@hirwing.se>";
|
||||
exfalso = "Andras Slemmer <0slemi0@gmail.com>";
|
||||
exi = "Reno Reckling <nixos@reckling.org>";
|
||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||
expipiplus1 = "Joe Hermaszewski <nix@monoid.al>";
|
||||
fadenb = "Tristan Helmich <tristan.helmich+nixos@gmail.com>";
|
||||
falsifian = "James Cook <james.cook@utoronto.ca>";
|
||||
fare = "Francois-Rene Rideau <fahree@gmail.com>";
|
||||
f-breidenstein = "Felix Breidenstein <mail@felixbreidenstein.de>";
|
||||
fgaz = "Francesco Gazzetta <francygazz@gmail.com>";
|
||||
FireyFly = "Jonas Höglund <nix@firefly.nu>";
|
||||
flokli = "Florian Klink <flokli@flokli.de>";
|
||||
@ -257,6 +259,7 @@
|
||||
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
||||
gebner = "Gabriel Ebner <gebner@gebner.org>";
|
||||
geistesk = "Alvar Penning <post@0x21.biz>";
|
||||
genesis = "Ronan Bignaux <ronan@aimao.org>";
|
||||
georgewhewell = "George Whewell <georgerw@gmail.com>";
|
||||
gilligan = "Tobias Pflug <tobias.pflug@gmail.com>";
|
||||
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
||||
@ -328,6 +331,7 @@
|
||||
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
|
||||
joelteon = "Joel Taylor <me@joelt.io>";
|
||||
johbo = "Johannes Bornhold <johannes@bornhold.name>";
|
||||
johnazoidberg = "Daniel Schäfer <git@danielschaefer.me>";
|
||||
johnmh = "John M. Harris, Jr. <johnmh@openblox.org>";
|
||||
johnramsden = "John Ramsden <johnramsden@riseup.net>";
|
||||
joko = "Ioannis Koutras <ioannis.koutras@gmail.com>";
|
||||
@ -445,6 +449,7 @@
|
||||
mirrexagon = "Andrew Abbott <mirrexagon@mirrexagon.com>";
|
||||
mjanczyk = "Marcin Janczyk <m@dragonvr.pl>";
|
||||
mjp = "Mike Playle <mike@mythik.co.uk>"; # github = "MikePlayle";
|
||||
mkg = "Mark K Gardner <mkg@vt.edu>";
|
||||
mlieberman85 = "Michael Lieberman <mlieberman85@gmail.com>";
|
||||
mmahut = "Marek Mahut <marek.mahut@gmail.com>";
|
||||
moaxcp = "John Mercier <moaxcp@gmail.com>";
|
||||
@ -459,6 +464,7 @@
|
||||
mounium = "Katona László <muoniurn@gmail.com>";
|
||||
MP2E = "Cray Elliott <MP2E@archlinux.us>";
|
||||
mpcsh = "Mark Cohen <m@mpc.sh>";
|
||||
mpickering = "Matthew Pickering <matthewtpickering@gmail.com>";
|
||||
mpscholten = "Marc Scholten <marc@mpscholten.de>";
|
||||
mpsyco = "Francis St-Amour <fr.st-amour@gmail.com>";
|
||||
mrVanDalo = "Ingolf Wanger <contact@ingolf-wagner.de>";
|
||||
@ -541,6 +547,7 @@
|
||||
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
|
||||
pmeunier = "Pierre-Étienne Meunier <pierre-etienne.meunier@inria.fr>";
|
||||
pmiddend = "Philipp Middendorf <pmidden@secure.mailbox.org>";
|
||||
pneumaticat = "Kevin Liu <kevin@potatofrom.space>";
|
||||
polyrod = "Maurizio Di Pietro <dc1mdp@gmail.com>";
|
||||
pradeepchhetri = "Pradeep Chhetri <pradeep.chhetri89@gmail.com>";
|
||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||
@ -561,6 +568,7 @@
|
||||
rasendubi = "Alexey Shmalko <rasen.dubi@gmail.com>";
|
||||
raskin = "Michael Raskin <7c6f434c@mail.ru>";
|
||||
ravloony = "Tom Macdonald <ravloony@gmail.com>";
|
||||
razvan = "Răzvan Flavius Panda <razvan.panda@gmail.com>";
|
||||
rbasso = "Rafael Basso <rbasso@sharpgeeks.net>";
|
||||
redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>";
|
||||
redvers = "Redvers Davies <red@infect.me>";
|
||||
@ -610,12 +618,14 @@
|
||||
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
|
||||
schneefux = "schneefux <schneefux+nixos_pkg@schneefux.xyz>";
|
||||
schristo = "Scott Christopher <schristopher@konputa.com>";
|
||||
scode = "Peter Schuller <peter.schuller@infidyne.com>";
|
||||
scolobb = "Sergiu Ivanov <sivanov@colimite.fr>";
|
||||
sdll = "Sasha Illarionov <sasha.delly@gmail.com>";
|
||||
SeanZicari = "Sean Zicari <sean.zicari@gmail.com>";
|
||||
sellout = "Greg Pfeil <greg@technomadic.org>";
|
||||
sepi = "Raffael Mancini <raffael@mancini.lu>";
|
||||
seppeljordan = "Sebastian Jordan <sebastian.jordan.mail@googlemail.com>";
|
||||
sfrijters = "Stefan Frijters <sfrijters@gmail.com>";
|
||||
shanemikel = "Shane Pearlman <shanemikel1@gmail.com>";
|
||||
shawndellysse = "Shawn Dellysse <sdellysse@gmail.com>";
|
||||
sheenobu = "Sheena Artrip <sheena.artrip@gmail.com>";
|
||||
@ -679,6 +689,7 @@
|
||||
ThomasMader = "Thomas Mader <thomas.mader@gmail.com>";
|
||||
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
|
||||
thpham = "Thomas Pham <thomas.pham@ithings.ch>";
|
||||
tilpner = "Till Höppner <till@hoeppner.ws>";
|
||||
timbertson = "Tim Cuthbertson <tim@gfxmonk.net>";
|
||||
timokau = "Timo Kaufmann <timokau@zoho.com>";
|
||||
tiramiseb = "Sébastien Maccagnoni <sebastien@maccagnoni.eu>";
|
||||
@ -689,6 +700,7 @@
|
||||
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
||||
tomsmeets = "Tom Smeets <tom@tsmeets.nl>";
|
||||
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
|
||||
treemo = "Matthieu Chevrier <matthieu.chevrier@treemo.fr>";
|
||||
trevorj = "Trevor Joynson <nix@trevor.joynson.io>";
|
||||
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
|
||||
tstrobel = "Thomas Strobel <4ZKTUB6TEP74PYJOPWIR013S2AV29YUBW5F9ZH2F4D5UMJUJ6S@hash.domains>";
|
||||
@ -698,6 +710,7 @@
|
||||
tvorog = "Marsel Zaripov <marszaripov@gmail.com>";
|
||||
tweber = "Thorsten Weber <tw+nixpkgs@360vier.de>";
|
||||
twey = "James ‘Twey’ Kay <twey@twey.co.uk>";
|
||||
unode = "Renato Alves <alves.rjc@gmail.com>";
|
||||
uralbash = "Svintsov Dmitry <root@uralbash.ru>";
|
||||
utdemir = "Utku Demir <me@utdemir.com>";
|
||||
#urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012
|
||||
@ -707,6 +720,7 @@
|
||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||
vanschelven = "Klaas van Schelven <klaas@vanschelven.com>";
|
||||
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
|
||||
varunpatro = "Varun Patro <varun.kumar.patro@gmail.com>";
|
||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||
|
@ -155,7 +155,7 @@ rec {
|
||||
# a module will resolve strictly the attributes used as argument but
|
||||
# not their values. The values are forwarding the result of the
|
||||
# evaluation of the option.
|
||||
requiredArgs = builtins.attrNames (builtins.functionArgs f);
|
||||
requiredArgs = builtins.attrNames (lib.functionArgs f);
|
||||
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
|
||||
extraArgs = builtins.listToAttrs (map (name: {
|
||||
inherit name;
|
||||
|
@ -14,6 +14,7 @@ rec {
|
||||
, 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.
|
||||
@ -76,7 +77,6 @@ rec {
|
||||
getValues = map (x: x.value);
|
||||
getFiles = map (x: x.file);
|
||||
|
||||
|
||||
# Generate documentation template from the list of option declaration like
|
||||
# the set generated with filterOptionSets.
|
||||
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
||||
@ -93,9 +93,10 @@ rec {
|
||||
readOnly = opt.readOnly or false;
|
||||
type = opt.type.description or null;
|
||||
}
|
||||
// (if opt ? example then { example = scrubOptionValue opt.example; } else {})
|
||||
// (if opt ? default then { default = scrubOptionValue opt.default; } else {})
|
||||
// (if opt ? defaultText then { default = opt.defaultText; } else {});
|
||||
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
|
||||
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
|
||||
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; }
|
||||
// optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) { inherit (opt) relatedPackages; };
|
||||
|
||||
subOptions =
|
||||
let ss = opt.type.getSubOptions opt.loc;
|
||||
|
@ -1,8 +1,8 @@
|
||||
{ lib }:
|
||||
let
|
||||
inherit (lib) lists;
|
||||
parse = import ./parse.nix { inherit lib; };
|
||||
inherit (import ./inspect.nix { inherit lib; }) predicates;
|
||||
inherit (lib.systems) parse;
|
||||
inherit (lib.systems.inspect) predicates;
|
||||
inherit (lib.attrsets) matchAttrs;
|
||||
|
||||
all = [
|
||||
|
@ -11,44 +11,33 @@ rec {
|
||||
|
||||
sheevaplug = rec {
|
||||
config = "armv5tel-unknown-linux-gnueabi";
|
||||
bigEndian = false;
|
||||
arch = "armv5tel";
|
||||
float = "soft";
|
||||
withTLS = true;
|
||||
libc = "glibc";
|
||||
platform = platforms.sheevaplug;
|
||||
openssl.system = "linux-generic32";
|
||||
};
|
||||
|
||||
raspberryPi = rec {
|
||||
config = "armv6l-unknown-linux-gnueabihf";
|
||||
bigEndian = false;
|
||||
arch = "armv6l";
|
||||
float = "hard";
|
||||
fpu = "vfp";
|
||||
withTLS = true;
|
||||
libc = "glibc";
|
||||
platform = platforms.raspberrypi;
|
||||
openssl.system = "linux-generic32";
|
||||
};
|
||||
|
||||
armv7l-hf-multiplatform = rec {
|
||||
config = "arm-unknown-linux-gnueabihf";
|
||||
bigEndian = false;
|
||||
arch = "armv7-a";
|
||||
float = "hard";
|
||||
fpu = "vfpv3-d16";
|
||||
withTLS = true;
|
||||
libc = "glibc";
|
||||
platform = platforms.armv7l-hf-multiplatform;
|
||||
openssl.system = "linux-generic32";
|
||||
};
|
||||
|
||||
aarch64-multiplatform = rec {
|
||||
config = "aarch64-unknown-linux-gnu";
|
||||
bigEndian = false;
|
||||
arch = "aarch64";
|
||||
withTLS = true;
|
||||
libc = "glibc";
|
||||
platform = platforms.aarch64-multiplatform;
|
||||
};
|
||||
@ -62,24 +51,16 @@ rec {
|
||||
arch = "armv5tel";
|
||||
config = "armv5tel-unknown-linux-gnueabi";
|
||||
float = "soft";
|
||||
|
||||
platform = platforms.pogoplug4;
|
||||
|
||||
libc = "glibc";
|
||||
|
||||
withTLS = true;
|
||||
openssl.system = "linux-generic32";
|
||||
platform = platforms.pogoplug4;
|
||||
};
|
||||
|
||||
fuloongminipc = rec {
|
||||
config = "mips64el-unknown-linux-gnu";
|
||||
bigEndian = false;
|
||||
arch = "mips";
|
||||
float = "hard";
|
||||
withTLS = true;
|
||||
libc = "glibc";
|
||||
platform = platforms.fuloong2f_n32;
|
||||
openssl.system = "linux-generic32";
|
||||
};
|
||||
|
||||
#
|
||||
|
@ -5,8 +5,6 @@ with lib.lists;
|
||||
|
||||
rec {
|
||||
patterns = rec {
|
||||
"32bit" = { cpu = { bits = 32; }; };
|
||||
"64bit" = { cpu = { bits = 64; }; };
|
||||
i686 = { cpu = cpuTypes.i686; };
|
||||
x86_64 = { cpu = cpuTypes.x86_64; };
|
||||
PowerPC = { cpu = cpuTypes.powerpc; };
|
||||
@ -14,6 +12,11 @@ rec {
|
||||
Arm = { cpu = { family = "arm"; }; };
|
||||
Aarch64 = { cpu = { family = "aarch64"; }; };
|
||||
Mips = { cpu = { family = "mips"; }; };
|
||||
RiscV = { cpu = { family = "riscv"; }; };
|
||||
Wasm = { cpu = { family = "wasm"; }; };
|
||||
|
||||
"32bit" = { cpu = { bits = 32; }; };
|
||||
"64bit" = { cpu = { bits = 64; }; };
|
||||
BigEndian = { cpu = { significantByte = significantBytes.bigEndian; }; };
|
||||
LittleEndian = { cpu = { significantByte = significantBytes.littleEndian; }; };
|
||||
|
||||
|
@ -4,6 +4,16 @@
|
||||
# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially
|
||||
# Triple::normalize. Parsing should essentially act as a more conservative
|
||||
# version of that last function.
|
||||
#
|
||||
# Most of the types below come in "open" and "closed" pairs. The open ones
|
||||
# specify what information we need to know about systems in general, and the
|
||||
# closed ones are sub-types representing the whitelist of systems we support in
|
||||
# practice.
|
||||
#
|
||||
# Code in the remainder of nixpkgs shouldn't rely on the closed ones in
|
||||
# e.g. exhaustive cases. Its more a sanity check to make sure nobody defines
|
||||
# systems that overlap with existing ones and won't notice something amiss.
|
||||
#
|
||||
{ lib }:
|
||||
with lib.lists;
|
||||
with lib.types;
|
||||
@ -11,29 +21,52 @@ with lib.attrsets;
|
||||
with (import ./inspect.nix { inherit lib; }).predicates;
|
||||
|
||||
let
|
||||
setTypesAssert = type: pred:
|
||||
inherit (lib.options) mergeOneOption;
|
||||
|
||||
setTypes = type:
|
||||
mapAttrs (name: value:
|
||||
assert pred value;
|
||||
setType type ({ inherit name; } // value));
|
||||
setTypes = type: setTypesAssert type (_: true);
|
||||
assert type.check value;
|
||||
setType type.name ({ inherit name; } // value));
|
||||
|
||||
in
|
||||
|
||||
rec {
|
||||
|
||||
isSignificantByte = isType "significant-byte";
|
||||
significantBytes = setTypes "significant-byte" {
|
||||
################################################################################
|
||||
|
||||
types.openSignifiantByte = mkOptionType {
|
||||
name = "significant-byte";
|
||||
description = "Endianness";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
types.significantByte = enum (attrValues significantBytes);
|
||||
|
||||
significantBytes = setTypes types.openSignifiantByte {
|
||||
bigEndian = {};
|
||||
littleEndian = {};
|
||||
};
|
||||
|
||||
isCpuType = isType "cpu-type";
|
||||
cpuTypes = with significantBytes; setTypesAssert "cpu-type"
|
||||
(x: elem x.bits [8 16 32 64 128]
|
||||
&& (if 8 < x.bits
|
||||
then isSignificantByte x.significantByte
|
||||
else !(x ? significantByte)))
|
||||
{
|
||||
################################################################################
|
||||
|
||||
# Reasonable power of 2
|
||||
types.bitWidth = enum [ 8 16 32 64 128 ];
|
||||
|
||||
################################################################################
|
||||
|
||||
types.openCpuType = mkOptionType {
|
||||
name = "cpu-type";
|
||||
description = "instruction set architecture name and information";
|
||||
merge = mergeOneOption;
|
||||
check = x: types.bitWidth.check x.bits
|
||||
&& (if 8 < x.bits
|
||||
then types.significantByte.check x.significantByte
|
||||
else !(x ? significantByte));
|
||||
};
|
||||
|
||||
types.cpuType = enum (attrValues cpuTypes);
|
||||
|
||||
cpuTypes = with significantBytes; setTypes types.openCpuType {
|
||||
arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
|
||||
armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; };
|
||||
armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; };
|
||||
@ -44,18 +77,40 @@ rec {
|
||||
x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; };
|
||||
mips64el = { bits = 32; significantByte = littleEndian; family = "mips"; };
|
||||
powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
|
||||
riscv32 = { bits = 32; significantByte = littleEndian; family = "riscv"; };
|
||||
riscv64 = { bits = 64; significantByte = littleEndian; family = "riscv"; };
|
||||
wasm32 = { bits = 32; significantByte = littleEndian; family = "wasm"; };
|
||||
wasm64 = { bits = 64; significantByte = littleEndian; family = "wasm"; };
|
||||
};
|
||||
|
||||
isVendor = isType "vendor";
|
||||
vendors = setTypes "vendor" {
|
||||
################################################################################
|
||||
|
||||
types.openVendor = mkOptionType {
|
||||
name = "vendor";
|
||||
description = "vendor for the platform";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
types.vendor = enum (attrValues vendors);
|
||||
|
||||
vendors = setTypes types.openVendor {
|
||||
apple = {};
|
||||
pc = {};
|
||||
|
||||
unknown = {};
|
||||
};
|
||||
|
||||
isExecFormat = isType "exec-format";
|
||||
execFormats = setTypes "exec-format" {
|
||||
################################################################################
|
||||
|
||||
types.openExecFormat = mkOptionType {
|
||||
name = "exec-format";
|
||||
description = "executable container used by the kernel";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
types.execFormat = enum (attrValues execFormats);
|
||||
|
||||
execFormats = setTypes types.openExecFormat {
|
||||
aout = {}; # a.out
|
||||
elf = {};
|
||||
macho = {};
|
||||
@ -64,15 +119,33 @@ rec {
|
||||
unknown = {};
|
||||
};
|
||||
|
||||
isKernelFamily = isType "kernel-family";
|
||||
kernelFamilies = setTypes "kernel-family" {
|
||||
################################################################################
|
||||
|
||||
types.openKernelFamily = mkOptionType {
|
||||
name = "exec-format";
|
||||
description = "executable container used by the kernel";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
types.kernelFamily = enum (attrValues kernelFamilies);
|
||||
|
||||
kernelFamilies = setTypes types.openKernelFamily {
|
||||
bsd = {};
|
||||
};
|
||||
|
||||
isKernel = x: isType "kernel" x;
|
||||
kernels = with execFormats; with kernelFamilies; setTypesAssert "kernel"
|
||||
(x: isExecFormat x.execFormat && all isKernelFamily (attrValues x.families))
|
||||
{
|
||||
################################################################################
|
||||
|
||||
types.openKernel = mkOptionType {
|
||||
name = "kernel";
|
||||
description = "kernel name and information";
|
||||
merge = mergeOneOption;
|
||||
check = x: types.execFormat.check x.execFormat
|
||||
&& all types.kernelFamily.check (attrValues x.families);
|
||||
};
|
||||
|
||||
types.kernel = enum (attrValues kernels);
|
||||
|
||||
kernels = with execFormats; with kernelFamilies; setTypes types.openKernel {
|
||||
darwin = { execFormat = macho; families = { }; };
|
||||
freebsd = { execFormat = elf; families = { inherit bsd; }; };
|
||||
hurd = { execFormat = elf; families = { }; };
|
||||
@ -89,8 +162,17 @@ rec {
|
||||
win32 = kernels.windows;
|
||||
};
|
||||
|
||||
isAbi = isType "abi";
|
||||
abis = setTypes "abi" {
|
||||
################################################################################
|
||||
|
||||
types.openAbi = mkOptionType {
|
||||
name = "abi";
|
||||
description = "binary interface for compiled code and syscalls";
|
||||
merge = mergeOneOption;
|
||||
};
|
||||
|
||||
types.abi = enum (attrValues abis);
|
||||
|
||||
abis = setTypes types.openAbi {
|
||||
cygnus = {};
|
||||
gnu = {};
|
||||
msvc = {};
|
||||
@ -102,12 +184,24 @@ rec {
|
||||
unknown = {};
|
||||
};
|
||||
|
||||
################################################################################
|
||||
|
||||
types.system = mkOptionType {
|
||||
name = "system";
|
||||
description = "fully parsed representation of llvm- or nix-style platform tuple";
|
||||
merge = mergeOneOption;
|
||||
check = { cpu, vendor, kernel, abi }:
|
||||
types.cpuType.check cpu
|
||||
&& types.vendor.check vendor
|
||||
&& types.kernel.check kernel
|
||||
&& types.abi.check abi;
|
||||
};
|
||||
|
||||
isSystem = isType "system";
|
||||
mkSystem = { cpu, vendor, kernel, abi }:
|
||||
assert isCpuType cpu && isVendor vendor && isKernel kernel && isAbi abi;
|
||||
setType "system" {
|
||||
inherit cpu vendor kernel abi;
|
||||
};
|
||||
|
||||
mkSystem = components:
|
||||
assert types.system.check components;
|
||||
setType "system" components;
|
||||
|
||||
mkSkeletonFromList = l: {
|
||||
"2" = # We only do 2-part hacks for things Nix already supports
|
||||
@ -170,4 +264,6 @@ rec {
|
||||
optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
|
||||
in "${cpu.name}-${vendor.name}-${kernel.name}${optAbi}";
|
||||
|
||||
################################################################################
|
||||
|
||||
}
|
||||
|
@ -479,6 +479,11 @@ rec {
|
||||
kernelPreferBuiltin = true;
|
||||
kernelTarget = "zImage";
|
||||
kernelExtraConfig = ''
|
||||
# Serial port for Raspberry Pi 3. Upstream forgot to add it to the ARMv7 defconfig.
|
||||
SERIAL_8250_BCM2835AUX y
|
||||
SERIAL_8250_EXTENDED y
|
||||
SERIAL_8250_SHARE_IRQ y
|
||||
|
||||
# Fix broken sunxi-sid nvmem driver.
|
||||
TI_CPTS y
|
||||
|
||||
|
@ -52,7 +52,7 @@ rec {
|
||||
|
||||
# Pull in some builtins not included elsewhere.
|
||||
inherit (builtins)
|
||||
pathExists readFile isBool isFunction
|
||||
pathExists readFile isBool
|
||||
isInt add sub lessThan
|
||||
seq deepSeq genericClosure;
|
||||
|
||||
@ -81,6 +81,42 @@ rec {
|
||||
*/
|
||||
mod = base: int: base - (int * (builtins.div base int));
|
||||
|
||||
/* C-style comparisons
|
||||
|
||||
a < b, compare a b => -1
|
||||
a == b, compare a b => 0
|
||||
a > b, compare a b => 1
|
||||
*/
|
||||
compare = a: b:
|
||||
if a < b
|
||||
then -1
|
||||
else if a > b
|
||||
then 1
|
||||
else 0;
|
||||
|
||||
/* Split type into two subtypes by predicate `p`, take all elements
|
||||
of the first subtype to be less than all the elements of the
|
||||
second subtype, compare elements of a single subtype with `yes`
|
||||
and `no` respectively.
|
||||
|
||||
Example:
|
||||
|
||||
let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
|
||||
|
||||
cmp "a" "z" => -1
|
||||
cmp "fooa" "fooz" => -1
|
||||
|
||||
cmp "f" "a" => 1
|
||||
cmp "fooa" "a" => -1
|
||||
# while
|
||||
compare "fooa" "a" => 1
|
||||
|
||||
*/
|
||||
splitByAndCompare = p: yes: no: a: 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. */
|
||||
importJSON = path:
|
||||
builtins.fromJSON (builtins.readFile path);
|
||||
@ -99,4 +135,29 @@ rec {
|
||||
*/
|
||||
warn = msg: builtins.trace "WARNING: ${msg}";
|
||||
info = msg: builtins.trace "INFO: ${msg}";
|
||||
|
||||
# | Add metadata about expected function arguments to a function.
|
||||
# The metadata should match the format given by
|
||||
# builtins.functionArgs, i.e. a set from expected argument to a bool
|
||||
# representing whether that argument has a default or not.
|
||||
# setFunctionArgs : (a → b) → Map String Bool → (a → b)
|
||||
#
|
||||
# This function is necessary because you can't dynamically create a
|
||||
# function of the { a, b ? foo, ... }: format, but some facilities
|
||||
# like callPackage expect to be able to query expected arguments.
|
||||
setFunctionArgs = f: args:
|
||||
{ # TODO: Should we add call-time "type" checking like built in?
|
||||
__functor = self: f;
|
||||
__functionArgs = args;
|
||||
};
|
||||
|
||||
# | Extract the expected function arguments from a function.
|
||||
# This works both with nix-native { a, b ? foo, ... }: style
|
||||
# functions and functions with args set with 'setFunctionArgs'. It
|
||||
# has the same return type and semantics as builtins.functionArgs.
|
||||
# setFunctionArgs : (a → b) → Map String Bool.
|
||||
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
|
||||
|
||||
isFunction = f: builtins.isFunction f ||
|
||||
(f ? __functor && isFunction (f.__functor f));
|
||||
}
|
||||
|
@ -256,6 +256,10 @@ rec {
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
nonEmptyListOf = elemType:
|
||||
let list = addCheck (types.listOf elemType) (l: l != []);
|
||||
in list // { description = "non-empty " + list.description; };
|
||||
|
||||
attrsOf = elemType: mkOptionType rec {
|
||||
name = "attrsOf";
|
||||
description = "attribute set of ${elemType.description}s";
|
||||
|
@ -9,8 +9,6 @@ let
|
||||
modules = [ configuration ];
|
||||
};
|
||||
|
||||
inherit (eval) pkgs;
|
||||
|
||||
# This is for `nixos-rebuild build-vm'.
|
||||
vmConfig = (import ./lib/eval-config.nix {
|
||||
inherit system;
|
||||
@ -30,7 +28,7 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
inherit (eval) config options;
|
||||
inherit (eval) pkgs config options;
|
||||
|
||||
system = eval.config.system.build.toplevel;
|
||||
|
||||
|
@ -6,22 +6,52 @@ let
|
||||
lib = pkgs.lib;
|
||||
|
||||
# Remove invisible and internal options.
|
||||
optionsList = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
||||
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
||||
|
||||
# Replace functions by the string <function>
|
||||
substFunction = x:
|
||||
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
|
||||
else if builtins.isList x then map substFunction x
|
||||
else if builtins.isFunction x then "<function>"
|
||||
else if lib.isFunction x then "<function>"
|
||||
else x;
|
||||
|
||||
# Clean up declaration sites to not refer to the NixOS source tree.
|
||||
optionsList' = lib.flip map optionsList (opt: opt // {
|
||||
# Generate DocBook documentation for a list of packages. This is
|
||||
# what `relatedPackages` option of `mkOption` from
|
||||
# ../../../lib/options.nix influences.
|
||||
#
|
||||
# Each element of `relatedPackages` can be either
|
||||
# - a string: that will be interpreted as an attribute name from `pkgs`,
|
||||
# - a list: that will be interpreted as an attribute path from `pkgs`,
|
||||
# - an attrset: that can specify `name`, `path`, `package`, `comment`
|
||||
# (either of `name`, `path` is required, the rest are optional).
|
||||
genRelatedPackages = packages:
|
||||
let
|
||||
unpack = p: if lib.isString p then { name = p; }
|
||||
else if lib.isList p then { path = p; }
|
||||
else p;
|
||||
describe = args:
|
||||
let
|
||||
name = args.name or (lib.concatStringsSep "." args.path);
|
||||
path = args.path or [ args.name ];
|
||||
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
|
||||
in "<listitem>"
|
||||
+ "<para><literal>pkgs.${name} (${package.meta.name})</literal>"
|
||||
+ lib.optionalString (!package.meta.evaluates) " <emphasis>[UNAVAILABLE]</emphasis>"
|
||||
+ ": ${package.meta.description or "???"}.</para>"
|
||||
+ lib.optionalString (args ? comment) "\n<para>${args.comment}</para>"
|
||||
# Lots of `longDescription's break DocBook, so we just wrap them into <programlisting>
|
||||
+ lib.optionalString (package.meta ? longDescription) "\n<programlisting>${package.meta.longDescription}</programlisting>"
|
||||
+ "</listitem>";
|
||||
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
|
||||
|
||||
optionsListDesc = lib.flip map optionsListVisible (opt: opt // {
|
||||
# Clean up declaration sites to not refer to the NixOS source tree.
|
||||
declarations = map stripAnyPrefixes opt.declarations;
|
||||
}
|
||||
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
|
||||
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
|
||||
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; });
|
||||
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
|
||||
// lib.optionalAttrs (opt ? relatedPackages) { relatedPackages = genRelatedPackages opt.relatedPackages; });
|
||||
|
||||
# We need to strip references to /nix/store/* from options,
|
||||
# including any `extraSources` if some modules came from elsewhere,
|
||||
@ -32,8 +62,22 @@ let
|
||||
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
|
||||
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
|
||||
|
||||
# Custom "less" that pushes up all the things ending in ".enable*"
|
||||
# and ".package"
|
||||
optionListLess = a: b:
|
||||
let
|
||||
splt = lib.splitString ".";
|
||||
ise = lib.hasPrefix "enable";
|
||||
isp = lib.hasPrefix "package";
|
||||
cmp = lib.splitByAndCompare ise lib.compare
|
||||
(lib.splitByAndCompare isp lib.compare lib.compare);
|
||||
in lib.compareLists cmp (splt a) (splt b) < 0;
|
||||
|
||||
# Customly sort option list for the man page.
|
||||
optionsList = lib.sort (a: b: optionListLess a.name b.name) optionsListDesc;
|
||||
|
||||
# Convert the list of options into an XML file.
|
||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList');
|
||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
|
||||
|
||||
optionsDocBook = runCommand "options-db.xml" {} ''
|
||||
optionsXML=${optionsXML}
|
||||
@ -191,7 +235,7 @@ in rec {
|
||||
mkdir -p $dst
|
||||
|
||||
cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
|
||||
(builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList'))))
|
||||
(builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList))))
|
||||
} $dst/options.json
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
|
@ -70,9 +70,21 @@ $ ./result/bin/run-*-vm
|
||||
</screen>
|
||||
|
||||
The VM does not have any data from your host system, so your existing
|
||||
user accounts and home directories will not be available. You can
|
||||
forward ports on the host to the guest. For instance, the following
|
||||
will forward host port 2222 to guest port 22 (SSH):
|
||||
user accounts and home directories will not be available unless you
|
||||
have set <literal>mutableUsers = false</literal>. Another way is to
|
||||
temporarily add the following to your configuration:
|
||||
|
||||
<screen>
|
||||
users.extraUsers.your-user.initialPassword = "test"
|
||||
</screen>
|
||||
|
||||
<emphasis>Important:</emphasis> delete the $hostname.qcow2 file if you
|
||||
have started the virtual machine at least once without the right
|
||||
users, otherwise the changes will not get picked up.
|
||||
|
||||
You can forward ports on the host to the guest. For
|
||||
instance, the following will forward host port 2222 to guest port 22
|
||||
(SSH):
|
||||
|
||||
<screen>
|
||||
$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
|
||||
|
@ -70,6 +70,15 @@
|
||||
</para>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="attr[@name = 'relatedPackages']">
|
||||
<para>
|
||||
<emphasis>Related packages:</emphasis>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of disable-output-escaping="yes"
|
||||
select="attr[@name = 'relatedPackages']/string/@value" />
|
||||
</para>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="count(attr[@name = 'declarations']/list/*) != 0">
|
||||
<para>
|
||||
<emphasis>Declared by:</emphasis>
|
||||
|
@ -88,6 +88,28 @@ following incompatible changes:</para>
|
||||
<option>services.pgmanage</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Package attributes starting with a digit have been prefixed with an
|
||||
underscore sign. This is to avoid quoting in the configuration and
|
||||
other issues with command-line tools like <literal>nix-env</literal>.
|
||||
The change affects the following packages:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>2048-in-terminal</literal> → <literal>_2048-in-terminal</literal></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><literal>90secondportraits</literal> → <literal>_90secondportraits</literal></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><literal>2bwm</literal> → <literal>_2bwm</literal></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><literal>389-ds-base</literal> → <literal>_389-ds-base</literal></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis role="strong">
|
||||
@ -149,6 +171,31 @@ following incompatible changes:</para>
|
||||
The <varname>hardware.amdHybridGraphics.disable</varname> option was removed for lack of a maintainer. If you still need this module, you may wish to include a copy of it from an older version of nixos in your imports.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The merging of config options for <varname>services.postfix.config</varname>
|
||||
was buggy. Previously, if other options in the Postfix module like
|
||||
<varname>services.postfix.useSrs</varname> were set and the user set config
|
||||
options that were also set by such options, the resulting config wouldn't
|
||||
include all options that were needed. They are now merged correctly. If
|
||||
config options need to be overridden, <literal>lib.mkForce</literal> or
|
||||
<literal>lib.mkOverride</literal> can be used.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The following changes apply if the <literal>stateVersion</literal> is changed to 18.03 or higher.
|
||||
For <literal>stateVersion = "17.09"</literal> or lower the old behavior is preserved.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>matrix-synapse</literal> uses postgresql by default instead of sqlite.
|
||||
Migration instructions can be found <link xlink:href="https://github.com/matrix-org/synapse/blob/master/docs/postgres.rst#porting-from-sqlite"> here </link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
@ -3,7 +3,7 @@
|
||||
let pkgs = import ../.. { inherit system config; }; in
|
||||
|
||||
with pkgs.lib;
|
||||
with import ../lib/qemu-flags.nix;
|
||||
with import ../lib/qemu-flags.nix { inherit pkgs; };
|
||||
|
||||
rec {
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
# QEMU flags shared between various Nix expressions.
|
||||
{ pkgs }:
|
||||
|
||||
{
|
||||
|
||||
@ -7,4 +8,14 @@
|
||||
"-net vde,vlan=${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
|
||||
];
|
||||
|
||||
qemuSerialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
|
||||
else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
|
||||
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
|
||||
|
||||
qemuBinary = qemuPkg: {
|
||||
"i686-linux" = "${qemuPkg}/bin/qemu-kvm";
|
||||
"x86_64-linux" = "${qemuPkg}/bin/qemu-kvm -cpu kvm64";
|
||||
"armv7l-linux" = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
|
||||
"aarch64-linux" = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
|
||||
}.${pkgs.stdenv.system} or (throw "Unknown QEMU binary for '${pkgs.stdenv.system}'");
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ rec {
|
||||
|
||||
testScript' =
|
||||
# Call the test script with the computed nodes.
|
||||
if builtins.isFunction testScript
|
||||
if lib.isFunction testScript
|
||||
then testScript { inherit nodes; }
|
||||
else testScript;
|
||||
|
||||
|
@ -69,9 +69,6 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# Leftover for old setups, should be set by nixos-generate-config now
|
||||
powerManagement.cpuFreqGovernor = mkDefault "ondemand";
|
||||
|
||||
systemd.targets.post-resume = {
|
||||
description = "Post-Resume Actions";
|
||||
requires = [ "post-resume.service" ];
|
||||
|
@ -43,11 +43,18 @@ in
|
||||
sdImage = {
|
||||
populateBootCommands = let
|
||||
configTxt = pkgs.writeText "config.txt" ''
|
||||
# Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
|
||||
# when attempting to show low-voltage or overtemperature warnings.
|
||||
avoid_warnings=1
|
||||
|
||||
[pi2]
|
||||
kernel=u-boot-rpi2.bin
|
||||
|
||||
[pi3]
|
||||
kernel=u-boot-rpi3.bin
|
||||
|
||||
# U-Boot used to need this to work, regardless of whether UART is actually used or not.
|
||||
# TODO: check when/if this can be removed.
|
||||
enable_uart=1
|
||||
'';
|
||||
in ''
|
||||
|
@ -302,6 +302,8 @@
|
||||
kodi = 283;
|
||||
restya-board = 284;
|
||||
mighttpd2 = 285;
|
||||
hass = 286;
|
||||
monero = 287;
|
||||
|
||||
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
|
||||
|
||||
@ -572,6 +574,8 @@
|
||||
kodi = 283;
|
||||
restya-board = 284;
|
||||
mighttpd2 = 285;
|
||||
hass = 286;
|
||||
monero = 287;
|
||||
|
||||
# When adding a gid, make sure it doesn't match an existing
|
||||
# uid. Users and groups with the same name should have equal
|
||||
|
@ -3,11 +3,13 @@
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.nixpkgs;
|
||||
|
||||
isConfig = x:
|
||||
builtins.isAttrs x || builtins.isFunction x;
|
||||
builtins.isAttrs x || lib.isFunction x;
|
||||
|
||||
optCall = f: x:
|
||||
if builtins.isFunction f
|
||||
if lib.isFunction f
|
||||
then f x
|
||||
else f;
|
||||
|
||||
@ -38,16 +40,55 @@ let
|
||||
overlayType = mkOptionType {
|
||||
name = "nixpkgs-overlay";
|
||||
description = "nixpkgs overlay";
|
||||
check = builtins.isFunction;
|
||||
check = lib.isFunction;
|
||||
merge = lib.mergeOneOption;
|
||||
};
|
||||
|
||||
_pkgs = import ../../.. config.nixpkgs;
|
||||
pkgsType = mkOptionType {
|
||||
name = "nixpkgs";
|
||||
description = "An evaluation of Nixpkgs; the top level attribute set of packages";
|
||||
check = builtins.isAttrs;
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options.nixpkgs = {
|
||||
|
||||
pkgs = mkOption {
|
||||
defaultText = literalExample
|
||||
''import "''${nixos}/.." {
|
||||
inherit (config.nixpkgs) config overlays system;
|
||||
}
|
||||
'';
|
||||
default = import ../../.. { inherit (cfg) config overlays system; };
|
||||
type = pkgsType;
|
||||
example = literalExample ''import <nixpkgs> {}'';
|
||||
description = ''
|
||||
This is the evaluation of Nixpkgs that will be provided to
|
||||
all NixOS modules. Defining this option has the effect of
|
||||
ignoring the other options that would otherwise be used to
|
||||
evaluate Nixpkgs, because those are arguments to the default
|
||||
value. The default value imports the Nixpkgs source files
|
||||
relative to the location of this NixOS module, because
|
||||
NixOS and Nixpkgs are distributed together for consistency,
|
||||
so the <code>nixos</code> in the default value is in fact a
|
||||
relative path. The <code>config</code>, <code>overlays</code>
|
||||
and <code>system</code> come from this option's siblings.
|
||||
|
||||
This option can be used by applications like NixOps to increase
|
||||
the performance of evaluation, or to create packages that depend
|
||||
on a container that should be built with the exact same evaluation
|
||||
of Nixpkgs, for example. Applications like this should set
|
||||
their default value using <code>lib.mkDefault</code>, so
|
||||
user-provided configuration can override it without using
|
||||
<code>lib</code>.
|
||||
|
||||
Note that using a distinct version of Nixpkgs with NixOS may
|
||||
be an unexpected source of problems. Use this option with care.
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
default = {};
|
||||
example = literalExample
|
||||
@ -59,6 +100,8 @@ in
|
||||
The configuration of the Nix Packages collection. (For
|
||||
details, see the Nixpkgs documentation.) It allows you to set
|
||||
package configuration options.
|
||||
|
||||
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -69,7 +112,6 @@ in
|
||||
[ (self: super: {
|
||||
openssh = super.openssh.override {
|
||||
hpnSupport = true;
|
||||
withKerberos = true;
|
||||
kerberos = self.libkrb5;
|
||||
};
|
||||
};
|
||||
@ -83,6 +125,8 @@ in
|
||||
takes as an argument the <emphasis>original</emphasis> Nixpkgs.
|
||||
The first argument should be used for finding dependencies, and
|
||||
the second should be used for overriding recipes.
|
||||
|
||||
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -94,14 +138,16 @@ in
|
||||
If unset, it defaults to the platform type of your host system.
|
||||
Specifying this option is useful when doing distributed
|
||||
multi-platform deployment, or when building virtual machines.
|
||||
|
||||
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
_module.args = {
|
||||
pkgs = _pkgs;
|
||||
pkgs_i686 = _pkgs.pkgsi686Linux;
|
||||
pkgs = cfg.pkgs;
|
||||
pkgs_i686 = cfg.pkgs.pkgsi686Linux;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -84,6 +84,7 @@
|
||||
./programs/info.nix
|
||||
./programs/java.nix
|
||||
./programs/kbdlight.nix
|
||||
./programs/less.nix
|
||||
./programs/light.nix
|
||||
./programs/man.nix
|
||||
./programs/mosh.nix
|
||||
@ -110,6 +111,7 @@
|
||||
./programs/wireshark.nix
|
||||
./programs/xfs_quota.nix
|
||||
./programs/xonsh.nix
|
||||
./programs/yabar.nix
|
||||
./programs/zsh/oh-my-zsh.nix
|
||||
./programs/zsh/zsh.nix
|
||||
./programs/zsh/zsh-syntax-highlighting.nix
|
||||
@ -314,6 +316,7 @@
|
||||
./services/misc/gogs.nix
|
||||
./services/misc/gollum.nix
|
||||
./services/misc/gpsd.nix
|
||||
./services/misc/home-assistant.nix
|
||||
./services/misc/ihaskell.nix
|
||||
./services/misc/irkerd.nix
|
||||
./services/misc/jackett.nix
|
||||
@ -415,7 +418,8 @@
|
||||
./services/network-filesystems/ipfs.nix
|
||||
./services/network-filesystems/netatalk.nix
|
||||
./services/network-filesystems/nfsd.nix
|
||||
./services/network-filesystems/openafs-client/default.nix
|
||||
./services/network-filesystems/openafs/client.nix
|
||||
./services/network-filesystems/openafs/server.nix
|
||||
./services/network-filesystems/rsyncd.nix
|
||||
./services/network-filesystems/samba.nix
|
||||
./services/network-filesystems/tahoe.nix
|
||||
@ -424,6 +428,7 @@
|
||||
./services/network-filesystems/yandex-disk.nix
|
||||
./services/network-filesystems/xtreemfs.nix
|
||||
./services/networking/amuled.nix
|
||||
./services/networking/aria2.nix
|
||||
./services/networking/asterisk.nix
|
||||
./services/networking/atftpd.nix
|
||||
./services/networking/avahi-daemon.nix
|
||||
@ -488,6 +493,7 @@
|
||||
./services/networking/minidlna.nix
|
||||
./services/networking/miniupnpd.nix
|
||||
./services/networking/mosquitto.nix
|
||||
./services/networking/monero.nix
|
||||
./services/networking/miredo.nix
|
||||
./services/networking/mstpd.nix
|
||||
./services/networking/murmur.nix
|
||||
@ -525,6 +531,7 @@
|
||||
./services/networking/redsocks.nix
|
||||
./services/networking/resilio.nix
|
||||
./services/networking/rpcbind.nix
|
||||
./services/networking/rxe.nix
|
||||
./services/networking/sabnzbd.nix
|
||||
./services/networking/searx.nix
|
||||
./services/networking/seeks.nix
|
||||
|
@ -17,7 +17,7 @@ let
|
||||
# you should use files).
|
||||
moduleFiles =
|
||||
# FIXME: use typeOf (Nix 1.6.1).
|
||||
filter (x: !isAttrs x && !builtins.isFunction x) modules;
|
||||
filter (x: !isAttrs x && !lib.isFunction x) modules;
|
||||
|
||||
# Partition module files because between NixOS and non-NixOS files. NixOS
|
||||
# files may change if the repository is updated.
|
||||
|
@ -16,6 +16,7 @@ with lib;
|
||||
To grant access to a user, it must be part of adbusers group:
|
||||
<code>users.extraUsers.alice.extraGroups = ["adbusers"];</code>
|
||||
'';
|
||||
relatedPackages = [ ["androidenv" "platformTools"] ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
118
nixos/modules/programs/less.nix
Normal file
118
nixos/modules/programs/less.nix
Normal file
@ -0,0 +1,118 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.programs.less;
|
||||
|
||||
configFile = ''
|
||||
#command
|
||||
${concatStringsSep "\n"
|
||||
(mapAttrsToList (command: action: "${command} ${action}") cfg.commands)
|
||||
}
|
||||
${if cfg.clearDefaultCommands then "#stop" else ""}
|
||||
|
||||
#line-edit
|
||||
${concatStringsSep "\n"
|
||||
(mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys)
|
||||
}
|
||||
|
||||
#env
|
||||
${concatStringsSep "\n"
|
||||
(mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables)
|
||||
}
|
||||
'';
|
||||
|
||||
lessKey = pkgs.runCommand "lesskey"
|
||||
{ src = pkgs.writeText "lessconfig" configFile; }
|
||||
"${pkgs.less}/bin/lesskey -o $out $src";
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
|
||||
programs.less = {
|
||||
|
||||
enable = mkEnableOption "less";
|
||||
|
||||
commands = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
example = {
|
||||
"h" = "noaction 5\e(";
|
||||
"l" = "noaction 5\e)";
|
||||
};
|
||||
description = "Defines new command keys.";
|
||||
};
|
||||
|
||||
clearDefaultCommands = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Clear all default commands.
|
||||
You should remember to set the quit key.
|
||||
Otherwise you will not be able to leave less without killing it.
|
||||
'';
|
||||
};
|
||||
|
||||
lineEditingKeys = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
example = {
|
||||
"\e" = "abort";
|
||||
};
|
||||
description = "Defines new line-editing keys.";
|
||||
};
|
||||
|
||||
envVariables = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
example = {
|
||||
LESS = "--quit-if-one-screen";
|
||||
};
|
||||
description = "Defines environment variables.";
|
||||
};
|
||||
|
||||
lessopen = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "|${pkgs.lesspipe}/bin/lesspipe.sh %s";
|
||||
description = ''
|
||||
Before less opens a file, it first gives your input preprocessor a chance to modify the way the contents of the file are displayed.
|
||||
'';
|
||||
};
|
||||
|
||||
lessclose = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
When less closes a file opened in such a way, it will call another program, called the input postprocessor, which may perform any desired clean-up action (such as deleting the replacement file created by LESSOPEN).
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.less ];
|
||||
|
||||
environment.variables = {
|
||||
"LESSKEY_SYSTEM" = toString lessKey;
|
||||
} // optionalAttrs (cfg.lessopen != null) {
|
||||
"LESSOPEN" = cfg.lessopen;
|
||||
} // optionalAttrs (cfg.lessclose != null) {
|
||||
"LESSCLOSE" = cfg.lessclose;
|
||||
};
|
||||
|
||||
warnings = optional (
|
||||
cfg.clearDefaultCommands && (all (x: x != "quit") (attrValues cfg.commands))
|
||||
) ''
|
||||
config.programs.less.clearDefaultCommands clears all default commands of less but there is no alternative binding for exiting.
|
||||
Consider adding a binding for 'quit'.
|
||||
'';
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ johnazoidberg ];
|
||||
|
||||
}
|
@ -26,8 +26,9 @@ let
|
||||
# Ensure privacy for newly created home directories.
|
||||
UMASK 077
|
||||
|
||||
# Uncomment this to allow non-root users to change their account
|
||||
#information. This should be made configurable.
|
||||
# Uncomment this and install chfn SUID to allow non-root
|
||||
# users to change their account GECOS information.
|
||||
# This should be made configurable.
|
||||
#CHFN_RESTRICT frwh
|
||||
|
||||
'';
|
||||
@ -103,13 +104,12 @@ in
|
||||
|
||||
security.wrappers = {
|
||||
su.source = "${pkgs.shadow.su}/bin/su";
|
||||
chfn.source = "${pkgs.shadow.out}/bin/chfn";
|
||||
sg.source = "${pkgs.shadow.out}/bin/sg";
|
||||
newgrp.source = "${pkgs.shadow.out}/bin/newgrp";
|
||||
newuidmap.source = "${pkgs.shadow.out}/bin/newuidmap";
|
||||
newgidmap.source = "${pkgs.shadow.out}/bin/newgidmap";
|
||||
} // (if config.users.mutableUsers then {
|
||||
passwd.source = "${pkgs.shadow.out}/bin/passwd";
|
||||
sg.source = "${pkgs.shadow.out}/bin/sg";
|
||||
newgrp.source = "${pkgs.shadow.out}/bin/newgrp";
|
||||
} else {});
|
||||
};
|
||||
}
|
||||
|
@ -61,7 +61,12 @@ in {
|
||||
options = {
|
||||
programs.tmux = {
|
||||
|
||||
enable = mkEnableOption "<command>tmux</command> - a <command>screen</command> replacement.";
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whenever to configure <command>tmux</command> system-wide.";
|
||||
relatedPackages = [ "tmux" ];
|
||||
};
|
||||
|
||||
aggressiveResize = mkOption {
|
||||
default = false;
|
||||
|
149
nixos/modules/programs/yabar.nix
Normal file
149
nixos/modules/programs/yabar.nix
Normal file
@ -0,0 +1,149 @@
|
||||
{ lib, pkgs, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.yabar;
|
||||
|
||||
mapExtra = v: lib.concatStringsSep "\n" (mapAttrsToList (
|
||||
key: val: "${key} = ${if (isString val) then "\"${val}\"" else "${builtins.toString val}"};"
|
||||
) v);
|
||||
|
||||
listKeys = r: concatStringsSep "," (map (n: "\"${n}\"") (attrNames r));
|
||||
|
||||
configFile = let
|
||||
bars = mapAttrsToList (
|
||||
name: cfg: ''
|
||||
${name}: {
|
||||
font: "${cfg.font}";
|
||||
position: "${cfg.position}";
|
||||
|
||||
${mapExtra cfg.extra}
|
||||
|
||||
block-list: [${listKeys cfg.indicators}]
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (
|
||||
name: cfg: ''
|
||||
${name}: {
|
||||
exec: "${cfg.exec}";
|
||||
align: "${cfg.align}";
|
||||
${mapExtra cfg.extra}
|
||||
};
|
||||
''
|
||||
) cfg.indicators)}
|
||||
};
|
||||
''
|
||||
) cfg.bars;
|
||||
in pkgs.writeText "yabar.conf" ''
|
||||
bar-list = [${listKeys cfg.bars}];
|
||||
${concatStringsSep "\n" bars}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.programs.yabar = {
|
||||
enable = mkEnableOption "yabar";
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.yabar;
|
||||
example = literalExample "pkgs.yabar-unstable";
|
||||
type = types.package;
|
||||
|
||||
description = ''
|
||||
The package which contains the `yabar` binary.
|
||||
|
||||
Nixpkgs provides the `yabar` and `yabar-unstable`
|
||||
derivations since 18.03, so it's possible to choose.
|
||||
'';
|
||||
};
|
||||
|
||||
bars = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf(types.submodule {
|
||||
options = {
|
||||
font = mkOption {
|
||||
default = "sans bold 9";
|
||||
example = "Droid Sans, FontAwesome Bold 9";
|
||||
type = types.string;
|
||||
|
||||
description = ''
|
||||
The font that will be used to draw the status bar.
|
||||
'';
|
||||
};
|
||||
|
||||
position = mkOption {
|
||||
default = "top";
|
||||
example = "bottom";
|
||||
type = types.enum [ "top" "bottom" ];
|
||||
|
||||
description = ''
|
||||
The position where the bar will be rendered.
|
||||
'';
|
||||
};
|
||||
|
||||
extra = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf types.string;
|
||||
|
||||
description = ''
|
||||
An attribute set which contains further attributes of a bar.
|
||||
'';
|
||||
};
|
||||
|
||||
indicators = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf(types.submodule {
|
||||
options.exec = mkOption {
|
||||
example = "YABAR_DATE";
|
||||
type = types.string;
|
||||
description = ''
|
||||
The type of the indicator to be executed.
|
||||
'';
|
||||
};
|
||||
|
||||
options.align = mkOption {
|
||||
default = "left";
|
||||
example = "right";
|
||||
type = types.enum [ "left" "center" "right" ];
|
||||
|
||||
description = ''
|
||||
Whether to align the indicator at the left or right of the bar.
|
||||
'';
|
||||
};
|
||||
|
||||
options.extra = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf (types.either types.string types.int);
|
||||
|
||||
description = ''
|
||||
An attribute set which contains further attributes of a indicator.
|
||||
'';
|
||||
};
|
||||
});
|
||||
|
||||
description = ''
|
||||
Indicators that should be rendered by yabar.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
description = ''
|
||||
List of bars that should be rendered by yabar.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.user.services.yabar = {
|
||||
description = "yabar service";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session.target" ];
|
||||
|
||||
script = ''
|
||||
${cfg.package}/bin/yabar -c ${configFile}
|
||||
'';
|
||||
|
||||
serviceConfig.Restart = "always";
|
||||
};
|
||||
};
|
||||
}
|
@ -210,6 +210,7 @@ with lib;
|
||||
"Set the option `services.xserver.displayManager.sddm.package' instead.")
|
||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
|
||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
|
||||
(mkRemovedOptionModule [ "virtualisation" "xen" "qemu" ] "You don't need this option anymore, it will work without it.")
|
||||
|
||||
# ZSH
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
||||
@ -220,5 +221,8 @@ with lib;
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "theme" ] [ "programs" "zsh" "ohMyZsh" "theme" ])
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "custom" ] [ "programs" "zsh" "ohMyZsh" "custom" ])
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "plugins" ] [ "programs" "zsh" "ohMyZsh" "plugins" ])
|
||||
|
||||
# Xen
|
||||
(mkRenamedOptionModule [ "virtualisation" "xen" "qemu-package" ] [ "virtualisation" "xen" "package-qemu" ])
|
||||
];
|
||||
}
|
||||
|
@ -6,10 +6,11 @@ let
|
||||
|
||||
cfg = config.security.acme;
|
||||
|
||||
certOpts = { ... }: {
|
||||
certOpts = { name, ... }: {
|
||||
options = {
|
||||
webroot = mkOption {
|
||||
type = types.str;
|
||||
example = "/var/lib/acme/acme-challenges";
|
||||
description = ''
|
||||
Where the webroot of the HTTP vhost is located.
|
||||
<filename>.well-known/acme-challenge/</filename> directory
|
||||
@ -20,8 +21,8 @@ let
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = "Domain to fetch certificate for (defaults to the entry name)";
|
||||
};
|
||||
|
||||
@ -48,7 +49,7 @@ let
|
||||
default = false;
|
||||
description = ''
|
||||
Give read permissions to the specified group
|
||||
(<option>security.acme.group</option>) to read SSL private certificates.
|
||||
(<option>security.acme.cert.<name>.group</option>) to read SSL private certificates.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -87,7 +88,7 @@ let
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Extra domain names for which certificates are to be issued, with their
|
||||
A list of extra domain names, which are included in the one certificate to be issued, with their
|
||||
own server roots if needed.
|
||||
'';
|
||||
};
|
||||
@ -193,10 +194,9 @@ in
|
||||
servicesLists = mapAttrsToList certToServices cfg.certs;
|
||||
certToServices = cert: data:
|
||||
let
|
||||
domain = if data.domain != null then data.domain else cert;
|
||||
cpath = "${cfg.directory}/${cert}";
|
||||
rights = if data.allowKeysForGroup then "750" else "700";
|
||||
cmdline = [ "-v" "-d" domain "--default_root" data.webroot "--valid_min" cfg.validMin "--tos_sha256" cfg.tosHash ]
|
||||
cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin "--tos_sha256" cfg.tosHash ]
|
||||
++ optionals (data.email != null) [ "--email" data.email ]
|
||||
++ concatMap (p: [ "-f" p ]) data.plugins
|
||||
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
|
||||
|
@ -46,6 +46,18 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
googleAuthenticator = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
If set, users with enabled Google Authenticator (created
|
||||
<filename>~/.google_authenticator</filename>) will be required
|
||||
to provide Google Authenticator token to log in.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
usbAuth = mkOption {
|
||||
default = config.security.pam.usb.enable;
|
||||
type = types.bool;
|
||||
@ -284,7 +296,12 @@ let
|
||||
# prompts the user for password so we run it once with 'required' at an
|
||||
# earlier point and it will run again with 'sufficient' further down.
|
||||
# We use try_first_pass the second time to avoid prompting password twice
|
||||
(optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount || cfg.enableKwallet || cfg.enableGnomeKeyring)) ''
|
||||
(optionalString (cfg.unixAuth &&
|
||||
(config.security.pam.enableEcryptfs
|
||||
|| cfg.pamMount
|
||||
|| cfg.enableKwallet
|
||||
|| cfg.enableGnomeKeyring
|
||||
|| cfg.googleAuthenticator.enable)) ''
|
||||
auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth
|
||||
${optionalString config.security.pam.enableEcryptfs
|
||||
"auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
|
||||
@ -295,6 +312,8 @@ let
|
||||
" kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
|
||||
${optionalString cfg.enableGnomeKeyring
|
||||
("auth optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so")}
|
||||
${optionalString cfg.googleAuthenticator.enable
|
||||
"auth required ${pkgs.googleAuthenticator}/lib/security/pam_google_authenticator.so no_increment_hotp"}
|
||||
'') + ''
|
||||
${optionalString cfg.unixAuth
|
||||
"auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
|
||||
|
@ -289,10 +289,10 @@ in
|
||||
# Create initial databases
|
||||
if ! test -e "${cfg.dataDir}/${database.name}"; then
|
||||
echo "Creating initial database: ${database.name}"
|
||||
( echo "create database ${database.name};"
|
||||
( echo "create database `${database.name}`;"
|
||||
|
||||
${optionalString (database ? "schema") ''
|
||||
echo "use ${database.name};"
|
||||
echo "use `${database.name}`;"
|
||||
|
||||
if [ -f "${database.schema}" ]
|
||||
then
|
||||
|
@ -23,7 +23,7 @@ let kernel = config.boot.kernelPackages; in
|
||||
###### implementation
|
||||
|
||||
config = lib.mkIf config.hardware.nvidiaOptimus.disable {
|
||||
boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb"];
|
||||
boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb" "nvidia-drm"];
|
||||
boot.kernelModules = [ "bbswitch" ];
|
||||
boot.extraModulePackages = [ kernel.bbswitch ];
|
||||
|
||||
|
@ -104,7 +104,7 @@ let
|
||||
};
|
||||
|
||||
mailboxConfig = mailbox: ''
|
||||
mailbox ${mailbox.name} {
|
||||
mailbox "${mailbox.name}" {
|
||||
auto = ${toString mailbox.auto}
|
||||
'' + optionalString (mailbox.specialUse != null) ''
|
||||
special_use = \${toString mailbox.specialUse}
|
||||
@ -113,7 +113,7 @@ let
|
||||
mailboxes = { lib, pkgs, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
type = types.strMatching ''[^"]+'';
|
||||
example = "Spam";
|
||||
description = "The name of the mailbox.";
|
||||
};
|
||||
|
@ -15,20 +15,18 @@ let
|
||||
haveVirtual = cfg.virtual != "";
|
||||
|
||||
clientAccess =
|
||||
if (cfg.dnsBlacklistOverrides != "")
|
||||
then [ "check_client_access hash:/etc/postfix/client_access" ]
|
||||
else [];
|
||||
optional (cfg.dnsBlacklistOverrides != "")
|
||||
"check_client_access hash:/etc/postfix/client_access";
|
||||
|
||||
dnsBl =
|
||||
if (cfg.dnsBlacklists != [])
|
||||
then [ (concatStringsSep ", " (map (s: "reject_rbl_client " + s) cfg.dnsBlacklists)) ]
|
||||
else [];
|
||||
optionals (cfg.dnsBlacklists != [])
|
||||
(map (s: "reject_rbl_client " + s) cfg.dnsBlacklists);
|
||||
|
||||
clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
|
||||
|
||||
mainCf = let
|
||||
escape = replaceStrings ["$"] ["$$"];
|
||||
mkList = items: "\n " + concatStringsSep "\n " items;
|
||||
mkList = items: "\n " + concatStringsSep ",\n " items;
|
||||
mkVal = value:
|
||||
if isList value then mkList value
|
||||
else " " + (if value == true then "yes"
|
||||
@ -36,72 +34,9 @@ let
|
||||
else toString value);
|
||||
mkEntry = name: value: "${escape name} =${mkVal value}";
|
||||
in
|
||||
concatStringsSep "\n" (mapAttrsToList mkEntry (recursiveUpdate defaultConf cfg.config))
|
||||
concatStringsSep "\n" (mapAttrsToList mkEntry cfg.config)
|
||||
+ "\n" + cfg.extraConfig;
|
||||
|
||||
defaultConf = {
|
||||
compatibility_level = "9999";
|
||||
mail_owner = user;
|
||||
default_privs = "nobody";
|
||||
|
||||
# NixOS specific locations
|
||||
data_directory = "/var/lib/postfix/data";
|
||||
queue_directory = "/var/lib/postfix/queue";
|
||||
|
||||
# Default location of everything in package
|
||||
meta_directory = "${pkgs.postfix}/etc/postfix";
|
||||
command_directory = "${pkgs.postfix}/bin";
|
||||
sample_directory = "/etc/postfix";
|
||||
newaliases_path = "${pkgs.postfix}/bin/newaliases";
|
||||
mailq_path = "${pkgs.postfix}/bin/mailq";
|
||||
readme_directory = false;
|
||||
sendmail_path = "${pkgs.postfix}/bin/sendmail";
|
||||
daemon_directory = "${pkgs.postfix}/libexec/postfix";
|
||||
manpage_directory = "${pkgs.postfix}/share/man";
|
||||
html_directory = "${pkgs.postfix}/share/postfix/doc/html";
|
||||
shlib_directory = false;
|
||||
relayhost = if cfg.relayHost == "" then "" else
|
||||
if cfg.lookupMX
|
||||
then "${cfg.relayHost}:${toString cfg.relayPort}"
|
||||
else "[${cfg.relayHost}]:${toString cfg.relayPort}";
|
||||
|
||||
mail_spool_directory = "/var/spool/mail/";
|
||||
setgid_group = setgidGroup;
|
||||
}
|
||||
// optionalAttrs config.networking.enableIPv6 { inet_protocols = "all"; }
|
||||
// optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
|
||||
// optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
|
||||
// optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
|
||||
// optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
|
||||
// optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
|
||||
// optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
|
||||
// optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
|
||||
// optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
|
||||
// optionalAttrs haveAliases { alias_maps = "${cfg.aliasMapType}:/etc/postfix/aliases"; }
|
||||
// optionalAttrs haveTransport { transport_maps = "hash:/etc/postfix/transport"; }
|
||||
// optionalAttrs haveVirtual { virtual_alias_maps = "${cfg.virtualMapType}:/etc/postfix/virtual"; }
|
||||
// optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
|
||||
// optionalAttrs cfg.useSrs {
|
||||
sender_canonical_maps = "tcp:127.0.0.1:10001";
|
||||
sender_canonical_classes = "envelope_sender";
|
||||
recipient_canonical_maps = "tcp:127.0.0.1:10002";
|
||||
recipient_canonical_classes= "envelope_recipient";
|
||||
}
|
||||
// optionalAttrs cfg.enableHeaderChecks { header_checks = "regexp:/etc/postfix/header_checks"; }
|
||||
// optionalAttrs (cfg.sslCert != "") {
|
||||
smtp_tls_CAfile = cfg.sslCACert;
|
||||
smtp_tls_cert_file = cfg.sslCert;
|
||||
smtp_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtp_use_tls = true;
|
||||
|
||||
smtpd_tls_CAfile = cfg.sslCACert;
|
||||
smtpd_tls_cert_file = cfg.sslCert;
|
||||
smtpd_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtpd_use_tls = true;
|
||||
};
|
||||
|
||||
masterCfOptions = { options, config, name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
@ -507,7 +442,6 @@ in
|
||||
|
||||
config = mkOption {
|
||||
type = with types; attrsOf (either bool (either str (listOf str)));
|
||||
default = defaultConf;
|
||||
description = ''
|
||||
The main.cf configuration file as key value set.
|
||||
'';
|
||||
@ -749,6 +683,67 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
services.postfix.config = (mapAttrs (_: v: mkDefault v) {
|
||||
compatibility_level = "9999";
|
||||
mail_owner = cfg.user;
|
||||
default_privs = "nobody";
|
||||
|
||||
# NixOS specific locations
|
||||
data_directory = "/var/lib/postfix/data";
|
||||
queue_directory = "/var/lib/postfix/queue";
|
||||
|
||||
# Default location of everything in package
|
||||
meta_directory = "${pkgs.postfix}/etc/postfix";
|
||||
command_directory = "${pkgs.postfix}/bin";
|
||||
sample_directory = "/etc/postfix";
|
||||
newaliases_path = "${pkgs.postfix}/bin/newaliases";
|
||||
mailq_path = "${pkgs.postfix}/bin/mailq";
|
||||
readme_directory = false;
|
||||
sendmail_path = "${pkgs.postfix}/bin/sendmail";
|
||||
daemon_directory = "${pkgs.postfix}/libexec/postfix";
|
||||
manpage_directory = "${pkgs.postfix}/share/man";
|
||||
html_directory = "${pkgs.postfix}/share/postfix/doc/html";
|
||||
shlib_directory = false;
|
||||
mail_spool_directory = "/var/spool/mail/";
|
||||
setgid_group = cfg.setgidGroup;
|
||||
})
|
||||
// optionalAttrs (cfg.relayHost != "") { relayhost = if cfg.lookupMX
|
||||
then "${cfg.relayHost}:${toString cfg.relayPort}"
|
||||
else "[${cfg.relayHost}]:${toString cfg.relayPort}"; }
|
||||
// optionalAttrs config.networking.enableIPv6 { inet_protocols = mkDefault "all"; }
|
||||
// optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
|
||||
// optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
|
||||
// optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
|
||||
// optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
|
||||
// optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
|
||||
// optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
|
||||
// optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
|
||||
// optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
|
||||
// optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
|
||||
// optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
|
||||
// optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
|
||||
// optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
|
||||
// optionalAttrs cfg.useSrs {
|
||||
sender_canonical_maps = [ "tcp:127.0.0.1:10001" ];
|
||||
sender_canonical_classes = [ "envelope_sender" ];
|
||||
recipient_canonical_maps = [ "tcp:127.0.0.1:10002" ];
|
||||
recipient_canonical_classes = [ "envelope_recipient" ];
|
||||
}
|
||||
// optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
|
||||
// optionalAttrs (cfg.sslCert != "") {
|
||||
smtp_tls_CAfile = cfg.sslCACert;
|
||||
smtp_tls_cert_file = cfg.sslCert;
|
||||
smtp_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtp_use_tls = true;
|
||||
|
||||
smtpd_tls_CAfile = cfg.sslCACert;
|
||||
smtpd_tls_cert_file = cfg.sslCert;
|
||||
smtpd_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtpd_use_tls = true;
|
||||
};
|
||||
|
||||
services.postfix.masterConfig = {
|
||||
smtp_inet = {
|
||||
name = "smtp";
|
||||
|
@ -1,14 +1,152 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, options, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.rspamd;
|
||||
opts = options.services.rspamd;
|
||||
|
||||
mkBindSockets = socks: concatStringsSep "\n" (map (each: " bind_socket = \"${each}\"") socks);
|
||||
bindSocketOpts = {options, config, ... }: {
|
||||
options = {
|
||||
socket = mkOption {
|
||||
type = types.str;
|
||||
example = "localhost:11333";
|
||||
description = ''
|
||||
Socket for this worker to listen on in a format acceptable by rspamd.
|
||||
'';
|
||||
};
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
default = "0644";
|
||||
description = "Mode to set on unix socket";
|
||||
};
|
||||
owner = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.user}";
|
||||
description = "Owner to set on unix socket";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.group}";
|
||||
description = "Group to set on unix socket";
|
||||
};
|
||||
rawEntry = mkOption {
|
||||
type = types.str;
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
config.rawEntry = let
|
||||
maybeOption = option:
|
||||
optionalString options.${option}.isDefined " ${option}=${config.${option}}";
|
||||
in
|
||||
if (!(hasPrefix "/" config.socket)) then "${config.socket}"
|
||||
else "${config.socket}${maybeOption "mode"}${maybeOption "owner"}${maybeOption "group"}";
|
||||
};
|
||||
|
||||
rspamdConfFile = pkgs.writeText "rspamd.conf"
|
||||
workerOpts = { name, ... }: {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = "Whether to run the rspamd worker.";
|
||||
};
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = name;
|
||||
description = "Name of the worker";
|
||||
};
|
||||
type = mkOption {
|
||||
type = types.nullOr (types.enum [
|
||||
"normal" "controller" "fuzzy_storage" "proxy" "lua"
|
||||
]);
|
||||
description = "The type of this worker";
|
||||
};
|
||||
bindSockets = mkOption {
|
||||
type = types.listOf (types.either types.str (types.submodule bindSocketOpts));
|
||||
default = [];
|
||||
description = ''
|
||||
List of sockets to listen, in format acceptable by rspamd
|
||||
'';
|
||||
example = [{
|
||||
socket = "/run/rspamd.sock";
|
||||
mode = "0666";
|
||||
owner = "rspamd";
|
||||
} "*:11333"];
|
||||
apply = value: map (each: if (isString each)
|
||||
then if (isUnixSocket each)
|
||||
then {socket = each; owner = cfg.user; group = cfg.group; mode = "0644"; rawEntry = "${each}";}
|
||||
else {socket = each; rawEntry = "${each}";}
|
||||
else each) value;
|
||||
};
|
||||
count = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
description = ''
|
||||
Number of worker instances to run
|
||||
'';
|
||||
};
|
||||
includes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
List of files to include in configuration
|
||||
'';
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = "Additional entries to put verbatim into worker section of rspamd config file.";
|
||||
};
|
||||
};
|
||||
config = mkIf (name == "normal" || name == "controller" || name == "fuzzy") {
|
||||
type = mkDefault name;
|
||||
includes = mkDefault [ "$CONFDIR/worker-${name}.inc" ];
|
||||
bindSockets = mkDefault (if name == "normal"
|
||||
then [{
|
||||
socket = "/run/rspamd/rspamd.sock";
|
||||
mode = "0660";
|
||||
owner = cfg.user;
|
||||
group = cfg.group;
|
||||
}]
|
||||
else if name == "controller"
|
||||
then [ "localhost:11334" ]
|
||||
else [] );
|
||||
};
|
||||
};
|
||||
|
||||
indexOf = default: start: list: e:
|
||||
if list == []
|
||||
then default
|
||||
else if (head list) == e then start
|
||||
else (indexOf default (start + (length (listenStreams (head list).socket))) (tail list) e);
|
||||
|
||||
systemdSocket = indexOf (abort "Socket not found") 0 allSockets;
|
||||
|
||||
isUnixSocket = socket: hasPrefix "/" (if (isString socket) then socket else socket.socket);
|
||||
isPort = hasPrefix "*:";
|
||||
isIPv4Socket = hasPrefix "*v4:";
|
||||
isIPv6Socket = hasPrefix "*v6:";
|
||||
isLocalHost = hasPrefix "localhost:";
|
||||
listenStreams = socket:
|
||||
if (isLocalHost socket) then
|
||||
let port = (removePrefix "localhost:" socket);
|
||||
in [ "127.0.0.1:${port}" ] ++ (if config.networking.enableIPv6 then ["[::1]:${port}"] else [])
|
||||
else if (isIPv6Socket socket) then [removePrefix "*v6:" socket]
|
||||
else if (isPort socket) then [removePrefix "*:" socket]
|
||||
else if (isIPv4Socket socket) then
|
||||
throw "error: IPv4 only socket not supported in rspamd with socket activation"
|
||||
else if (length (splitString " " socket)) != 1 then
|
||||
throw "error: string options not supported in rspamd with socket activation"
|
||||
else [socket];
|
||||
|
||||
mkBindSockets = enabled: socks: concatStringsSep "\n " (flatten (map (each:
|
||||
if cfg.socketActivation && enabled != false then
|
||||
let systemd = (systemdSocket each);
|
||||
in (imap (idx: e: "bind_socket = \"systemd:${toString (systemd + idx - 1)}\";") (listenStreams each.socket))
|
||||
else "bind_socket = \"${each.rawEntry}\";") socks));
|
||||
|
||||
rspamdConfFile = pkgs.writeText "rspamd.conf"
|
||||
''
|
||||
.include "$CONFDIR/common.conf"
|
||||
|
||||
@ -22,19 +160,33 @@ let
|
||||
.include "$CONFDIR/logging.inc"
|
||||
}
|
||||
|
||||
worker {
|
||||
${mkBindSockets cfg.bindSocket}
|
||||
.include "$CONFDIR/worker-normal.inc"
|
||||
}
|
||||
|
||||
worker {
|
||||
${mkBindSockets cfg.bindUISocket}
|
||||
.include "$CONFDIR/worker-controller.inc"
|
||||
}
|
||||
${concatStringsSep "\n" (mapAttrsToList (name: value: ''
|
||||
worker ${optionalString (value.name != "normal" && value.name != "controller") "${value.name}"} {
|
||||
type = "${value.type}";
|
||||
${optionalString (value.enable != null)
|
||||
"enabled = ${if value.enable != false then "yes" else "no"};"}
|
||||
${mkBindSockets value.enable value.bindSockets}
|
||||
${optionalString (value.count != null) "count = ${toString value.count};"}
|
||||
${concatStringsSep "\n " (map (each: ".include \"${each}\"") value.includes)}
|
||||
${value.extraConfig}
|
||||
}
|
||||
'') cfg.workers)}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
allMappedSockets = flatten (mapAttrsToList (name: value:
|
||||
if value.enable != false
|
||||
then imap (idx: each: {
|
||||
name = "${name}";
|
||||
index = idx;
|
||||
value = each;
|
||||
}) value.bindSockets
|
||||
else []) cfg.workers);
|
||||
allSockets = map (e: e.value) allMappedSockets;
|
||||
|
||||
allSocketNames = map (each: "rspamd-${each.name}-${toString each.index}.socket") allMappedSockets;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
@ -48,36 +200,43 @@ in
|
||||
enable = mkEnableOption "Whether to run the rspamd daemon.";
|
||||
|
||||
debug = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to run the rspamd daemon in debug mode.";
|
||||
};
|
||||
|
||||
bindSocket = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}"
|
||||
];
|
||||
defaultText = ''[
|
||||
"/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}"
|
||||
]'';
|
||||
socketActivation = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
List of sockets to listen, in format acceptable by rspamd
|
||||
'';
|
||||
example = ''
|
||||
bindSocket = [
|
||||
"/run/rspamd.sock mode=0666 owner=rspamd"
|
||||
"*:11333"
|
||||
];
|
||||
Enable systemd socket activation for rspamd.
|
||||
'';
|
||||
};
|
||||
|
||||
bindUISocket = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [
|
||||
"localhost:11334"
|
||||
];
|
||||
workers = mkOption {
|
||||
type = with types; attrsOf (submodule workerOpts);
|
||||
description = ''
|
||||
List of sockets for web interface, in format acceptable by rspamd
|
||||
Attribute set of workers to start.
|
||||
'';
|
||||
default = {
|
||||
normal = {};
|
||||
controller = {};
|
||||
};
|
||||
example = literalExample ''
|
||||
{
|
||||
normal = {
|
||||
includes = [ "$CONFDIR/worker-normal.inc" ];
|
||||
bindSockets = [{
|
||||
socket = "/run/rspamd/rspamd.sock";
|
||||
mode = "0660";
|
||||
owner = "${cfg.user}";
|
||||
group = "${cfg.group}";
|
||||
}];
|
||||
};
|
||||
controller = {
|
||||
includes = [ "$CONFDIR/worker-controller.inc" ];
|
||||
bindSockets = [ "[::1]:11334" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
@ -113,6 +272,13 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
services.rspamd.socketActivation = mkDefault (!opts.bindSocket.isDefined && !opts.bindUISocket.isDefined);
|
||||
|
||||
assertions = [ {
|
||||
assertion = !cfg.socketActivation || !(opts.bindSocket.isDefined || opts.bindUISocket.isDefined);
|
||||
message = "Can't use socketActivation for rspamd when using renamed bind socket options";
|
||||
} ];
|
||||
|
||||
# Allow users to run 'rspamc' and 'rspamadm'.
|
||||
environment.systemPackages = [ pkgs.rspamd ];
|
||||
|
||||
@ -128,17 +294,22 @@ in
|
||||
gid = config.ids.gids.rspamd;
|
||||
};
|
||||
|
||||
environment.etc."rspamd.conf".source = rspamdConfFile;
|
||||
|
||||
systemd.services.rspamd = {
|
||||
description = "Rspamd Service";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = mkIf (!cfg.socketActivation) [ "multi-user.target" ];
|
||||
after = [ "network.target" ] ++
|
||||
(if cfg.socketActivation then allSocketNames else []);
|
||||
requires = mkIf cfg.socketActivation allSocketNames;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
|
||||
Restart = "always";
|
||||
RuntimeDirectory = "rspamd";
|
||||
PrivateTmp = true;
|
||||
Sockets = mkIf cfg.socketActivation (concatStringsSep " " allSocketNames);
|
||||
};
|
||||
|
||||
preStart = ''
|
||||
@ -146,5 +317,25 @@ in
|
||||
${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /var/lib/rspamd
|
||||
'';
|
||||
};
|
||||
systemd.sockets = mkIf cfg.socketActivation
|
||||
(listToAttrs (map (each: {
|
||||
name = "rspamd-${each.name}-${toString each.index}";
|
||||
value = {
|
||||
description = "Rspamd socket ${toString each.index} for worker ${each.name}";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
listenStreams = (listenStreams each.value.socket);
|
||||
socketConfig = {
|
||||
BindIPv6Only = mkIf (isIPv6Socket each.value.socket) "ipv6-only";
|
||||
Service = "rspamd.service";
|
||||
SocketUser = mkIf (isUnixSocket each.value.socket) each.value.owner;
|
||||
SocketGroup = mkIf (isUnixSocket each.value.socket) each.value.group;
|
||||
SocketMode = mkIf (isUnixSocket each.value.socket) each.value.mode;
|
||||
};
|
||||
};
|
||||
}) allMappedSockets));
|
||||
};
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "rspamd" "bindSocket" ] [ "services" "rspamd" "workers" "normal" "bindSockets" ])
|
||||
(mkRenamedOptionModule [ "services" "rspamd" "bindUISocket" ] [ "services" "rspamd" "workers" "controller" "bindSockets" ])
|
||||
];
|
||||
}
|
||||
|
135
nixos/modules/services/misc/home-assistant.nix
Normal file
135
nixos/modules/services/misc/home-assistant.nix
Normal file
@ -0,0 +1,135 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.home-assistant;
|
||||
|
||||
configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config);
|
||||
|
||||
availableComponents = pkgs.home-assistant.availableComponents;
|
||||
|
||||
# Given component "parentConfig.platform", returns whether config.parentConfig
|
||||
# is a list containing a set with set.platform == "platform".
|
||||
#
|
||||
# For example, the component sensor.luftdaten is used as follows:
|
||||
# config.sensor = [ {
|
||||
# platform = "luftdaten";
|
||||
# ...
|
||||
# } ];
|
||||
useComponentPlatform = component:
|
||||
let
|
||||
path = splitString "." component;
|
||||
parentConfig = attrByPath (init path) null cfg.config;
|
||||
platform = last path;
|
||||
in isList parentConfig && any
|
||||
(item: item.platform or null == platform)
|
||||
parentConfig;
|
||||
|
||||
# Returns whether component is used in config
|
||||
useComponent = component:
|
||||
hasAttrByPath (splitString "." component) cfg.config
|
||||
|| useComponentPlatform component;
|
||||
|
||||
# List of components used in config
|
||||
extraComponents = filter useComponent availableComponents;
|
||||
|
||||
package = if cfg.autoExtraComponents
|
||||
then (cfg.package.override { inherit extraComponents; })
|
||||
else cfg.package;
|
||||
|
||||
in {
|
||||
meta.maintainers = with maintainers; [ dotlambda ];
|
||||
|
||||
options.services.home-assistant = {
|
||||
enable = mkEnableOption "Home Assistant";
|
||||
|
||||
configDir = mkOption {
|
||||
default = "/var/lib/hass";
|
||||
type = types.path;
|
||||
description = "The config directory, where your <filename>configuration.yaml</filename> is located.";
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr attrs;
|
||||
example = literalExample ''
|
||||
{
|
||||
homeassistant = {
|
||||
name = "Home";
|
||||
time_zone = "UTC";
|
||||
};
|
||||
frontend = { };
|
||||
http = { };
|
||||
feedreader.urls = [ "https://nixos.org/blogs.xml" ];
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Your <filename>configuration.yaml</filename> as a Nix attribute set.
|
||||
Beware that setting this option will delete your previous <filename>configuration.yaml</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.home-assistant;
|
||||
defaultText = "pkgs.home-assistant";
|
||||
type = types.package;
|
||||
example = literalExample ''
|
||||
pkgs.home-assistant.override {
|
||||
extraPackages = ps: with ps; [ colorlog ];
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Home Assistant package to use.
|
||||
Override <literal>extraPackages</literal> in order to add additional dependencies.
|
||||
'';
|
||||
};
|
||||
|
||||
autoExtraComponents = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
If set to <literal>true</literal>, the components used in <literal>config</literal>
|
||||
are set as the specified package's <literal>extraComponents</literal>.
|
||||
This in turn adds all packaged dependencies to the derivation.
|
||||
You might still see import errors in your log.
|
||||
In this case, you will need to package the necessary dependencies yourself
|
||||
or ask for someone else to package them.
|
||||
If a dependency is packaged but not automatically added to this list,
|
||||
you might need to specify it in <literal>extraPackages</literal>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.home-assistant = {
|
||||
description = "Home Assistant";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
preStart = lib.optionalString (cfg.config != null) ''
|
||||
rm -f ${cfg.configDir}/configuration.yaml
|
||||
ln -s ${configFile} ${cfg.configDir}/configuration.yaml
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${package}/bin/hass --config "${cfg.configDir}"
|
||||
'';
|
||||
User = "hass";
|
||||
Group = "hass";
|
||||
Restart = "on-failure";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = "${cfg.configDir}";
|
||||
PrivateTmp = true;
|
||||
};
|
||||
};
|
||||
|
||||
users.extraUsers.hass = {
|
||||
home = cfg.configDir;
|
||||
createHome = true;
|
||||
group = "hass";
|
||||
uid = config.ids.uids.hass;
|
||||
};
|
||||
|
||||
users.extraGroups.hass.gid = config.ids.gids.hass;
|
||||
};
|
||||
}
|
@ -4,6 +4,8 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.matrix-synapse;
|
||||
pg = config.services.postgresql;
|
||||
usePostgresql = cfg.database_type == "psycopg2";
|
||||
logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
|
||||
mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
|
||||
mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
|
||||
@ -38,7 +40,7 @@ database: {
|
||||
name: "${cfg.database_type}",
|
||||
args: {
|
||||
${concatStringsSep ",\n " (
|
||||
mapAttrsToList (n: v: "\"${n}\": ${v}") cfg.database_args
|
||||
mapAttrsToList (n: v: "\"${n}\": ${builtins.toJSON v}") cfg.database_args
|
||||
)}
|
||||
}
|
||||
}
|
||||
@ -155,7 +157,7 @@ in {
|
||||
tls_certificate_path = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/lib/matrix-synapse/homeserver.tls.crt";
|
||||
example = "${cfg.dataDir}/homeserver.tls.crt";
|
||||
description = ''
|
||||
PEM encoded X509 certificate for TLS.
|
||||
You can replace the self-signed certificate that synapse
|
||||
@ -167,7 +169,7 @@ in {
|
||||
tls_private_key_path = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/lib/matrix-synapse/homeserver.tls.key";
|
||||
example = "${cfg.dataDir}/homeserver.tls.key";
|
||||
description = ''
|
||||
PEM encoded private key for TLS. Specify null if synapse is not
|
||||
speaking TLS directly.
|
||||
@ -176,7 +178,7 @@ in {
|
||||
tls_dh_params_path = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/lib/matrix-synapse/homeserver.tls.dh";
|
||||
example = "${cfg.dataDir}/homeserver.tls.dh";
|
||||
description = ''
|
||||
PEM dh parameters for ephemeral keys
|
||||
'';
|
||||
@ -184,6 +186,7 @@ in {
|
||||
server_name = mkOption {
|
||||
type = types.str;
|
||||
example = "example.com";
|
||||
default = config.networking.hostName;
|
||||
description = ''
|
||||
The domain name of the server, with optional explicit port.
|
||||
This is used by remote servers to connect to this server,
|
||||
@ -339,16 +342,39 @@ in {
|
||||
};
|
||||
database_type = mkOption {
|
||||
type = types.enum [ "sqlite3" "psycopg2" ];
|
||||
default = "sqlite3";
|
||||
default = if versionAtLeast config.system.stateVersion "18.03"
|
||||
then "psycopg2"
|
||||
else "sqlite3";
|
||||
description = ''
|
||||
The database engine name. Can be sqlite or psycopg2.
|
||||
'';
|
||||
};
|
||||
create_local_database = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to create a local database automatically.
|
||||
'';
|
||||
};
|
||||
database_name = mkOption {
|
||||
type = types.str;
|
||||
default = "matrix-synapse";
|
||||
description = "Database name.";
|
||||
};
|
||||
database_user = mkOption {
|
||||
type = types.str;
|
||||
default = "matrix-synapse";
|
||||
description = "Database user name.";
|
||||
};
|
||||
database_args = mkOption {
|
||||
type = types.attrs;
|
||||
default = {
|
||||
database = "${cfg.dataDir}/homeserver.db";
|
||||
};
|
||||
sqlite3 = { database = "${cfg.dataDir}/homeserver.db"; };
|
||||
psycopg2 = {
|
||||
user = cfg.database_user;
|
||||
database = cfg.database_name;
|
||||
};
|
||||
}."${cfg.database_type}";
|
||||
description = ''
|
||||
Arguments to pass to the engine.
|
||||
'';
|
||||
@ -623,15 +649,36 @@ in {
|
||||
gid = config.ids.gids.matrix-synapse;
|
||||
} ];
|
||||
|
||||
services.postgresql.enable = mkIf usePostgresql (mkDefault true);
|
||||
|
||||
systemd.services.matrix-synapse = {
|
||||
description = "Synapse Matrix homeserver";
|
||||
after = [ "network.target" ];
|
||||
after = [ "network.target" "postgresql.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
preStart = ''
|
||||
${cfg.package}/bin/homeserver \
|
||||
--config-path ${configFile} \
|
||||
--keys-directory ${cfg.dataDir} \
|
||||
--generate-keys
|
||||
'' + optionalString (usePostgresql && cfg.create_local_database) ''
|
||||
if ! test -e "${cfg.dataDir}/db-created"; then
|
||||
${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
|
||||
${pg.package}/bin/createuser \
|
||||
--login \
|
||||
--no-createdb \
|
||||
--no-createrole \
|
||||
--encrypted \
|
||||
${cfg.database_user}
|
||||
${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
|
||||
${pg.package}/bin/createdb \
|
||||
--owner=${cfg.database_user} \
|
||||
--encoding=UTF8 \
|
||||
--lc-collate=C \
|
||||
--lc-ctype=C \
|
||||
--template=template0 \
|
||||
${cfg.database_name}
|
||||
touch "${cfg.dataDir}/db-created"
|
||||
fi
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
|
@ -8,7 +8,7 @@ let
|
||||
|
||||
nix = cfg.package.out;
|
||||
|
||||
isNix112 = versionAtLeast (getVersion nix) "1.12pre";
|
||||
isNix20 = versionAtLeast (getVersion nix) "2.0pre";
|
||||
|
||||
makeNixBuildUser = nr:
|
||||
{ name = "nixbld${toString nr}";
|
||||
@ -26,32 +26,40 @@ let
|
||||
|
||||
nixConf =
|
||||
let
|
||||
# If we're using sandbox for builds, then provide /bin/sh in
|
||||
# the sandbox as a bind-mount to bash. This means we also need to
|
||||
# include the entire closure of bash.
|
||||
# In Nix < 2.0, If we're using sandbox for builds, then provide
|
||||
# /bin/sh in the sandbox as a bind-mount to bash. This means we
|
||||
# also need to include the entire closure of bash. Nix >= 2.0
|
||||
# provides a /bin/sh by default.
|
||||
sh = pkgs.stdenv.shell;
|
||||
binshDeps = pkgs.writeReferencesToFile sh;
|
||||
in
|
||||
pkgs.runCommand "nix.conf" {extraOptions = cfg.extraOptions; } ''
|
||||
extraPaths=$(for i in $(cat ${binshDeps}); do if test -d $i; then echo $i; fi; done)
|
||||
pkgs.runCommand "nix.conf" { extraOptions = cfg.extraOptions; inherit binshDeps; } ''
|
||||
${optionalString (!isNix20) ''
|
||||
extraPaths=$(for i in $(cat binshDeps); do if test -d $i; then echo $i; fi; done)
|
||||
''}
|
||||
cat > $out <<END
|
||||
# WARNING: this file is generated from the nix.* options in
|
||||
# your NixOS configuration, typically
|
||||
# /etc/nixos/configuration.nix. Do not edit it!
|
||||
build-users-group = nixbld
|
||||
build-max-jobs = ${toString (cfg.maxJobs)}
|
||||
build-cores = ${toString (cfg.buildCores)}
|
||||
build-use-sandbox = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
|
||||
build-sandbox-paths = ${toString cfg.sandboxPaths} /bin/sh=${sh} $(echo $extraPaths)
|
||||
binary-caches = ${toString cfg.binaryCaches}
|
||||
trusted-binary-caches = ${toString cfg.trustedBinaryCaches}
|
||||
binary-cache-public-keys = ${toString cfg.binaryCachePublicKeys}
|
||||
${if isNix20 then "max-jobs" else "build-max-jobs"} = ${toString (cfg.maxJobs)}
|
||||
${if isNix20 then "cores" else "build-cores"} = ${toString (cfg.buildCores)}
|
||||
${if isNix20 then "sandbox" else "build-use-sandbox"} = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
|
||||
${if isNix20 then "extra-sandbox-paths" else "build-sandbox-paths"} = ${toString cfg.sandboxPaths} ${optionalString (!isNix20) "/bin/sh=${sh} $(echo $extraPaths)"}
|
||||
${if isNix20 then "substituters" else "binary-caches"} = ${toString cfg.binaryCaches}
|
||||
${if isNix20 then "trusted-substituters" else "trusted-binary-caches"} = ${toString cfg.trustedBinaryCaches}
|
||||
${if isNix20 then "trusted-public-keys" else "binary-cache-public-keys"} = ${toString cfg.binaryCachePublicKeys}
|
||||
auto-optimise-store = ${boolToString cfg.autoOptimiseStore}
|
||||
${optionalString cfg.requireSignedBinaryCaches ''
|
||||
signed-binary-caches = *
|
||||
${if isNix20 then ''
|
||||
require-sigs = ${if cfg.requireSignedBinaryCaches then "true" else "false"}
|
||||
'' else ''
|
||||
signed-binary-caches = ${if cfg.requireSignedBinaryCaches then "*" else ""}
|
||||
''}
|
||||
trusted-users = ${toString cfg.trustedUsers}
|
||||
allowed-users = ${toString cfg.allowedUsers}
|
||||
${optionalString (isNix20 && !cfg.distributedBuilds) ''
|
||||
builders =
|
||||
''}
|
||||
$extraOptions
|
||||
END
|
||||
'';
|
||||
@ -377,8 +385,9 @@ in
|
||||
systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];
|
||||
|
||||
systemd.services.nix-daemon =
|
||||
{ path = [ nix pkgs.openssl.bin pkgs.utillinux config.programs.ssh.package ]
|
||||
++ optionals cfg.distributedBuilds [ pkgs.gzip ];
|
||||
{ path = [ nix pkgs.utillinux ]
|
||||
++ optionals cfg.distributedBuilds [ config.programs.ssh.package pkgs.gzip ]
|
||||
++ optionals (!isNix20) [ pkgs.openssl.bin ];
|
||||
|
||||
environment = cfg.envVars
|
||||
// { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; }
|
||||
@ -396,10 +405,9 @@ in
|
||||
};
|
||||
|
||||
nix.envVars =
|
||||
{ NIX_CONF_DIR = "/etc/nix";
|
||||
}
|
||||
optionalAttrs (!isNix20) {
|
||||
NIX_CONF_DIR = "/etc/nix";
|
||||
|
||||
// optionalAttrs (!isNix112) {
|
||||
# Enable the copy-from-other-stores substituter, which allows
|
||||
# builds to be sped up by copying build results from remote
|
||||
# Nix stores. To do this, mount the remote file system on a
|
||||
@ -407,12 +415,8 @@ in
|
||||
NIX_OTHER_STORES = "/run/nix/remote-stores/*/nix";
|
||||
}
|
||||
|
||||
// optionalAttrs cfg.distributedBuilds {
|
||||
NIX_BUILD_HOOK =
|
||||
if isNix112 then
|
||||
"${nix}/libexec/nix/build-remote"
|
||||
else
|
||||
"${nix}/libexec/nix/build-remote.pl";
|
||||
// optionalAttrs (cfg.distributedBuilds && !isNix20) {
|
||||
NIX_BUILD_HOOK = "${nix}/libexec/nix/build-remote.pl";
|
||||
};
|
||||
|
||||
# Set up the environment variables for running Nix.
|
||||
@ -420,7 +424,7 @@ in
|
||||
{ NIX_PATH = concatStringsSep ":" cfg.nixPath;
|
||||
};
|
||||
|
||||
environment.extraInit =
|
||||
environment.extraInit = optionalString (!isNix20)
|
||||
''
|
||||
# Set up secure multi-user builds: non-root users build through the
|
||||
# Nix daemon.
|
||||
|
@ -106,10 +106,19 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
description = "The zookeeper package to use";
|
||||
default = pkgs.zookeeper;
|
||||
defaultText = "pkgs.zookeeper";
|
||||
type = types.package;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
systemd.services.zookeeper = {
|
||||
description = "Zookeeper Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@ -118,7 +127,7 @@ in {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.jre}/bin/java \
|
||||
-cp "${pkgs.zookeeper}/lib/*:${pkgs.zookeeper}/${pkgs.zookeeper.name}.jar:${configDir}" \
|
||||
-cp "${cfg.package}/lib/*:${cfg.package}/${cfg.package.name}.jar:${configDir}" \
|
||||
${escapeShellArgs cfg.extraCmdLineOptions} \
|
||||
-Dzookeeper.datadir.autocreate=false \
|
||||
${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
|
||||
|
@ -1,99 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption mkIf;
|
||||
|
||||
cfg = config.services.openafsClient;
|
||||
|
||||
cellServDB = pkgs.fetchurl {
|
||||
url = http://dl.central.org/dl/cellservdb/CellServDB.2017-03-14;
|
||||
sha256 = "1197z6c5xrijgf66rhaymnm5cvyg2yiy1i20y4ah4mrzmjx0m7sc";
|
||||
};
|
||||
|
||||
afsConfig = pkgs.runCommand "afsconfig" {} ''
|
||||
mkdir -p $out
|
||||
echo ${cfg.cellName} > $out/ThisCell
|
||||
cp ${cellServDB} $out/CellServDB
|
||||
echo "/afs:${cfg.cacheDirectory}:${cfg.cacheSize}" > $out/cacheinfo
|
||||
'';
|
||||
|
||||
openafsPkgs = config.boot.kernelPackages.openafsClient;
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.openafsClient = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable the OpenAFS client.";
|
||||
};
|
||||
|
||||
cellName = mkOption {
|
||||
default = "grand.central.org";
|
||||
description = "Cell name.";
|
||||
};
|
||||
|
||||
cacheSize = mkOption {
|
||||
default = "100000";
|
||||
description = "Cache size.";
|
||||
};
|
||||
|
||||
cacheDirectory = mkOption {
|
||||
default = "/var/cache/openafs";
|
||||
description = "Cache directory.";
|
||||
};
|
||||
|
||||
crypt = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable (weak) protocol encryption.";
|
||||
};
|
||||
|
||||
sparse = mkOption {
|
||||
default = false;
|
||||
description = "Minimal cell list in /afs.";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ openafsPkgs ];
|
||||
|
||||
environment.etc = [
|
||||
{ source = afsConfig;
|
||||
target = "openafs";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.afsd = {
|
||||
description = "AFS client";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = { RemainAfterExit = true; };
|
||||
|
||||
preStart = ''
|
||||
mkdir -p -m 0755 /afs
|
||||
mkdir -m 0700 -p ${cfg.cacheDirectory}
|
||||
${pkgs.kmod}/bin/insmod ${openafsPkgs}/lib/openafs/libafs-*.ko || true
|
||||
${openafsPkgs}/sbin/afsd -confdir ${afsConfig} -cachedir ${cfg.cacheDirectory} ${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} -fakestat -afsdb
|
||||
${openafsPkgs}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
|
||||
'';
|
||||
|
||||
# Doing this in preStop, because after these commands AFS is basically
|
||||
# stopped, so systemd has nothing to do, just noticing it. If done in
|
||||
# postStop, then we get a hang + kernel oops, because AFS can't be
|
||||
# stopped simply by sending signals to processes.
|
||||
preStop = ''
|
||||
${pkgs.utillinux}/bin/umount /afs
|
||||
${openafsPkgs}/sbin/afsd -shutdown
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
239
nixos/modules/services/network-filesystems/openafs/client.nix
Normal file
239
nixos/modules/services/network-filesystems/openafs/client.nix
Normal file
@ -0,0 +1,239 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with import ./lib.nix { inherit lib; };
|
||||
|
||||
let
|
||||
inherit (lib) getBin mkOption mkIf optionalString singleton types;
|
||||
|
||||
cfg = config.services.openafsClient;
|
||||
|
||||
cellServDB = pkgs.fetchurl {
|
||||
url = http://dl.central.org/dl/cellservdb/CellServDB.2017-03-14;
|
||||
sha256 = "1197z6c5xrijgf66rhaymnm5cvyg2yiy1i20y4ah4mrzmjx0m7sc";
|
||||
};
|
||||
|
||||
clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.cellServDB);
|
||||
|
||||
afsConfig = pkgs.runCommand "afsconfig" {} ''
|
||||
mkdir -p $out
|
||||
echo ${cfg.cellName} > $out/ThisCell
|
||||
cat ${cellServDB} ${clientServDB} > $out/CellServDB
|
||||
echo "${cfg.mountPoint}:${cfg.cache.directory}:${toString cfg.cache.blocks}" > $out/cacheinfo
|
||||
'';
|
||||
|
||||
openafsMod = config.boot.kernelPackages.openafs;
|
||||
openafsBin = lib.getBin pkgs.openafs;
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.openafsClient = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "Whether to enable the OpenAFS client.";
|
||||
};
|
||||
|
||||
afsdb = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = "Resolve cells via AFSDB DNS records.";
|
||||
};
|
||||
|
||||
cellName = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Cell name.";
|
||||
example = "grand.central.org";
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [];
|
||||
type = with types; listOf (submodule { options = cellServDBConfig; });
|
||||
description = ''
|
||||
This cell's database server records, added to the global
|
||||
CellServDB. See CellServDB(5) man page for syntax. Ignored when
|
||||
<literal>afsdb</literal> is set to <literal>true</literal>.
|
||||
'';
|
||||
example = ''
|
||||
[ { ip = "1.2.3.4"; dnsname = "first.afsdb.server.dns.fqdn.org"; }
|
||||
{ ip = "2.3.4.5"; dnsname = "second.afsdb.server.dns.fqdn.org"; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
cache = {
|
||||
blocks = mkOption {
|
||||
default = 100000;
|
||||
type = types.int;
|
||||
description = "Cache size in 1KB blocks.";
|
||||
};
|
||||
|
||||
chunksize = mkOption {
|
||||
default = 0;
|
||||
type = types.ints.between 0 30;
|
||||
description = ''
|
||||
Size of each cache chunk given in powers of
|
||||
2. <literal>0</literal> resets the chunk size to its default
|
||||
values (13 (8 KB) for memcache, 18-20 (256 KB to 1 MB) for
|
||||
diskcache). Maximum value is 30. Important performance
|
||||
parameter. Set to higher values when dealing with large files.
|
||||
'';
|
||||
};
|
||||
|
||||
directory = mkOption {
|
||||
default = "/var/cache/openafs";
|
||||
type = types.str;
|
||||
description = "Cache directory.";
|
||||
};
|
||||
|
||||
diskless = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Use in-memory cache for diskless machines. Has no real
|
||||
performance benefit anymore.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
crypt = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = "Whether to enable (weak) protocol encryption.";
|
||||
};
|
||||
|
||||
daemons = mkOption {
|
||||
default = 2;
|
||||
type = types.int;
|
||||
description = ''
|
||||
Number of daemons to serve user requests. Numbers higher than 6
|
||||
usually do no increase performance. Default is sufficient for up
|
||||
to five concurrent users.
|
||||
'';
|
||||
};
|
||||
|
||||
fakestat = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Return fake data on stat() calls. If <literal>true</literal>,
|
||||
always do so. If <literal>false</literal>, only do so for
|
||||
cross-cell mounts (as these are potentially expensive).
|
||||
'';
|
||||
};
|
||||
|
||||
inumcalc = mkOption {
|
||||
default = "compat";
|
||||
type = types.strMatching "compat|md5";
|
||||
description = ''
|
||||
Inode calculation method. <literal>compat</literal> is
|
||||
computationally less expensive, but <literal>md5</literal> greatly
|
||||
reduces the likelihood of inode collisions in larger scenarios
|
||||
involving multiple cells mounted into one AFS space.
|
||||
'';
|
||||
};
|
||||
|
||||
mountPoint = mkOption {
|
||||
default = "/afs";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Mountpoint of the AFS file tree, conventionally
|
||||
<literal>/afs</literal>. When set to a different value, only
|
||||
cross-cells that use the same value can be accessed.
|
||||
'';
|
||||
};
|
||||
|
||||
sparse = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = "Minimal cell list in /afs.";
|
||||
};
|
||||
|
||||
startDisconnected = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Start up in disconnected mode. You need to execute
|
||||
<literal>fs disco online</literal> (as root) to switch to
|
||||
connected mode. Useful for roaming devices.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{ assertion = cfg.afsdb || cfg.cellServDB != [];
|
||||
message = "You should specify all cell-local database servers in config.services.openafsClient.cellServDB or set config.services.openafsClient.afsdb.";
|
||||
}
|
||||
{ assertion = cfg.cellName != "";
|
||||
message = "You must specify the local cell name in config.services.openafsClient.cellName.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.openafs ];
|
||||
|
||||
environment.etc = {
|
||||
clientCellServDB = {
|
||||
source = pkgs.runCommand "CellServDB" {} ''
|
||||
cat ${cellServDB} ${clientServDB} > $out
|
||||
'';
|
||||
target = "openafs/CellServDB";
|
||||
mode = "0644";
|
||||
};
|
||||
clientCell = {
|
||||
text = ''
|
||||
${cfg.cellName}
|
||||
'';
|
||||
target = "openafs/ThisCell";
|
||||
mode = "0644";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.afsd = {
|
||||
description = "AFS client";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = singleton (if cfg.startDisconnected then "network.target" else "network-online.target");
|
||||
serviceConfig = { RemainAfterExit = true; };
|
||||
restartIfChanged = false;
|
||||
|
||||
preStart = ''
|
||||
mkdir -p -m 0755 ${cfg.mountPoint}
|
||||
mkdir -m 0700 -p ${cfg.cache.directory}
|
||||
${pkgs.kmod}/bin/insmod ${openafsMod}/lib/modules/*/extra/openafs/libafs.ko.xz
|
||||
${openafsBin}/sbin/afsd \
|
||||
-mountdir ${cfg.mountPoint} \
|
||||
-confdir ${afsConfig} \
|
||||
${optionalString (!cfg.cache.diskless) "-cachedir ${cfg.cache.directory}"} \
|
||||
-blocks ${toString cfg.cache.blocks} \
|
||||
-chunksize ${toString cfg.cache.chunksize} \
|
||||
${optionalString cfg.cache.diskless "-memcache"} \
|
||||
-inumcalc ${cfg.inumcalc} \
|
||||
${if cfg.fakestat then "-fakestat-all" else "-fakestat"} \
|
||||
${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} \
|
||||
${optionalString cfg.afsdb "-afsdb"}
|
||||
${openafsBin}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
|
||||
${optionalString cfg.startDisconnected "${openafsBin}/bin/fs discon offline"}
|
||||
'';
|
||||
|
||||
# Doing this in preStop, because after these commands AFS is basically
|
||||
# stopped, so systemd has nothing to do, just noticing it. If done in
|
||||
# postStop, then we get a hang + kernel oops, because AFS can't be
|
||||
# stopped simply by sending signals to processes.
|
||||
preStop = ''
|
||||
${pkgs.utillinux}/bin/umount ${cfg.mountPoint}
|
||||
${openafsBin}/sbin/afsd -shutdown
|
||||
${pkgs.kmod}/sbin/rmmod libafs
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
28
nixos/modules/services/network-filesystems/openafs/lib.nix
Normal file
28
nixos/modules/services/network-filesystems/openafs/lib.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ lib, ...}:
|
||||
|
||||
let
|
||||
inherit (lib) concatStringsSep mkOption types;
|
||||
|
||||
in rec {
|
||||
|
||||
mkCellServDB = cellName: db: ''
|
||||
>${cellName}
|
||||
'' + (concatStringsSep "\n" (map (dbm: if (dbm.ip != "" && dbm.dnsname != "") then dbm.ip + " #" + dbm.dnsname else "")
|
||||
db));
|
||||
|
||||
# CellServDB configuration type
|
||||
cellServDBConfig = {
|
||||
ip = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "1.2.3.4";
|
||||
description = "IP Address of a database server";
|
||||
};
|
||||
dnsname = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "afs.example.org";
|
||||
description = "DNS full-qualified domain name of a database server";
|
||||
};
|
||||
};
|
||||
}
|
260
nixos/modules/services/network-filesystems/openafs/server.nix
Normal file
260
nixos/modules/services/network-filesystems/openafs/server.nix
Normal file
@ -0,0 +1,260 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with import ./lib.nix { inherit lib; };
|
||||
|
||||
let
|
||||
inherit (lib) concatStringsSep intersperse mapAttrsToList mkForce mkIf mkMerge mkOption optionalString types;
|
||||
|
||||
bosConfig = pkgs.writeText "BosConfig" (''
|
||||
restrictmode 1
|
||||
restarttime 16 0 0 0 0
|
||||
checkbintime 3 0 5 0 0
|
||||
'' + (optionalString cfg.roles.database.enable ''
|
||||
bnode simple vlserver 1
|
||||
parm ${openafsBin}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs}
|
||||
end
|
||||
bnode simple ptserver 1
|
||||
parm ${openafsBin}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs}
|
||||
end
|
||||
'') + (optionalString cfg.roles.fileserver.enable ''
|
||||
bnode dafs dafs 1
|
||||
parm ${openafsBin}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs}
|
||||
parm ${openafsBin}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs}
|
||||
parm ${openafsBin}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs}
|
||||
parm ${openafsBin}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs}
|
||||
end
|
||||
'') + (optionalString (cfg.roles.database.enable && cfg.roles.backup.enable) ''
|
||||
bnode simple buserver 1
|
||||
parm ${openafsBin}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString (cfg.roles.backup.cellServDB != []) "-cellservdb /etc/openafs/backup/"}
|
||||
end
|
||||
''));
|
||||
|
||||
netInfo = if (cfg.advertisedAddresses != []) then
|
||||
pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n")
|
||||
else null;
|
||||
|
||||
buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.roles.backup.cellServDB);
|
||||
|
||||
cfg = config.services.openafsServer;
|
||||
|
||||
udpSizeStr = toString cfg.udpPacketSize;
|
||||
|
||||
openafsBin = lib.getBin pkgs.openafs;
|
||||
|
||||
in {
|
||||
|
||||
options = {
|
||||
|
||||
services.openafsServer = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Whether to enable the OpenAFS server. An OpenAFS server needs a
|
||||
complex setup. So, be aware that enabling this service and setting
|
||||
some options does not give you a turn-key-ready solution. You need
|
||||
at least a running Kerberos 5 setup, as OpenAFS relies on it for
|
||||
authentication. See the Guide "QuickStartUnix" coming with
|
||||
<literal>pkgs.openafs.doc</literal> for complete setup
|
||||
instructions.
|
||||
'';
|
||||
};
|
||||
|
||||
advertisedAddresses = mkOption {
|
||||
default = [];
|
||||
description = "List of IP addresses this server is advertised under. See NetInfo(5)";
|
||||
};
|
||||
|
||||
cellName = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Cell name, this server will serve.";
|
||||
example = "grand.central.org";
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [];
|
||||
type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
|
||||
description = "Definition of all cell-local database server machines.";
|
||||
};
|
||||
|
||||
roles = {
|
||||
fileserver = {
|
||||
enable = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = "Fileserver role, serves files and volumes from its local storage.";
|
||||
};
|
||||
|
||||
fileserverArgs = mkOption {
|
||||
default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000";
|
||||
type = types.str;
|
||||
description = "Arguments to the dafileserver process. See its man page.";
|
||||
};
|
||||
|
||||
volserverArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the davolserver process. See its man page.";
|
||||
example = "-sync never";
|
||||
};
|
||||
|
||||
salvageserverArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the salvageserver process. See its man page.";
|
||||
example = "-showlog";
|
||||
};
|
||||
|
||||
salvagerArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the dasalvager process. See its man page.";
|
||||
example = "-showlog -showmounts";
|
||||
};
|
||||
};
|
||||
|
||||
database = {
|
||||
enable = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Database server role, maintains the Volume Location Database,
|
||||
Protection Database (and Backup Database, see
|
||||
<literal>backup</literal> role). There can be multiple
|
||||
servers in the database role for replication, which then need
|
||||
reliable network connection to each other.
|
||||
|
||||
Servers in this role appear in AFSDB DNS records or the
|
||||
CellServDB.
|
||||
'';
|
||||
};
|
||||
|
||||
vlserverArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the vlserver process. See its man page.";
|
||||
example = "-rxbind";
|
||||
};
|
||||
|
||||
ptserverArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the ptserver process. See its man page.";
|
||||
example = "-restricted -default_access S---- S-M---";
|
||||
};
|
||||
};
|
||||
|
||||
backup = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Backup server role. Use in conjunction with the
|
||||
<literal>database</literal> role to maintain the Backup
|
||||
Database. Normally only used in conjunction with tape storage
|
||||
or IBM's Tivoli Storage Manager.
|
||||
'';
|
||||
};
|
||||
|
||||
buserverArgs = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = "Arguments to the buserver process. See its man page.";
|
||||
example = "-p 8";
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [];
|
||||
type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
|
||||
description = ''
|
||||
Definition of all cell-local backup database server machines.
|
||||
Use this when your cell uses less backup database servers than
|
||||
other database server machines.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dottedPrincipals= mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
If enabled, allow principal names containing (.) dots. Enabling
|
||||
this has security implications!
|
||||
'';
|
||||
};
|
||||
|
||||
udpPacketSize = mkOption {
|
||||
default = 1310720;
|
||||
type = types.int;
|
||||
description = ''
|
||||
UDP packet size to use in Bytes. Higher values can speed up
|
||||
communications. The default of 1 MB is a sufficient in most
|
||||
cases. Make sure to increase the kernel's UDP buffer size
|
||||
accordingly via <literal>net.core(w|r|opt)mem_max</literal>
|
||||
sysctl.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{ assertion = cfg.cellServDB != [];
|
||||
message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB.";
|
||||
}
|
||||
{ assertion = cfg.cellName != "";
|
||||
message = "You must specify the local cell name in config.services.openafsServer.cellName.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.openafs ];
|
||||
|
||||
environment.etc = {
|
||||
bosConfig = {
|
||||
source = bosConfig;
|
||||
target = "openafs/BosConfig";
|
||||
mode = "0644";
|
||||
};
|
||||
cellServDB = {
|
||||
text = mkCellServDB cfg.cellName cfg.cellServDB;
|
||||
target = "openafs/server/CellServDB";
|
||||
mode = "0644";
|
||||
};
|
||||
thisCell = {
|
||||
text = cfg.cellName;
|
||||
target = "openafs/server/ThisCell";
|
||||
mode = "0644";
|
||||
};
|
||||
buCellServDB = {
|
||||
enable = (cfg.roles.backup.cellServDB != []);
|
||||
text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB;
|
||||
target = "openafs/backup/CellServDB";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
openafs-server = {
|
||||
description = "OpenAFS server";
|
||||
after = [ "syslog.target" "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartIfChanged = false;
|
||||
unitConfig.ConditionPathExists = [ "/etc/openafs/server/rxkad.keytab" ];
|
||||
preStart = ''
|
||||
mkdir -m 0755 -p /var/openafs
|
||||
${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"}
|
||||
${optionalString (cfg.roles.backup.cellServDB != []) "cp ${buCellServDB}"}
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = "${openafsBin}/bin/bosserver -nofork";
|
||||
ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -54,10 +54,12 @@ let
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${samba}/sbin/${appName} ${args}";
|
||||
ExecStart = "${samba}/sbin/${appName} --foreground --no-process-group ${args}";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
LimitNOFILE = 16384;
|
||||
PIDFile = "/run/${appName}.pid";
|
||||
Type = "notify";
|
||||
NotifyAccess = "all"; #may not do anything...
|
||||
};
|
||||
|
||||
restartTriggers = [ configFile ];
|
||||
@ -231,11 +233,12 @@ in
|
||||
after = [ "samba-setup.service" "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# Refer to https://github.com/samba-team/samba/tree/master/packaging/systemd
|
||||
# for correct use with systemd
|
||||
services = {
|
||||
"samba-smbd" = daemonService "smbd" "-F";
|
||||
"samba-nmbd" = mkIf cfg.enableNmbd (daemonService "nmbd" "-F");
|
||||
"samba-winbindd" = mkIf cfg.enableWinbindd (daemonService "winbindd" "-F");
|
||||
"samba-smbd" = daemonService "smbd" "";
|
||||
"samba-nmbd" = mkIf cfg.enableNmbd (daemonService "nmbd" "");
|
||||
"samba-winbindd" = mkIf cfg.enableWinbindd (daemonService "winbindd" "");
|
||||
"samba-setup" = {
|
||||
description = "Samba Setup Task";
|
||||
script = setupScript;
|
||||
|
@ -10,9 +10,9 @@ let
|
||||
settingsDir = "${homeDir}";
|
||||
sessionFile = "${homeDir}/aria2.session";
|
||||
downloadDir = "${homeDir}/Downloads";
|
||||
|
||||
|
||||
rangesToStringList = map (x: builtins.toString x.from +"-"+ builtins.toString x.to);
|
||||
|
||||
|
||||
settingsFile = pkgs.writeText "aria2.conf"
|
||||
''
|
||||
dir=${cfg.downloadDir}
|
||||
@ -110,12 +110,12 @@ in
|
||||
mkdir -m 0770 -p "${homeDir}"
|
||||
chown aria2:aria2 "${homeDir}"
|
||||
if [[ ! -d "${config.services.aria2.downloadDir}" ]]
|
||||
then
|
||||
then
|
||||
mkdir -m 0770 -p "${config.services.aria2.downloadDir}"
|
||||
chown aria2:aria2 "${config.services.aria2.downloadDir}"
|
||||
fi
|
||||
if [[ ! -e "${sessionFile}" ]]
|
||||
then
|
||||
then
|
||||
touch "${sessionFile}"
|
||||
chown aria2:aria2 "${sessionFile}"
|
||||
fi
|
||||
@ -132,4 +132,4 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ in
|
||||
type = with types; listOf str;
|
||||
default = [ "::1" "127.0.0.1" ];
|
||||
description = ''
|
||||
What addresses the server should listen on.
|
||||
What addresses the server should listen on. (UDP+TCP 53)
|
||||
'';
|
||||
};
|
||||
# TODO: perhaps options for more common stuff like cache size or forwarding
|
||||
@ -99,9 +99,9 @@ in
|
||||
Restart = "on-failure";
|
||||
};
|
||||
|
||||
# Trust anchor goes from dns-root-data by default.
|
||||
script = ''
|
||||
exec '${package}/bin/kresd' --config '${configFile}' \
|
||||
-k '${pkgs.dns-root-data}/root.key'
|
||||
exec '${package}/bin/kresd' --config '${configFile}' --forks=1
|
||||
'';
|
||||
|
||||
requires = [ "kresd.socket" ];
|
||||
|
238
nixos/modules/services/networking/monero.nix
Normal file
238
nixos/modules/services/networking/monero.nix
Normal file
@ -0,0 +1,238 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.monero;
|
||||
dataDir = "/var/lib/monero";
|
||||
|
||||
listToConf = option: list:
|
||||
concatMapStrings (value: "${option}=${value}\n") list;
|
||||
|
||||
login = (cfg.rpc.user != null && cfg.rpc.password != null);
|
||||
|
||||
configFile = with cfg; pkgs.writeText "monero.conf" ''
|
||||
log-file=/dev/stdout
|
||||
data-dir=${dataDir}
|
||||
|
||||
${optionalString mining.enable ''
|
||||
start-mining=${mining.address}
|
||||
mining-threads=${toString mining.threads}
|
||||
''}
|
||||
|
||||
rpc-bind-ip=${rpc.address}
|
||||
rpc-bind-port=${toString rpc.port}
|
||||
${optionalString login ''
|
||||
rpc-login=${rpc.user}:${rpc.password}
|
||||
''}
|
||||
${optionalString rpc.restricted ''
|
||||
restrict-rpc=1
|
||||
''}
|
||||
|
||||
limit-rate-up=${toString limits.upload}
|
||||
limit-rate-down=${toString limits.download}
|
||||
max-concurrency=${toString limits.threads}
|
||||
block-sync-size=${toString limits.syncSize}
|
||||
|
||||
${listToConf "add-peer" extraNodes}
|
||||
${listToConf "add-priority-node" priorityNodes}
|
||||
${listToConf "add-exclusive-node" exclusiveNodes}
|
||||
|
||||
${extraConfig}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.monero = {
|
||||
|
||||
enable = mkEnableOption "Monero node daemon.";
|
||||
|
||||
mining.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to mine moneroj.
|
||||
'';
|
||||
};
|
||||
|
||||
mining.address = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Monero address where to send mining rewards.
|
||||
'';
|
||||
};
|
||||
|
||||
mining.threads = mkOption {
|
||||
type = types.addCheck types.int (x: x>=0);
|
||||
default = 0;
|
||||
description = ''
|
||||
Number of threads used for mining.
|
||||
Set to <literal>0</literal> to use all available.
|
||||
'';
|
||||
};
|
||||
|
||||
rpc.user = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
User name for RPC connections.
|
||||
'';
|
||||
};
|
||||
|
||||
rpc.password = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Password for RPC connections.
|
||||
'';
|
||||
};
|
||||
|
||||
rpc.address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = ''
|
||||
IP address the RPC server will bind to.
|
||||
'';
|
||||
};
|
||||
|
||||
rpc.port = mkOption {
|
||||
type = types.int;
|
||||
default = 18081;
|
||||
description = ''
|
||||
Port the RPC server will bind to.
|
||||
'';
|
||||
};
|
||||
|
||||
rpc.restricted = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to restrict RPC to view only commands.
|
||||
'';
|
||||
};
|
||||
|
||||
limits.upload = mkOption {
|
||||
type = types.addCheck types.int (x: x>=-1);
|
||||
default = -1;
|
||||
description = ''
|
||||
Limit of the upload rate in kB/s.
|
||||
Set to <literal>-1</literal> to leave unlimited.
|
||||
'';
|
||||
};
|
||||
|
||||
limits.download = mkOption {
|
||||
type = types.addCheck types.int (x: x>=-1);
|
||||
default = -1;
|
||||
description = ''
|
||||
Limit of the download rate in kB/s.
|
||||
Set to <literal>-1</literal> to leave unlimited.
|
||||
'';
|
||||
};
|
||||
|
||||
limits.threads = mkOption {
|
||||
type = types.addCheck types.int (x: x>=0);
|
||||
default = 0;
|
||||
description = ''
|
||||
Maximum number of threads used for a parallel job.
|
||||
Set to <literal>0</literal> to leave unlimited.
|
||||
'';
|
||||
};
|
||||
|
||||
limits.syncSize = mkOption {
|
||||
type = types.addCheck types.int (x: x>=0);
|
||||
default = 0;
|
||||
description = ''
|
||||
Maximum number of blocks to sync at once.
|
||||
Set to <literal>0</literal> for adaptive.
|
||||
'';
|
||||
};
|
||||
|
||||
extraNodes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of additional peer IP addresses to add to the local list.
|
||||
'';
|
||||
};
|
||||
|
||||
priorityNodes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of peer IP addresses to connect to and
|
||||
attempt to keep the connection open.
|
||||
'';
|
||||
};
|
||||
|
||||
exclusiveNodes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of peer IP addresses to connect to *only*.
|
||||
If given the other peer options will be ignored.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines to be added verbatim to monerod configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
users.extraUsers = singleton {
|
||||
name = "monero";
|
||||
uid = config.ids.uids.monero;
|
||||
description = "Monero daemon user";
|
||||
home = dataDir;
|
||||
createHome = true;
|
||||
};
|
||||
|
||||
users.extraGroups = singleton {
|
||||
name = "monero";
|
||||
gid = config.ids.gids.monero;
|
||||
};
|
||||
|
||||
systemd.services.monero = {
|
||||
description = "monero daemon";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = "monero";
|
||||
Group = "monero";
|
||||
ExecStart = "${pkgs.monero}/bin/monerod --config-file=${configFile} --non-interactive";
|
||||
Restart = "always";
|
||||
SuccessExitStatus = [ 0 1 ];
|
||||
};
|
||||
};
|
||||
|
||||
assertions = singleton {
|
||||
assertion = cfg.mining.enable -> cfg.mining.address != "";
|
||||
message = ''
|
||||
You need a Monero address to receive mining rewards:
|
||||
specify one using option monero.mining.address.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ in
|
||||
'' + concatStringsSep "\n" (
|
||||
mapAttrsToList (n: c:
|
||||
if c.hashedPassword != null then
|
||||
"echo '${n}:${c.hashedPassword}' > ${cfg.dataDir}/passwd"
|
||||
"echo '${n}:${c.hashedPassword}' >> ${cfg.dataDir}/passwd"
|
||||
else optionalString (c.password != null)
|
||||
"${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}"
|
||||
) cfg.users);
|
||||
|
63
nixos/modules/services/networking/rxe.nix
Normal file
63
nixos/modules/services/networking/rxe.nix
Normal file
@ -0,0 +1,63 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking.rxe;
|
||||
|
||||
runRxeCmd = cmd: ifcs:
|
||||
concatStrings ( map (x: "${pkgs.rdma-core}/bin/rxe_cfg -n ${cmd} ${x};") ifcs);
|
||||
|
||||
startScript = pkgs.writeShellScriptBin "rxe-start" ''
|
||||
${pkgs.rdma-core}/bin/rxe_cfg -n start
|
||||
${runRxeCmd "add" cfg.interfaces}
|
||||
${pkgs.rdma-core}/bin/rxe_cfg
|
||||
'';
|
||||
|
||||
stopScript = pkgs.writeShellScriptBin "rxe-stop" ''
|
||||
${runRxeCmd "remove" cfg.interfaces }
|
||||
${pkgs.rdma-core}/bin/rxe_cfg -n stop
|
||||
'';
|
||||
|
||||
in {
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
networking.rxe = {
|
||||
enable = mkEnableOption "RDMA over converged ethernet";
|
||||
interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "eth0" ];
|
||||
description = ''
|
||||
Enable RDMA on the listed interfaces. The corresponding virtual
|
||||
RDMA interfaces will be named rxe0 ... rxeN where the ordering
|
||||
will be as they are named in the list. UDP port 4791 must be
|
||||
open on the respective ethernet interfaces.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
systemd.services.rxe = {
|
||||
path = with pkgs; [ kmod rdma-core ];
|
||||
description = "RoCE interfaces";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "systemd-modules-load.service" "network-online.target" ];
|
||||
wants = [ "network-pre.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = "${startScript}/bin/rxe-start";
|
||||
ExecStop = "${stopScript}/bin/rxe-stop";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -375,9 +375,6 @@ in
|
||||
# LogLevel VERBOSE logs user's key fingerprint on login.
|
||||
# Needed to have a clear audit track of which key was used to log in.
|
||||
LogLevel VERBOSE
|
||||
|
||||
# Use kernel sandbox mechanisms where possible in unprivileged processes.
|
||||
UsePrivilegeSeparation sandbox
|
||||
'';
|
||||
|
||||
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
|
||||
|
@ -30,6 +30,20 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
allowAnyUser = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to allow any user to lock the screen. This will install a
|
||||
setuid wrapper to allow any user to start physlock as root, which
|
||||
is a minor security risk. Call the physlock binary to use this instead
|
||||
of using the systemd service.
|
||||
|
||||
Note that you might need to relog to have the correct binary in your
|
||||
PATH upon changing this option.
|
||||
'';
|
||||
};
|
||||
|
||||
disableSysRq = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
@ -79,28 +93,36 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
|
||||
# for physlock -l and physlock -L
|
||||
environment.systemPackages = [ pkgs.physlock ];
|
||||
# for physlock -l and physlock -L
|
||||
environment.systemPackages = [ pkgs.physlock ];
|
||||
|
||||
systemd.services."physlock" = {
|
||||
enable = true;
|
||||
description = "Physlock";
|
||||
wantedBy = optional cfg.lockOn.suspend "suspend.target"
|
||||
++ optional cfg.lockOn.hibernate "hibernate.target"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
before = optional cfg.lockOn.suspend "systemd-suspend.service"
|
||||
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
serviceConfig.Type = "forking";
|
||||
script = ''
|
||||
${pkgs.physlock}/bin/physlock -d${optionalString cfg.disableSysRq "s"}
|
||||
'';
|
||||
};
|
||||
systemd.services."physlock" = {
|
||||
enable = true;
|
||||
description = "Physlock";
|
||||
wantedBy = optional cfg.lockOn.suspend "suspend.target"
|
||||
++ optional cfg.lockOn.hibernate "hibernate.target"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
before = optional cfg.lockOn.suspend "systemd-suspend.service"
|
||||
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${pkgs.physlock}/bin/physlock -d${optionalString cfg.disableSysRq "s"}";
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.services.physlock = {};
|
||||
security.pam.services.physlock = {};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
(mkIf cfg.allowAnyUser {
|
||||
|
||||
security.wrappers.physlock = { source = "${pkgs.physlock}/bin/physlock"; user = "root"; };
|
||||
|
||||
})
|
||||
]);
|
||||
|
||||
}
|
||||
|
@ -88,6 +88,9 @@ let
|
||||
${flip concatMapStrings v.map (p: ''
|
||||
HiddenServicePort ${toString p.port} ${p.destination}
|
||||
'')}
|
||||
${optionalString (v.authorizeClient != null) ''
|
||||
HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
|
||||
''}
|
||||
''))
|
||||
+ cfg.extraConfig;
|
||||
|
||||
@ -619,6 +622,33 @@ in
|
||||
}));
|
||||
};
|
||||
|
||||
authorizeClient = mkOption {
|
||||
default = null;
|
||||
description = "If configured, the hidden service is accessible for authorized clients only.";
|
||||
type = types.nullOr (types.submodule ({config, ...}: {
|
||||
|
||||
options = {
|
||||
|
||||
authType = mkOption {
|
||||
type = types.enum [ "basic" "stealth" ];
|
||||
description = ''
|
||||
Either <literal>"basic"</literal> for a general-purpose authorization protocol
|
||||
or <literal>"stealth"</literal> for a less scalable protocol
|
||||
that also hides service activity from unauthorized clients.
|
||||
'';
|
||||
};
|
||||
|
||||
clientNames = mkOption {
|
||||
type = types.nonEmptyListOf (types.strMatching "[A-Za-z0-9+-_]+");
|
||||
description = ''
|
||||
Only clients that are listed here are authorized to access the hidden service.
|
||||
Generated authorization data can be found in <filename>${torDirectory}/onion/$name/hostname</filename>.
|
||||
Clients need to put this authorization data in their configuration file using <literal>HidServAuth</literal>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
@ -15,6 +15,9 @@ let
|
||||
} // (optionalAttrs vhostConfig.enableACME {
|
||||
sslCertificate = "/var/lib/acme/${serverName}/fullchain.pem";
|
||||
sslCertificateKey = "/var/lib/acme/${serverName}/key.pem";
|
||||
}) // (optionalAttrs (vhostConfig.useACMEHost != null) {
|
||||
sslCertificate = "/var/lib/acme/${vhostConfig.useACMEHost}/fullchain.pem";
|
||||
sslCertificateKey = "/var/lib/acme/${vhostConfig.useACMEHost}/key.pem";
|
||||
})
|
||||
) cfg.virtualHosts;
|
||||
enableIPv6 = config.networking.enableIPv6;
|
||||
@ -174,7 +177,7 @@ let
|
||||
|
||||
redirectListen = filter (x: !x.ssl) defaultListen;
|
||||
|
||||
acmeLocation = ''
|
||||
acmeLocation = optionalString (vhost.enableACME || vhost.useACMEHost != null) ''
|
||||
location /.well-known/acme-challenge {
|
||||
${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"}
|
||||
root ${vhost.acmeRoot};
|
||||
@ -194,7 +197,7 @@ let
|
||||
${concatMapStringsSep "\n" listenString redirectListen}
|
||||
|
||||
server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
|
||||
${optionalString vhost.enableACME acmeLocation}
|
||||
${acmeLocation}
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
@ -204,7 +207,7 @@ let
|
||||
server {
|
||||
${concatMapStringsSep "\n" listenString hostListen}
|
||||
server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
|
||||
${optionalString vhost.enableACME acmeLocation}
|
||||
${acmeLocation}
|
||||
${optionalString (vhost.root != null) "root ${vhost.root};"}
|
||||
${optionalString (vhost.globalRedirect != null) ''
|
||||
return 301 http${optionalString hasSSL "s"}://${vhost.globalRedirect}$request_uri;
|
||||
@ -555,6 +558,14 @@ in
|
||||
are mutually exclusive.
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
assertion = all (conf: !(conf.enableACME && conf.useACMEHost != null)) (attrValues virtualHosts);
|
||||
message = ''
|
||||
Options services.nginx.service.virtualHosts.<name>.enableACME and
|
||||
services.nginx.virtualHosts.<name>.useACMEHost are mutually exclusive.
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.nginx = {
|
||||
@ -580,7 +591,7 @@ in
|
||||
security.acme.certs = filterAttrs (n: v: v != {}) (
|
||||
let
|
||||
vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
|
||||
acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs;
|
||||
acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs;
|
||||
acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
|
||||
user = cfg.user;
|
||||
group = lib.mkDefault cfg.group;
|
||||
|
@ -48,7 +48,21 @@ with lib;
|
||||
enableACME = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to ask Let's Encrypt to sign a certificate for this vhost.";
|
||||
description = ''
|
||||
Whether to ask Let's Encrypt to sign a certificate for this vhost.
|
||||
Alternately, you can use an existing certificate through <option>useACMEHost</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
useACMEHost = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
A host of an existing Let's Encrypt certificate to use.
|
||||
This is useful if you have many subdomains and want to avoid hitting the
|
||||
<link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>.
|
||||
Alternately, you can generate a certificate through <option>enableACME</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
acmeRoot = mkOption {
|
||||
|
@ -64,6 +64,16 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
default = "traefik";
|
||||
type = types.string;
|
||||
example = "docker";
|
||||
description = ''
|
||||
Set the group that traefik runs under.
|
||||
For the docker backend this needs to be set to <literal>docker</literal> instead.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.traefik;
|
||||
defaultText = "pkgs.traefik";
|
||||
@ -87,7 +97,7 @@ in {
|
||||
];
|
||||
Type = "simple";
|
||||
User = "traefik";
|
||||
Group = "traefik";
|
||||
Group = cfg.group;
|
||||
Restart = "on-failure";
|
||||
StartLimitInterval = 86400;
|
||||
StartLimitBurst = 5;
|
||||
|
@ -47,6 +47,18 @@ in
|
||||
${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
|
||||
''}
|
||||
|
||||
if [ -f "$HOME/.config/kdeglobals" ]
|
||||
then
|
||||
# Remove extraneous font style names.
|
||||
# See also: https://phabricator.kde.org/D9070
|
||||
${getBin pkgs.gnused}/bin/sed -i "$HOME/.config/kdeglobals" \
|
||||
-e '/^fixed=/ s/,Regular$//' \
|
||||
-e '/^font=/ s/,Regular$//' \
|
||||
-e '/^menuFont=/ s/,Regular$//' \
|
||||
-e '/^smallestReadableFont=/ s/,Regular$//' \
|
||||
-e '/^toolBarFont=/ s/,Regular$//'
|
||||
fi
|
||||
|
||||
exec "${getBin plasma5.plasma-workspace}/bin/startkde"
|
||||
'';
|
||||
};
|
||||
|
@ -25,12 +25,12 @@ in
|
||||
{ name = "2bwm";
|
||||
start =
|
||||
''
|
||||
${pkgs."2bwm"}/bin/2bwm &
|
||||
${pkgs._2bwm}/bin/2bwm &
|
||||
waitPID=$!
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs."2bwm" ];
|
||||
environment.systemPackages = [ pkgs._2bwm ];
|
||||
|
||||
};
|
||||
|
||||
|
@ -206,7 +206,8 @@ in
|
||||
"xhci_hcd"
|
||||
"xhci_pci"
|
||||
"usbhid"
|
||||
"hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp"
|
||||
"hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
|
||||
"hid_logitech_hidpp" "hid_logitech_dj"
|
||||
|
||||
] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
|
||||
# Misc. x86 keyboard stuff.
|
||||
|
@ -24,7 +24,11 @@ let
|
||||
|
||||
kernel = config.boot.kernelPackages;
|
||||
|
||||
packages = if config.boot.zfs.enableUnstable then {
|
||||
packages = if config.boot.zfs.enableLegacyCrypto then {
|
||||
spl = kernel.splLegacyCrypto;
|
||||
zfs = kernel.zfsLegacyCrypto;
|
||||
zfsUser = pkgs.zfsLegacyCrypto;
|
||||
} else if config.boot.zfs.enableUnstable then {
|
||||
spl = kernel.splUnstable;
|
||||
zfs = kernel.zfsUnstable;
|
||||
zfsUser = pkgs.zfsUnstable;
|
||||
@ -75,6 +79,27 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
enableLegacyCrypto = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enabling this option will allow you to continue to use the old format for
|
||||
encrypted datasets. With the inclusion of stability patches the format of
|
||||
encrypted datasets has changed. They can still be accessed and mounted but
|
||||
in read-only mode mounted. It is highly recommended to convert them to
|
||||
the new format.
|
||||
|
||||
This option is only for convenience to people that cannot convert their
|
||||
datasets to the new format yet and it will be removed in due time.
|
||||
|
||||
For migration strategies from old format to this new one, check the Wiki:
|
||||
https://nixos.wiki/wiki/NixOS_on_ZFS#Encrypted_Dataset_Format_Change
|
||||
|
||||
See https://github.com/zfsonlinux/zfs/pull/6864 for more details about
|
||||
the stability patches.
|
||||
'';
|
||||
};
|
||||
|
||||
extraPools = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
|
@ -230,9 +230,7 @@ let
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
ip tuntap add dev "${i.name}" \
|
||||
${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
|
||||
user "${i.virtualOwner}"
|
||||
ip tuntap add dev "${i.name}" mode "${i.virtualType}" user "${i.virtualOwner}"
|
||||
'';
|
||||
postStop = ''
|
||||
ip link del ${i.name} || true
|
||||
|
@ -74,21 +74,17 @@ in
|
||||
networks."99-main" = genericNetwork mkDefault;
|
||||
}
|
||||
(mkMerge (flip map interfaces (i: {
|
||||
netdevs = mkIf i.virtual (
|
||||
let
|
||||
devType = if i.virtualType != null then i.virtualType
|
||||
else (if hasPrefix "tun" i.name then "tun" else "tap");
|
||||
in {
|
||||
"40-${i.name}" = {
|
||||
netdevConfig = {
|
||||
Name = i.name;
|
||||
Kind = devType;
|
||||
};
|
||||
"${devType}Config" = optionalAttrs (i.virtualOwner != null) {
|
||||
User = i.virtualOwner;
|
||||
};
|
||||
netdevs = mkIf i.virtual ({
|
||||
"40-${i.name}" = {
|
||||
netdevConfig = {
|
||||
Name = i.name;
|
||||
Kind = i.virtualType;
|
||||
};
|
||||
});
|
||||
"${i.virtualType}Config" = optionalAttrs (i.virtualOwner != null) {
|
||||
User = i.virtualOwner;
|
||||
};
|
||||
};
|
||||
});
|
||||
networks."40-${i.name}" = mkMerge [ (genericNetwork mkDefault) {
|
||||
name = mkDefault i.name;
|
||||
DHCP = mkForce (dhcpStr
|
||||
|
@ -273,11 +273,13 @@ let
|
||||
};
|
||||
|
||||
virtualType = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr (enum [ "tun" "tap" ]);
|
||||
default = if hasPrefix "tun" name then "tun" else "tap";
|
||||
defaultText = literalExample ''if hasPrefix "tun" name then "tun" else "tap"'';
|
||||
type = with types; enum [ "tun" "tap" ];
|
||||
description = ''
|
||||
The explicit type of interface to create. Accepts tun or tap strings.
|
||||
Also accepts null to implicitly detect the type of device.
|
||||
The type of interface to create.
|
||||
The default is TUN for an interface name starting
|
||||
with "tun", otherwise TAP.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -4,13 +4,10 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with import ../../lib/qemu-flags.nix { inherit pkgs; };
|
||||
|
||||
let
|
||||
kernel = config.boot.kernelPackages.kernel;
|
||||
# FIXME: figure out a common place for this instead of copy pasting
|
||||
serialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
|
||||
else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
|
||||
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
|
||||
in
|
||||
|
||||
{
|
||||
@ -28,8 +25,8 @@ in
|
||||
|
||||
systemd.services.backdoor =
|
||||
{ wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "dev-hvc0.device" "dev-${serialDevice}.device" ];
|
||||
after = [ "dev-hvc0.device" "dev-${serialDevice}.device" ];
|
||||
requires = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
|
||||
after = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
|
||||
script =
|
||||
''
|
||||
export USER=root
|
||||
@ -46,7 +43,7 @@ in
|
||||
|
||||
cd /tmp
|
||||
exec < /dev/hvc0 > /dev/hvc0
|
||||
while ! exec 2> /dev/${serialDevice}; do sleep 0.1; done
|
||||
while ! exec 2> /dev/${qemuSerialDevice}; do sleep 0.1; done
|
||||
echo "connecting to host..." >&2
|
||||
stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion
|
||||
echo
|
||||
@ -55,10 +52,10 @@ in
|
||||
serviceConfig.KillSignal = "SIGHUP";
|
||||
};
|
||||
|
||||
# Prevent agetty from being instantiated on ${serialDevice}, since it
|
||||
# interferes with the backdoor (writes to ${serialDevice} will randomly fail
|
||||
# Prevent agetty from being instantiated on the serial device, since it
|
||||
# interferes with the backdoor (writes to it will randomly fail
|
||||
# with EIO). Likewise for hvc0.
|
||||
systemd.services."serial-getty@${serialDevice}".enable = false;
|
||||
systemd.services."serial-getty@${qemuSerialDevice}".enable = false;
|
||||
systemd.services."serial-getty@hvc0".enable = false;
|
||||
|
||||
boot.initrd.preDeviceCommands =
|
||||
@ -94,7 +91,7 @@ in
|
||||
# Panic if an error occurs in stage 1 (rather than waiting for
|
||||
# user intervention).
|
||||
boot.kernelParams =
|
||||
[ "console=${serialDevice}" "panic=1" "boot.panic_on_fail" ];
|
||||
[ "console=${qemuSerialDevice}" "panic=1" "boot.panic_on_fail" ];
|
||||
|
||||
# `xwininfo' is used by the test driver to query open windows.
|
||||
environment.systemPackages = [ pkgs.xorg.xwininfo ];
|
||||
|
@ -11,7 +11,7 @@ with lib;
|
||||
services.udisks2.enable = mkDefault false;
|
||||
powerManagement.enable = mkDefault false;
|
||||
|
||||
networking.useHostResolvConf = true;
|
||||
networking.useHostResolvConf = mkDefault true;
|
||||
|
||||
# Containers should be light-weight, so start sshd on demand.
|
||||
services.openssh.startWhenNeeded = mkDefault true;
|
||||
|
@ -10,21 +10,11 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
with import ../../lib/qemu-flags.nix { inherit pkgs; };
|
||||
|
||||
let
|
||||
|
||||
qemu = config.system.build.qemu or pkgs.qemu_test;
|
||||
qemuKvm = {
|
||||
"i686-linux" = "${qemu}/bin/qemu-kvm";
|
||||
"x86_64-linux" = "${qemu}/bin/qemu-kvm -cpu kvm64";
|
||||
"armv7l-linux" = "${qemu}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
|
||||
"aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
|
||||
}.${pkgs.stdenv.system};
|
||||
|
||||
# FIXME: figure out a common place for this instead of copy pasting
|
||||
serialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
|
||||
else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
|
||||
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
|
||||
|
||||
vmName =
|
||||
if config.networking.hostName == ""
|
||||
@ -34,7 +24,7 @@ let
|
||||
cfg = config.virtualisation;
|
||||
|
||||
qemuGraphics = if cfg.graphics then "" else "-nographic";
|
||||
kernelConsole = if cfg.graphics then "" else "console=${serialDevice}";
|
||||
kernelConsole = if cfg.graphics then "" else "console=${qemuSerialDevice}";
|
||||
ttys = [ "tty1" "tty2" "tty3" "tty4" "tty5" "tty6" ];
|
||||
|
||||
# Shell script to start the VM.
|
||||
@ -83,7 +73,7 @@ let
|
||||
'')}
|
||||
|
||||
# Start QEMU.
|
||||
exec ${qemuKvm} \
|
||||
exec ${qemuBinary qemu} \
|
||||
-name ${vmName} \
|
||||
-m ${toString config.virtualisation.memorySize} \
|
||||
-smp ${toString config.virtualisation.cores} \
|
||||
|
@ -35,24 +35,19 @@ in
|
||||
description = ''
|
||||
The package used for Xen binary.
|
||||
'';
|
||||
relatedPackages = [ "xen" "xen-light" ];
|
||||
};
|
||||
|
||||
virtualisation.xen.qemu = mkOption {
|
||||
type = types.path;
|
||||
defaultText = "\${pkgs.xen}/lib/xen/bin/qemu-system-i386";
|
||||
example = literalExample "''${pkgs.qemu_xen-light}/bin/qemu-system-i386";
|
||||
description = ''
|
||||
The qemu binary to use for Dom-0 backend.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualisation.xen.qemu-package = mkOption {
|
||||
virtualisation.xen.package-qemu = mkOption {
|
||||
type = types.package;
|
||||
defaultText = "pkgs.xen";
|
||||
example = literalExample "pkgs.qemu_xen-light";
|
||||
description = ''
|
||||
The package with qemu binaries for xendomains.
|
||||
The package with qemu binaries for dom0 qemu and xendomains.
|
||||
'';
|
||||
relatedPackages = [ "xen"
|
||||
{ name = "qemu_xen-light"; comment = "For use with pkgs.xen-light."; }
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.xen.bootParams =
|
||||
@ -158,8 +153,7 @@ in
|
||||
} ];
|
||||
|
||||
virtualisation.xen.package = mkDefault pkgs.xen;
|
||||
virtualisation.xen.qemu = mkDefault "${pkgs.xen}/lib/xen/bin/qemu-system-i386";
|
||||
virtualisation.xen.qemu-package = mkDefault pkgs.xen;
|
||||
virtualisation.xen.package-qemu = mkDefault pkgs.xen;
|
||||
virtualisation.xen.stored = mkDefault "${cfg.package}/bin/oxenstored";
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
@ -339,7 +333,8 @@ in
|
||||
after = [ "xen-console.service" ];
|
||||
requires = [ "xen-store.service" ];
|
||||
serviceConfig.ExecStart = ''
|
||||
${cfg.qemu} -xen-attach -xen-domid 0 -name dom0 -M xenpv \
|
||||
${cfg.package-qemu}/${cfg.package-qemu.qemu-system-i386} \
|
||||
-xen-attach -xen-domid 0 -name dom0 -M xenpv \
|
||||
-nographic -monitor /dev/null -serial /dev/null -parallel /dev/null
|
||||
'';
|
||||
};
|
||||
@ -448,7 +443,7 @@ in
|
||||
before = [ "dhcpd.service" ];
|
||||
restartIfChanged = false;
|
||||
serviceConfig.RemainAfterExit = "yes";
|
||||
path = [ cfg.package cfg.qemu-package ];
|
||||
path = [ cfg.package cfg.package-qemu ];
|
||||
environment.XENDOM_CONFIG = "${cfg.package}/etc/sysconfig/xendomains";
|
||||
preStart = "mkdir -p /var/lock/subsys -m 755";
|
||||
serviceConfig.ExecStart = "${cfg.package}/etc/init.d/xendomains start";
|
||||
|
@ -2,7 +2,7 @@
|
||||
# and nixos-14.04). The channel is updated every time the ‘tested’ job
|
||||
# succeeds, and all other jobs have finished (they may fail).
|
||||
|
||||
{ nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
{ nixpkgs ? { outPath = (import ../lib).cleanSource ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
, stableBranch ? false
|
||||
, supportedSystems ? [ "x86_64-linux" ]
|
||||
, limitedSupportedSystems ? [ "i686-linux" ]
|
||||
@ -52,7 +52,8 @@ in rec {
|
||||
(all nixos.dummy)
|
||||
(all nixos.manual)
|
||||
|
||||
(all nixos.iso_minimal)
|
||||
nixos.iso_minimal.x86_64-linux
|
||||
nixos.iso_minimal.i686-linux
|
||||
nixos.iso_graphical.x86_64-linux
|
||||
nixos.ova.x86_64-linux
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# small subset of Nixpkgs, mostly useful for servers that need fast
|
||||
# security updates.
|
||||
|
||||
{ nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
{ nixpkgs ? { outPath = (import ../lib).cleanSource ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
, stableBranch ? false
|
||||
, supportedSystems ? [ "x86_64-linux" ] # no i686-linux
|
||||
}:
|
||||
@ -41,6 +41,7 @@ in rec {
|
||||
nfs3
|
||||
openssh
|
||||
php-pcre
|
||||
predictable-interface-names
|
||||
proxy
|
||||
simple;
|
||||
installer = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
{ nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
{ nixpkgs ? { outPath = (import ../lib).cleanSource ./..; revCount = 56789; shortRev = "gfedcba"; }
|
||||
, stableBranch ? false
|
||||
, supportedSystems ? [ "x86_64-linux" "aarch64-linux" ]
|
||||
}:
|
||||
@ -227,6 +227,7 @@ in rec {
|
||||
tests.blivet = callTest tests/blivet.nix {};
|
||||
tests.boot = callSubTests tests/boot.nix {};
|
||||
tests.boot-stage1 = callTest tests/boot-stage1.nix {};
|
||||
tests.borgbackup = callTest tests/borgbackup.nix {};
|
||||
tests.cadvisor = callTestOnTheseSystems ["x86_64-linux"] tests/cadvisor.nix {};
|
||||
tests.chromium = (callSubTestsOnTheseSystems ["x86_64-linux"] tests/chromium.nix {}).stable;
|
||||
tests.cjdns = callTest tests/cjdns.nix {};
|
||||
@ -266,6 +267,7 @@ in rec {
|
||||
tests.graphite = callTest tests/graphite.nix {};
|
||||
tests.hardened = callTest tests/hardened.nix { };
|
||||
tests.hibernate = callTest tests/hibernate.nix {};
|
||||
tests.home-assistant = callTest tests/home-assistant.nix { };
|
||||
tests.hound = callTest tests/hound.nix {};
|
||||
tests.i3wm = callTest tests/i3wm.nix {};
|
||||
tests.initrd-network-ssh = callTest tests/initrd-network-ssh {};
|
||||
@ -290,6 +292,7 @@ in rec {
|
||||
tests.login = callTest tests/login.nix {};
|
||||
#tests.logstash = callTest tests/logstash.nix {};
|
||||
tests.mathics = callTest tests/mathics.nix {};
|
||||
tests.matrix-synapse = callTest tests/matrix-synapse.nix {};
|
||||
tests.mesos = callTest tests/mesos.nix {};
|
||||
tests.misc = callTest tests/misc.nix {};
|
||||
tests.mongodb = callTest tests/mongodb.nix {};
|
||||
@ -323,6 +326,7 @@ in rec {
|
||||
tests.pgmanage = callTest tests/pgmanage.nix {};
|
||||
tests.postgis = callTest tests/postgis.nix {};
|
||||
#tests.pgjwt = callTest tests/pgjwt.nix {};
|
||||
tests.predictable-interface-names = callSubTests tests/predictable-interface-names.nix {};
|
||||
tests.printing = callTest tests/printing.nix {};
|
||||
tests.prometheus = callTest tests/prometheus.nix {};
|
||||
tests.proxy = callTest tests/proxy.nix {};
|
||||
@ -330,7 +334,9 @@ in rec {
|
||||
# tests.quagga = callTest tests/quagga.nix {};
|
||||
tests.quake3 = callTest tests/quake3.nix {};
|
||||
tests.radicale = callTest tests/radicale.nix {};
|
||||
tests.rspamd = callSubTests tests/rspamd.nix {};
|
||||
tests.runInMachine = callTest tests/run-in-machine.nix {};
|
||||
tests.rxe = callTest tests/rxe.nix {};
|
||||
tests.samba = callTest tests/samba.nix {};
|
||||
tests.sddm = callSubTests tests/sddm.nix {};
|
||||
tests.simple = callTest tests/simple.nix {};
|
||||
@ -348,6 +354,7 @@ in rec {
|
||||
tests.wordpress = callTest tests/wordpress.nix {};
|
||||
tests.xfce = callTest tests/xfce.nix {};
|
||||
tests.xmonad = callTest tests/xmonad.nix {};
|
||||
tests.yabar = callTest tests/yabar.nix {};
|
||||
tests.zookeeper = callTest tests/zookeeper.nix {};
|
||||
|
||||
/* Build a bunch of typical closures so that Hydra can keep track of
|
||||
|
@ -1,7 +1,6 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with import ../lib/qemu-flags.nix;
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
21
nixos/tests/borgbackup.nix
Normal file
21
nixos/tests/borgbackup.nix
Normal file
@ -0,0 +1,21 @@
|
||||
import ./make-test.nix ({ pkgs, ...}: {
|
||||
name = "borgbackup";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ mic92 ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
machine = { config, pkgs, ... }: {
|
||||
environment.systemPackages = [ pkgs.borgbackup ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
my $borg = "BORG_PASSPHRASE=supersecret borg";
|
||||
$machine->succeed("$borg init --encryption=repokey /tmp/backup");
|
||||
$machine->succeed("mkdir /tmp/data/ && echo 'data' >/tmp/data/file");
|
||||
$machine->succeed("$borg create --stats /tmp/backup::test /tmp/data");
|
||||
$machine->succeed("$borg extract /tmp/backup::test");
|
||||
$machine->succeed('c=$(cat data/file) && echo "c = $c" >&2 && [[ "$c" == "data" ]]');
|
||||
'';
|
||||
})
|
@ -1,7 +1,6 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with import ../lib/qemu-flags.nix;
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
@ -1,7 +1,6 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with import ../lib/qemu-flags.nix;
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
46
nixos/tests/home-assistant.nix
Normal file
46
nixos/tests/home-assistant.nix
Normal file
@ -0,0 +1,46 @@
|
||||
import ./make-test.nix ({ pkgs, ... }:
|
||||
|
||||
let
|
||||
configDir = "/var/lib/foobar";
|
||||
|
||||
in {
|
||||
name = "home-assistant";
|
||||
|
||||
nodes = {
|
||||
hass =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
services.home-assistant = {
|
||||
inherit configDir;
|
||||
enable = true;
|
||||
config = {
|
||||
homeassistant = {
|
||||
name = "Home";
|
||||
time_zone = "UTC";
|
||||
latitude = "0.0";
|
||||
longitude = "0.0";
|
||||
elevation = 0;
|
||||
};
|
||||
frontend = { };
|
||||
http = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
$hass->waitForUnit("home-assistant.service");
|
||||
|
||||
# Since config is specified using a Nix attribute set,
|
||||
# configuration.yaml is a link to the Nix store
|
||||
$hass->succeed("test -L ${configDir}/configuration.yaml");
|
||||
|
||||
# Check that Home Assistant's web interface and API can be reached
|
||||
$hass->waitForOpenPort(8123);
|
||||
$hass->succeed("curl --fail http://localhost:8123/states");
|
||||
$hass->succeed("curl --fail http://localhost:8123/api/ | grep 'API running'");
|
||||
|
||||
$hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR");
|
||||
'';
|
||||
})
|
@ -1,7 +1,6 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with import ../lib/qemu-flags.nix;
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
@ -1,7 +1,6 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
with import ../../lib/testing.nix { inherit system; };
|
||||
with import ../../lib/qemu-flags.nix;
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
@ -2,4 +2,4 @@ f: { system ? builtins.currentSystem, ... } @ args:
|
||||
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
|
||||
makeTest (if builtins.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
|
||||
makeTest (if pkgs.lib.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
|
||||
|
30
nixos/tests/matrix-synapse.nix
Normal file
30
nixos/tests/matrix-synapse.nix
Normal file
@ -0,0 +1,30 @@
|
||||
import ./make-test.nix ({ pkgs, ... } : {
|
||||
|
||||
name = "matrix-synapse";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ corngood ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
server_postgres = args: {
|
||||
services.matrix-synapse.enable = true;
|
||||
services.matrix-synapse.database_type = "psycopg2";
|
||||
};
|
||||
|
||||
server_sqlite = args: {
|
||||
services.matrix-synapse.enable = true;
|
||||
services.matrix-synapse.database_type = "sqlite3";
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
startAll;
|
||||
$server_postgres->waitForUnit("matrix-synapse.service");
|
||||
$server_postgres->waitUntilSucceeds("curl -Lk https://localhost:8448/");
|
||||
$server_postgres->requireActiveUnit("postgresql.service");
|
||||
$server_sqlite->waitForUnit("matrix-synapse.service");
|
||||
$server_sqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/");
|
||||
$server_sqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]");
|
||||
'';
|
||||
|
||||
})
|
@ -433,6 +433,49 @@ let
|
||||
$client2->succeed("ip addr show dev vlan >&2");
|
||||
'';
|
||||
};
|
||||
virtual = {
|
||||
name = "Virtual";
|
||||
machine = {
|
||||
networking.interfaces."tap0" = {
|
||||
ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ];
|
||||
ip6 = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
|
||||
virtual = true;
|
||||
};
|
||||
networking.interfaces."tun0" = {
|
||||
ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
|
||||
ip6 = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
|
||||
virtual = true;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
my $targetList = <<'END';
|
||||
tap0: tap UNKNOWN_FLAGS:800 user 0
|
||||
tun0: tun UNKNOWN_FLAGS:800 user 0
|
||||
END
|
||||
|
||||
# Wait for networking to come up
|
||||
$machine->start;
|
||||
$machine->waitForUnit("network.target");
|
||||
|
||||
# Test interfaces set up
|
||||
my $list = $machine->succeed("ip tuntap list | sort");
|
||||
"$list" eq "$targetList" or die(
|
||||
"The list of virtual interfaces does not match the expected one:\n",
|
||||
"Result:\n", "$list\n",
|
||||
"Expected:\n", "$targetList\n"
|
||||
);
|
||||
|
||||
# Test interfaces clean up
|
||||
$machine->succeed("systemctl stop network-addresses-tap0");
|
||||
$machine->succeed("systemctl stop network-addresses-tun0");
|
||||
my $residue = $machine->succeed("ip tuntap list");
|
||||
$residue eq "" or die(
|
||||
"Some virtual interface has not been properly cleaned:\n",
|
||||
"$residue\n"
|
||||
);
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
in mapAttrs (const (attrs: makeTest (attrs // {
|
||||
|
27
nixos/tests/predictable-interface-names.nix
Normal file
27
nixos/tests/predictable-interface-names.nix
Normal file
@ -0,0 +1,27 @@
|
||||
{ system ? builtins.currentSystem
|
||||
, pkgs ? import ../.. { inherit system; }
|
||||
}:
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
let boolToString = x: if x then "yes" else "no"; in
|
||||
let testWhenSetTo = predictable: withNetworkd:
|
||||
makeTest {
|
||||
name = "${if predictable then "" else "un"}predictableInterfaceNames${if withNetworkd then "-with-networkd" else ""}";
|
||||
meta = {};
|
||||
|
||||
machine = { config, pkgs, ... }: {
|
||||
networking.usePredictableInterfaceNames = pkgs.stdenv.lib.mkForce predictable;
|
||||
networking.useNetworkd = withNetworkd;
|
||||
networking.dhcpcd.enable = !withNetworkd;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
print $machine->succeed("ip link");
|
||||
$machine->succeed("ip link show ${if predictable then "ens3" else "eth0"}");
|
||||
$machine->fail("ip link show ${if predictable then "eth0" else "ens3"}");
|
||||
'';
|
||||
}; in
|
||||
with pkgs.stdenv.lib.lists;
|
||||
with pkgs.stdenv.lib.attrsets;
|
||||
listToAttrs (map (drv: nameValuePair drv.name drv) (
|
||||
crossLists testWhenSetTo [[true false] [true false]]
|
||||
))
|
140
nixos/tests/rspamd.nix
Normal file
140
nixos/tests/rspamd.nix
Normal file
@ -0,0 +1,140 @@
|
||||
{ system ? builtins.currentSystem }:
|
||||
with import ../lib/testing.nix { inherit system; };
|
||||
with pkgs.lib;
|
||||
let
|
||||
initMachine = ''
|
||||
startAll
|
||||
$machine->waitForUnit("rspamd.service");
|
||||
$machine->succeed("id \"rspamd\" >/dev/null");
|
||||
'';
|
||||
checkSocket = socket: user: group: mode: ''
|
||||
$machine->succeed("ls ${socket} >/dev/null");
|
||||
$machine->succeed("[[ \"\$(stat -c %U ${socket})\" == \"${user}\" ]]");
|
||||
$machine->succeed("[[ \"\$(stat -c %G ${socket})\" == \"${group}\" ]]");
|
||||
$machine->succeed("[[ \"\$(stat -c %a ${socket})\" == \"${mode}\" ]]");
|
||||
'';
|
||||
simple = name: socketActivation: enableIPv6: makeTest {
|
||||
name = "rspamd-${name}";
|
||||
machine = {
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
socketActivation = socketActivation;
|
||||
};
|
||||
networking.enableIPv6 = enableIPv6;
|
||||
};
|
||||
testScript = ''
|
||||
startAll
|
||||
$machine->waitForUnit("multi-user.target");
|
||||
$machine->waitForOpenPort(11334);
|
||||
$machine->waitForUnit("rspamd.service");
|
||||
$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("systemctl cat rspamd.service"));
|
||||
${if socketActivation then ''
|
||||
$machine->log($machine->succeed("systemctl cat rspamd-controller-1.socket"));
|
||||
$machine->log($machine->succeed("systemctl cat rspamd-normal-1.socket"));
|
||||
'' else ''
|
||||
$machine->fail("systemctl cat rspamd-controller-1.socket");
|
||||
$machine->fail("systemctl cat rspamd-normal-1.socket");
|
||||
''}
|
||||
$machine->log($machine->succeed("curl http://localhost:11334/auth"));
|
||||
$machine->log($machine->succeed("curl http://127.0.0.1:11334/auth"));
|
||||
${optionalString enableIPv6 ''
|
||||
$machine->log($machine->succeed("curl http://[::1]:11334/auth"));
|
||||
''}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
simple = simple "simple" false true;
|
||||
ipv4only = simple "ipv4only" false false;
|
||||
simple-socketActivated = simple "simple-socketActivated" true true;
|
||||
ipv4only-socketActivated = simple "ipv4only-socketActivated" true false;
|
||||
deprecated = makeTest {
|
||||
name = "rspamd-deprecated";
|
||||
machine = {
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
bindSocket = [ "/run/rspamd.sock mode=0600 user=root group=root" ];
|
||||
bindUISocket = [ "/run/rspamd-worker.sock mode=0666 user=root group=root" ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
$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->fail("systemctl cat rspamd-normal-1.socket");
|
||||
$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"));
|
||||
'';
|
||||
};
|
||||
|
||||
bindports = makeTest {
|
||||
name = "rspamd-bindports";
|
||||
machine = {
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
socketActivation = false;
|
||||
workers.normal.bindSockets = [{
|
||||
socket = "/run/rspamd.sock";
|
||||
mode = "0600";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
}];
|
||||
workers.controller.bindSockets = [{
|
||||
socket = "/run/rspamd-worker.sock";
|
||||
mode = "0666";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
}];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
$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->fail("systemctl cat rspamd-normal-1.socket");
|
||||
$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"));
|
||||
'';
|
||||
};
|
||||
socketActivated = makeTest {
|
||||
name = "rspamd-socketActivated";
|
||||
machine = {
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
workers.normal.bindSockets = [{
|
||||
socket = "/run/rspamd.sock";
|
||||
mode = "0600";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
}];
|
||||
workers.controller.bindSockets = [{
|
||||
socket = "/run/rspamd-worker.sock";
|
||||
mode = "0666";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
}];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
startAll
|
||||
$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("systemctl cat rspamd-normal-1.socket"));
|
||||
$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"));
|
||||
'';
|
||||
};
|
||||
}
|
53
nixos/tests/rxe.nix
Normal file
53
nixos/tests/rxe.nix
Normal file
@ -0,0 +1,53 @@
|
||||
import ./make-test.nix ({ pkgs, ... } :
|
||||
|
||||
let
|
||||
node = { config, pkgs, lib, ... } : {
|
||||
networking = {
|
||||
firewall = {
|
||||
allowedUDPPorts = [ 4791 ]; # open RoCE port
|
||||
allowedTCPPorts = [ 4800 ]; # port for test utils
|
||||
};
|
||||
rxe = {
|
||||
enable = true;
|
||||
interfaces = [ "eth1" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ rdma-core screen ];
|
||||
};
|
||||
|
||||
in {
|
||||
name = "rxe";
|
||||
|
||||
nodes = {
|
||||
server = node;
|
||||
client = node;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
# Test if rxe interface comes up
|
||||
$server->waitForUnit("default.target");
|
||||
$server->succeed("systemctl status rxe.service");
|
||||
$server->succeed("ibv_devices | grep rxe0");
|
||||
|
||||
$client->waitForUnit("default.target");
|
||||
|
||||
# ping pong test
|
||||
$server->succeed("screen -dmS rc_pingpong ibv_rc_pingpong -p 4800 -g0");
|
||||
$client->succeed("sleep 2; ibv_rc_pingpong -p 4800 -g0 server");
|
||||
|
||||
$server->succeed("screen -dmS uc_pingpong ibv_uc_pingpong -p 4800 -g0");
|
||||
$client->succeed("sleep 2; ibv_uc_pingpong -p 4800 -g0 server");
|
||||
|
||||
$server->succeed("screen -dmS ud_pingpong ibv_ud_pingpong -p 4800 -s 1024 -g0");
|
||||
$client->succeed("sleep 2; ibv_ud_pingpong -p 4800 -s 1024 -g0 server");
|
||||
|
||||
$server->succeed("screen -dmS srq_pingpong ibv_srq_pingpong -p 4800 -g0");
|
||||
$client->succeed("sleep 2; ibv_srq_pingpong -p 4800 -g0 server");
|
||||
|
||||
$server->succeed("screen -dmS rping rping -s -a server -C 10");
|
||||
$client->succeed("sleep 2; rping -c -a server -C 10");
|
||||
'';
|
||||
})
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ./make-test.nix ({ pkgs, lib }:
|
||||
import ./make-test.nix ({ pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
25
nixos/tests/yabar.nix
Normal file
25
nixos/tests/yabar.nix
Normal file
@ -0,0 +1,25 @@
|
||||
import ./make-test.nix ({ pkgs, lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
name = "yabar";
|
||||
meta = with pkgs.stdenv.lib.maintainers; {
|
||||
maintainers = [ ma27 ];
|
||||
};
|
||||
|
||||
nodes.yabar = {
|
||||
imports = [ ./common/x11.nix ./common/user-account.nix ];
|
||||
|
||||
services.xserver.displayManager.auto.user = "bob";
|
||||
|
||||
programs.yabar.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
$yabar->start;
|
||||
$yabar->waitForX;
|
||||
|
||||
$yabar->waitForUnit("yabar.service", "bob");
|
||||
'';
|
||||
})
|
89
pkgs/applications/altcoins/monero-gui/default.nix
Normal file
89
pkgs/applications/altcoins/monero-gui/default.nix
Normal file
@ -0,0 +1,89 @@
|
||||
{ stdenv, fetchFromGitHub
|
||||
, makeWrapper, makeDesktopItem
|
||||
, qtbase, qmake, qtmultimedia, qttools
|
||||
, qtgraphicaleffects, qtdeclarative
|
||||
, qtlocation, qtquickcontrols, qtwebchannel
|
||||
, qtwebengine, qtx11extras, qtxmlpatterns
|
||||
, monero, unbound, readline, boost, libunwind
|
||||
}:
|
||||
|
||||
with stdenv.lib;
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
name = "monero-gui-${version}";
|
||||
version = "0.11.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "monero-project";
|
||||
repo = "monero-gui";
|
||||
rev = "v${version}";
|
||||
sha256 = "01d7apwrv8j8bh7plvvhlnll3ransaha3n6rx19nkgvfn319hswq";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ qmake ];
|
||||
|
||||
buildInputs = [
|
||||
qtbase qtmultimedia qtgraphicaleffects
|
||||
qtdeclarative qtlocation qtquickcontrols
|
||||
qtwebchannel qtwebengine qtx11extras
|
||||
qtxmlpatterns monero unbound readline
|
||||
boost libunwind makeWrapper
|
||||
];
|
||||
|
||||
patches = [
|
||||
./move-log-file.patch
|
||||
./move-translations-dir.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
echo '
|
||||
var GUI_VERSION = "${version}";
|
||||
var GUI_MONERO_VERSION = "${getVersion monero}";
|
||||
' > version.js
|
||||
substituteInPlace monero-wallet-gui.pro \
|
||||
--replace '$$[QT_INSTALL_BINS]/lrelease' '${getDev qttools}/bin/lrelease'
|
||||
substituteInPlace src/daemon/DaemonManager.cpp \
|
||||
--replace 'QApplication::applicationDirPath() + "' '"${monero}/bin'
|
||||
'';
|
||||
|
||||
makeFlags = [ "INSTALL_ROOT=$(out)" ];
|
||||
|
||||
preBuild = ''
|
||||
sed -i s#/opt/monero-wallet-gui##g Makefile
|
||||
make -C src/zxcvbn-c
|
||||
'';
|
||||
|
||||
desktopItem = makeDesktopItem {
|
||||
name = "monero-wallet-gui";
|
||||
exec = "monero-wallet-gui";
|
||||
icon = "monero";
|
||||
desktopName = "Monero Wallet";
|
||||
genericName = "Wallet";
|
||||
categories = "Application;Network;Utility;";
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
# install desktop entry
|
||||
mkdir -p $out/share/applications
|
||||
cp ${desktopItem}/share/applications/* $out/share/applications
|
||||
|
||||
# install translations
|
||||
cp -r release/bin/translations $out/share/
|
||||
|
||||
# install icons
|
||||
for n in 16 24 32 48 64 96 128 256; do
|
||||
size=$n"x"$n
|
||||
mkdir -p $out/share/icons/hicolor/$size/apps
|
||||
cp $src/images/appicons/$size.png \
|
||||
$out/share/icons/hicolor/$size/apps/monero.png
|
||||
done;
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Private, secure, untraceable currency";
|
||||
homepage = https://getmonero.org/;
|
||||
license = licenses.bsd3;
|
||||
platforms = platforms.all;
|
||||
maintainers = with maintainers; [ rnhmjoj ];
|
||||
};
|
||||
}
|
42
pkgs/applications/altcoins/monero-gui/move-log-file.patch
Normal file
42
pkgs/applications/altcoins/monero-gui/move-log-file.patch
Normal file
@ -0,0 +1,42 @@
|
||||
diff --git a/main.cpp b/main.cpp
|
||||
index 1a9a979..2316929 100644
|
||||
--- a/main.cpp
|
||||
+++ b/main.cpp
|
||||
@@ -74,10 +74,6 @@ int main(int argc, char *argv[])
|
||||
// qDebug() << "High DPI auto scaling - enabled";
|
||||
//#endif
|
||||
|
||||
- // Log settings
|
||||
- Monero::Wallet::init(argv[0], "monero-wallet-gui");
|
||||
-// qInstallMessageHandler(messageHandler);
|
||||
-
|
||||
MainApp app(argc, argv);
|
||||
|
||||
qDebug() << "app startd";
|
||||
@@ -86,6 +82,13 @@ int main(int argc, char *argv[])
|
||||
app.setOrganizationDomain("getmonero.org");
|
||||
app.setOrganizationName("monero-project");
|
||||
|
||||
+ // Log settings
|
||||
+ QString logfile =
|
||||
+ QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||
+ + "/monero-wallet-gui.log";
|
||||
+ Monero::Wallet::init(argv[0], logfile.toUtf8().constData());
|
||||
+
|
||||
+
|
||||
filter *eventFilter = new filter;
|
||||
app.installEventFilter(eventFilter);
|
||||
|
||||
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
|
||||
index 8525bf3..6967b24 100644
|
||||
--- a/src/libwalletqt/Wallet.cpp
|
||||
+++ b/src/libwalletqt/Wallet.cpp
|
||||
@@ -613,7 +613,7 @@ QString Wallet::getDaemonLogPath() const
|
||||
|
||||
QString Wallet::getWalletLogPath() const
|
||||
{
|
||||
- return QCoreApplication::applicationDirPath() + "/monero-wallet-gui.log";
|
||||
+ return QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/monero-wallet-gui.log";
|
||||
}
|
||||
|
||||
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user