Merge branch 'master' into add_vim_plugins

This commit is contained in:
Jörg Thalheim 2018-02-10 12:38:56 +00:00 committed by GitHub
commit cbd14de2c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
907 changed files with 35373 additions and 14163 deletions

View file

@ -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 &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).systems.examples.fooBarBaz'</command>.
You can use them programmatically, or on the command line: <programlisting>
nix-build &lt;nixpkgs&gt; --arg crossSystem '(import &lt;nixpkgs/lib&gt;).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 &lt;nixpkgs&gt; --arg crossSystem.config '&lt;arch&gt;-&lt;os&gt;-&lt;vendor&gt;-&lt;abi&gt;' -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.

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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);

View file

@ -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;

View file

@ -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];

View file

@ -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>";

View file

@ -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;

View file

@ -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;

View file

@ -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 = [

View file

@ -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";
};
#

View file

@ -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; }; };

View file

@ -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}";
################################################################################
}

View file

@ -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

View file

@ -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));
}

View file

@ -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";

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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 {

View file

@ -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}'");
}

View file

@ -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;

View file

@ -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" ];

View file

@ -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 ''

View file

@ -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

View file

@ -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;
};
};
}

View file

@ -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

View file

@ -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.

View file

@ -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"] ];
};
};
};

View 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 ];
}

View file

@ -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 {});
};
}

View file

@ -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;

View 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";
};
};
}

View file

@ -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" ])
];
}

View file

@ -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.&lt;name&gt;.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)

View file

@ -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"}

View file

@ -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

View file

@ -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 ];

View file

@ -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.";
};

View file

@ -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";

View file

@ -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" ])
];
}

View 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;
};
}

View file

@ -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";

View file

@ -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.

View file

@ -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"} \

View file

@ -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
'';
};
};
}

View 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
'';
};
};
}

View 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";
};
};
}

View 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";
};
};
};
};
}

View file

@ -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;

View file

@ -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
};
};
};
}
}

View file

@ -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" ];

View 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.
'';
};
};
}

View file

@ -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);

View 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";
};
};
};
}

View file

@ -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;

View file

@ -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"; };
})
]);
}

View file

@ -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 = {

View file

@ -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;

View file

@ -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 {

View file

@ -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;

View file

@ -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"
'';
};

View file

@ -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 ];
};

View file

@ -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.

View file

@ -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 = [];

View file

@ -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

View file

@ -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

View file

@ -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.
'';
};

View file

@ -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 ];

View file

@ -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;

View file

@ -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} \

View file

@ -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";

View file

@ -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

View file

@ -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 = {

View file

@ -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

View file

@ -1,7 +1,6 @@
{ system ? builtins.currentSystem }:
with import ../lib/testing.nix { inherit system; };
with import ../lib/qemu-flags.nix;
with pkgs.lib;
let

View 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" ]]');
'';
})

View file

@ -1,7 +1,6 @@
{ system ? builtins.currentSystem }:
with import ../lib/testing.nix { inherit system; };
with import ../lib/qemu-flags.nix;
with pkgs.lib;
let

View file

@ -1,7 +1,6 @@
{ system ? builtins.currentSystem }:
with import ../lib/testing.nix { inherit system; };
with import ../lib/qemu-flags.nix;
with pkgs.lib;
let

View 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");
'';
})

View file

@ -1,7 +1,6 @@
{ system ? builtins.currentSystem }:
with import ../lib/testing.nix { inherit system; };
with import ../lib/qemu-flags.nix;
with pkgs.lib;
let

View file

@ -1,7 +1,6 @@
{ system ? builtins.currentSystem }:
with import ../../lib/testing.nix { inherit system; };
with import ../../lib/qemu-flags.nix;
with pkgs.lib;
let

View file

@ -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)

View 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 ]");
'';
})

View file

@ -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 // {

View 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
View 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
View 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");
'';
})

View file

@ -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
View 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");
'';
})

View 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 ];
};
}

View 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