mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-12 05:16:25 +03:00
Merge remote-tracking branch 'origin/master' into nix-2.0
This commit is contained in:
commit
d12c9911df
1451 changed files with 38300 additions and 19401 deletions
|
@ -334,14 +334,10 @@ navigate there.
|
||||||
|
|
||||||
Finally, you can run
|
Finally, you can run
|
||||||
```shell
|
```shell
|
||||||
hoogle server -p 8080
|
hoogle server -p 8080 --local
|
||||||
```
|
```
|
||||||
and navigate to http://localhost:8080/ for your own local
|
and navigate to http://localhost:8080/ for your own local
|
||||||
[Hoogle](https://www.haskell.org/hoogle/). Note, however, that Firefox and
|
[Hoogle](https://www.haskell.org/hoogle/).
|
||||||
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.
|
|
||||||
|
|
||||||
### How to build a Haskell project using Stack
|
### How to build a Haskell project using Stack
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@ To install crates with nix there is also an experimental project called
|
||||||
|
|
||||||
## Compiling Rust crates using Nix instead of Cargo
|
## Compiling Rust crates using Nix instead of Cargo
|
||||||
|
|
||||||
|
### Simple operation
|
||||||
|
|
||||||
When run, `cargo build` produces a file called `Cargo.lock`,
|
When run, `cargo build` produces a file called `Cargo.lock`,
|
||||||
containing pinned versions of all dependencies. Nixpkgs contains a
|
containing pinned versions of all dependencies. Nixpkgs contains a
|
||||||
tool called `carnix` (`nix-env -iA nixos.carnix`), which can be used
|
tool called `carnix` (`nix-env -iA nixos.carnix`), which can be used
|
||||||
|
@ -153,6 +155,8 @@ Here, the `libc` crate has no `src` attribute, so `buildRustCrate`
|
||||||
will fetch it from [crates.io](https://crates.io). A `sha256`
|
will fetch it from [crates.io](https://crates.io). A `sha256`
|
||||||
attribute is still needed for Nix purity.
|
attribute is still needed for Nix purity.
|
||||||
|
|
||||||
|
### Handling external dependencies
|
||||||
|
|
||||||
Some crates require external libraries. For crates from
|
Some crates require external libraries. For crates from
|
||||||
[crates.io](https://crates.io), such libraries can be specified in
|
[crates.io](https://crates.io), such libraries can be specified in
|
||||||
`defaultCrateOverrides` package in nixpkgs itself.
|
`defaultCrateOverrides` package in nixpkgs itself.
|
||||||
|
@ -210,7 +214,10 @@ with import <nixpkgs> {};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Three more parameters can be overridden:
|
### Options and phases configuration
|
||||||
|
|
||||||
|
Actually, the overrides introduced in the previous section are more
|
||||||
|
general. A number of other parameters can be overridden:
|
||||||
|
|
||||||
- The version of rustc used to compile the crate:
|
- The version of rustc used to compile the crate:
|
||||||
|
|
||||||
|
@ -232,6 +239,30 @@ Three more parameters can be overridden:
|
||||||
(hello {}).override { verbose = false; };
|
(hello {}).override { verbose = false; };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Extra arguments to be passed to `rustc`:
|
||||||
|
|
||||||
|
```
|
||||||
|
(hello {}).override { extraRustcOpts = "-Z debuginfo=2"; };
|
||||||
|
```
|
||||||
|
|
||||||
|
- Phases, just like in any other derivation, can be specified using
|
||||||
|
the following attributes: `preUnpack`, `postUnpack`, `prePatch`,
|
||||||
|
`patches`, `postPatch`, `preConfigure` (in the case of a Rust crate,
|
||||||
|
this is run before calling the "build" script), `postConfigure`
|
||||||
|
(after the "build" script),`preBuild`, `postBuild`, `preInstall` and
|
||||||
|
`postInstall`. As an example, here is how to create a new module
|
||||||
|
before running the build script:
|
||||||
|
|
||||||
|
```
|
||||||
|
(hello {}).override {
|
||||||
|
preConfigure = ''
|
||||||
|
echo "pub const PATH=\"${hi.out}\";" >> src/path.rs"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
One can also supply features switches. For example, if we want to
|
One can also supply features switches. For example, if we want to
|
||||||
compile `diesel_cli` only with the `postgres` feature, and no default
|
compile `diesel_cli` only with the `postgres` feature, and no default
|
||||||
features, we would write:
|
features, we would write:
|
||||||
|
@ -243,7 +274,7 @@ features, we would write:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Where `diesel.nix` is the file generated by Carnix, as explained above.
|
||||||
|
|
||||||
## Using the Rust nightlies overlay
|
## Using the Rust nightlies overlay
|
||||||
|
|
||||||
|
|
|
@ -660,6 +660,32 @@ cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el
|
||||||
passing <command>-q</command> to the Emacs command.
|
passing <command>-q</command> to the Emacs command.
|
||||||
</para>
|
</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>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1802,6 +1802,20 @@ addEnvHooks "$hostOffset" myBashFunction
|
||||||
disabled or patched to work with PaX.</para></listitem>
|
disabled or patched to work with PaX.</para></listitem>
|
||||||
</varlistentry>
|
</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>
|
</variablelist>
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -56,7 +56,8 @@ let
|
||||||
replaceStrings seq stringLength sub substring tail;
|
replaceStrings seq stringLength sub substring tail;
|
||||||
inherit (trivial) id const concat or and boolToString mergeAttrs
|
inherit (trivial) id const concat or and boolToString mergeAttrs
|
||||||
flip mapNullable inNixShell min max importJSON warn info
|
flip mapNullable inNixShell min max importJSON warn info
|
||||||
nixpkgsVersion mod functionArgs setFunctionArgs isFunction;
|
nixpkgsVersion mod compare splitByAndCompare
|
||||||
|
functionArgs setFunctionArgs isFunction;
|
||||||
|
|
||||||
inherit (fixedPoints) fix fix' extends composeExtensions
|
inherit (fixedPoints) fix fix' extends composeExtensions
|
||||||
makeExtensible makeExtensibleWithCustomName;
|
makeExtensible makeExtensibleWithCustomName;
|
||||||
|
@ -71,8 +72,8 @@ let
|
||||||
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
|
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
|
||||||
concatMap flatten remove findSingle findFirst any all count
|
concatMap flatten remove findSingle findFirst any all count
|
||||||
optional optionals toList range partition zipListsWith zipLists
|
optional optionals toList range partition zipListsWith zipLists
|
||||||
reverseList listDfs toposort sort take drop sublist last init
|
reverseList listDfs toposort sort compareLists take drop sublist
|
||||||
crossLists unique intersectLists subtractLists
|
last init crossLists unique intersectLists subtractLists
|
||||||
mutuallyExclusive;
|
mutuallyExclusive;
|
||||||
inherit (strings) concatStrings concatMapStrings concatImapStrings
|
inherit (strings) concatStrings concatMapStrings concatImapStrings
|
||||||
intersperse concatStringsSep concatMapStringsSep
|
intersperse concatStringsSep concatMapStringsSep
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
let
|
let
|
||||||
|
|
||||||
spdx = lic: lic // {
|
spdx = lic: lic // {
|
||||||
url = "http://spdx.org/licenses/${lic.spdxId}";
|
url = "http://spdx.org/licenses/${lic.spdxId}.html";
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
|
@ -79,6 +79,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||||
fullName = ''Beerware License'';
|
fullName = ''Beerware License'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bsd0 = spdx {
|
||||||
|
spdxId = "0BSD";
|
||||||
|
fullName = "BSD Zero Clause License";
|
||||||
|
};
|
||||||
|
|
||||||
bsd2 = spdx {
|
bsd2 = spdx {
|
||||||
spdxId = "BSD-2-Clause";
|
spdxId = "BSD-2-Clause";
|
||||||
fullName = ''BSD 2-clause "Simplified" License'';
|
fullName = ''BSD 2-clause "Simplified" License'';
|
||||||
|
@ -94,6 +99,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||||
fullName = ''BSD 4-clause "Original" or "Old" License'';
|
fullName = ''BSD 4-clause "Original" or "Old" License'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clArtistic = spdx {
|
||||||
|
spdxId = "ClArtistic";
|
||||||
|
fullName = "Clarified Artistic License";
|
||||||
|
};
|
||||||
|
|
||||||
cc0 = spdx {
|
cc0 = spdx {
|
||||||
spdxId = "CC0-1.0";
|
spdxId = "CC0-1.0";
|
||||||
fullName = "Creative Commons Zero v1.0 Universal";
|
fullName = "Creative Commons Zero v1.0 Universal";
|
||||||
|
@ -482,6 +492,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||||
fullName = "PostgreSQL License";
|
fullName = "PostgreSQL License";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
postman = {
|
||||||
|
fullName = "Postman EULA";
|
||||||
|
url = https://www.getpostman.com/licenses/postman_base_app;
|
||||||
|
free = false;
|
||||||
|
};
|
||||||
|
|
||||||
psfl = spdx {
|
psfl = spdx {
|
||||||
spdxId = "Python-2.0";
|
spdxId = "Python-2.0";
|
||||||
fullName = "Python Software Foundation License version 2";
|
fullName = "Python Software Foundation License version 2";
|
||||||
|
@ -569,6 +585,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||||
fullName = "Vovida Software License v1.0";
|
fullName = "Vovida Software License v1.0";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watcom = spdx {
|
||||||
|
spdxId = "Watcom-1.0";
|
||||||
|
fullName = "Sybase Open Watcom Public License 1.0";
|
||||||
|
};
|
||||||
|
|
||||||
w3c = spdx {
|
w3c = spdx {
|
||||||
spdxId = "W3C";
|
spdxId = "W3C";
|
||||||
fullName = "W3C Software Notice and License";
|
fullName = "W3C Software Notice and License";
|
||||||
|
@ -603,5 +624,4 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
|
||||||
spdxId = "ZPL-2.1";
|
spdxId = "ZPL-2.1";
|
||||||
fullName = "Zope Public License 2.1";
|
fullName = "Zope Public License 2.1";
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,6 +385,30 @@ rec {
|
||||||
if len < 2 then list
|
if len < 2 then list
|
||||||
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
|
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.
|
/* Return the first (at most) N elements of a list.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -440,7 +464,11 @@ rec {
|
||||||
init = list: assert list != []; take (length list - 1) list;
|
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];
|
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
andir = "Andreas Rammhold <andreas@rammhold.de>";
|
andir = "Andreas Rammhold <andreas@rammhold.de>";
|
||||||
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
|
andres = "Andres Loeh <ksnixos@andres-loeh.de>";
|
||||||
andrestylianos = "Andre S. Ramos <andre.stylianos@gmail.com>";
|
andrestylianos = "Andre S. Ramos <andre.stylianos@gmail.com>";
|
||||||
|
andrew-d = "Andrew Dunham <andrew@du.nham.ca>";
|
||||||
andrewrk = "Andrew Kelley <superjoe30@gmail.com>";
|
andrewrk = "Andrew Kelley <superjoe30@gmail.com>";
|
||||||
andsild = "Anders Sildnes <andsild@gmail.com>";
|
andsild = "Anders Sildnes <andsild@gmail.com>";
|
||||||
aneeshusa = "Aneesh Agrawal <aneeshusa@gmail.com>";
|
aneeshusa = "Aneesh Agrawal <aneeshusa@gmail.com>";
|
||||||
|
@ -225,6 +226,7 @@
|
||||||
ertes = "Ertugrul Söylemez <esz@posteo.de>";
|
ertes = "Ertugrul Söylemez <esz@posteo.de>";
|
||||||
ethercrow = "Dmitry Ivanov <ethercrow@gmail.com>";
|
ethercrow = "Dmitry Ivanov <ethercrow@gmail.com>";
|
||||||
etu = "Elis Hirwing <elis@hirwing.se>";
|
etu = "Elis Hirwing <elis@hirwing.se>";
|
||||||
|
exfalso = "Andras Slemmer <0slemi0@gmail.com>";
|
||||||
exi = "Reno Reckling <nixos@reckling.org>";
|
exi = "Reno Reckling <nixos@reckling.org>";
|
||||||
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
exlevan = "Alexey Levan <exlevan@gmail.com>";
|
||||||
expipiplus1 = "Joe Hermaszewski <nix@monoid.al>";
|
expipiplus1 = "Joe Hermaszewski <nix@monoid.al>";
|
||||||
|
@ -258,6 +260,7 @@
|
||||||
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
|
||||||
gebner = "Gabriel Ebner <gebner@gebner.org>";
|
gebner = "Gabriel Ebner <gebner@gebner.org>";
|
||||||
geistesk = "Alvar Penning <post@0x21.biz>";
|
geistesk = "Alvar Penning <post@0x21.biz>";
|
||||||
|
genesis = "Ronan Bignaux <ronan@aimao.org>";
|
||||||
georgewhewell = "George Whewell <georgerw@gmail.com>";
|
georgewhewell = "George Whewell <georgerw@gmail.com>";
|
||||||
gilligan = "Tobias Pflug <tobias.pflug@gmail.com>";
|
gilligan = "Tobias Pflug <tobias.pflug@gmail.com>";
|
||||||
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
|
||||||
|
@ -324,6 +327,7 @@
|
||||||
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
|
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
|
||||||
jlesquembre = "José Luis Lafuente <jl@lafuente.me>";
|
jlesquembre = "José Luis Lafuente <jl@lafuente.me>";
|
||||||
jluttine = "Jaakko Luttinen <jaakko.luttinen@iki.fi>";
|
jluttine = "Jaakko Luttinen <jaakko.luttinen@iki.fi>";
|
||||||
|
Jo = "Joachim Ernst <0x4A6F@shackspace.de>";
|
||||||
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
|
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
|
||||||
joamaki = "Jussi Maki <joamaki@gmail.com>";
|
joamaki = "Jussi Maki <joamaki@gmail.com>";
|
||||||
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
|
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
|
||||||
|
@ -366,6 +370,7 @@
|
||||||
kristoff3r = "Kristoffer Søholm <k.soeholm@gmail.com>";
|
kristoff3r = "Kristoffer Søholm <k.soeholm@gmail.com>";
|
||||||
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
|
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
|
||||||
kuznero = "Roman Kuznetsov <roman@kuznero.com>";
|
kuznero = "Roman Kuznetsov <roman@kuznero.com>";
|
||||||
|
lasandell = "Luke Sandell <lasandell@gmail.com>";
|
||||||
lassulus = "Lassulus <lassulus@gmail.com>";
|
lassulus = "Lassulus <lassulus@gmail.com>";
|
||||||
layus = "Guillaume Maudoux <layus.on@gmail.com>";
|
layus = "Guillaume Maudoux <layus.on@gmail.com>";
|
||||||
ldesgoui = "Lucas Desgouilles <ldesgoui@gmail.com>";
|
ldesgoui = "Lucas Desgouilles <ldesgoui@gmail.com>";
|
||||||
|
@ -380,6 +385,7 @@
|
||||||
lheckemann = "Linus Heckemann <git@sphalerite.org>";
|
lheckemann = "Linus Heckemann <git@sphalerite.org>";
|
||||||
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
|
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
|
||||||
lihop = "Leroy Hopson <nixos@leroy.geek.nz>";
|
lihop = "Leroy Hopson <nixos@leroy.geek.nz>";
|
||||||
|
limeytexan = "Michael Brantley <limeytexan@gmail.com>";
|
||||||
linquize = "Linquize <linquize@yahoo.com.hk>";
|
linquize = "Linquize <linquize@yahoo.com.hk>";
|
||||||
linus = "Linus Arver <linusarver@gmail.com>";
|
linus = "Linus Arver <linusarver@gmail.com>";
|
||||||
lluchs = "Lukas Werling <lukas.werling@gmail.com>";
|
lluchs = "Lukas Werling <lukas.werling@gmail.com>";
|
||||||
|
@ -447,6 +453,7 @@
|
||||||
mirrexagon = "Andrew Abbott <mirrexagon@mirrexagon.com>";
|
mirrexagon = "Andrew Abbott <mirrexagon@mirrexagon.com>";
|
||||||
mjanczyk = "Marcin Janczyk <m@dragonvr.pl>";
|
mjanczyk = "Marcin Janczyk <m@dragonvr.pl>";
|
||||||
mjp = "Mike Playle <mike@mythik.co.uk>"; # github = "MikePlayle";
|
mjp = "Mike Playle <mike@mythik.co.uk>"; # github = "MikePlayle";
|
||||||
|
mkg = "Mark K Gardner <mkg@vt.edu>";
|
||||||
mlieberman85 = "Michael Lieberman <mlieberman85@gmail.com>";
|
mlieberman85 = "Michael Lieberman <mlieberman85@gmail.com>";
|
||||||
mmahut = "Marek Mahut <marek.mahut@gmail.com>";
|
mmahut = "Marek Mahut <marek.mahut@gmail.com>";
|
||||||
moaxcp = "John Mercier <moaxcp@gmail.com>";
|
moaxcp = "John Mercier <moaxcp@gmail.com>";
|
||||||
|
@ -474,6 +481,7 @@
|
||||||
mudri = "James Wood <lamudri@gmail.com>";
|
mudri = "James Wood <lamudri@gmail.com>";
|
||||||
muflax = "Stefan Dorn <mail@muflax.com>";
|
muflax = "Stefan Dorn <mail@muflax.com>";
|
||||||
myrl = "Myrl Hex <myrl.0xf@gmail.com>";
|
myrl = "Myrl Hex <myrl.0xf@gmail.com>";
|
||||||
|
nadrieril = "Nadrieril Feneanar <nadrieril@gmail.com>";
|
||||||
namore = "Roman Naumann <namor@hemio.de>";
|
namore = "Roman Naumann <namor@hemio.de>";
|
||||||
nand0p = "Fernando Jose Pando <nando@hex7.com>";
|
nand0p = "Fernando Jose Pando <nando@hex7.com>";
|
||||||
Nate-Devv = "Nathan Moore <natedevv@gmail.com>";
|
Nate-Devv = "Nathan Moore <natedevv@gmail.com>";
|
||||||
|
@ -489,6 +497,8 @@
|
||||||
nicknovitski = "Nick Novitski <nixpkgs@nicknovitski.com>";
|
nicknovitski = "Nick Novitski <nixpkgs@nicknovitski.com>";
|
||||||
nico202 = "Nicolò Balzarotti <anothersms@gmail.com>";
|
nico202 = "Nicolò Balzarotti <anothersms@gmail.com>";
|
||||||
NikolaMandic = "Ratko Mladic <nikola@mandic.email>";
|
NikolaMandic = "Ratko Mladic <nikola@mandic.email>";
|
||||||
|
ninjatrappeur = "Félix Baylac-Jacqué <felix@alternativebit.fr>";
|
||||||
|
nipav = "Niko Pavlinek <niko.pavlinek@gmail.com>";
|
||||||
nixy = "Andrew R. M. <nixy@nixy.moe>";
|
nixy = "Andrew R. M. <nixy@nixy.moe>";
|
||||||
nmattia = "Nicolas Mattia <nicolas@nmattia.com>";
|
nmattia = "Nicolas Mattia <nicolas@nmattia.com>";
|
||||||
nocoolnametom = "Tom Doggett <nocoolnametom@gmail.com>";
|
nocoolnametom = "Tom Doggett <nocoolnametom@gmail.com>";
|
||||||
|
@ -549,7 +559,7 @@
|
||||||
pradeepchhetri = "Pradeep Chhetri <pradeep.chhetri89@gmail.com>";
|
pradeepchhetri = "Pradeep Chhetri <pradeep.chhetri89@gmail.com>";
|
||||||
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
|
||||||
primeos = "Michael Weiss <dev.primeos@gmail.com>";
|
primeos = "Michael Weiss <dev.primeos@gmail.com>";
|
||||||
profpatsch = "Profpatsch <mail@profpatsch.de>";
|
Profpatsch = "Profpatsch <mail@profpatsch.de>";
|
||||||
proglodyte = "Proglodyte <proglodyte23@gmail.com>";
|
proglodyte = "Proglodyte <proglodyte23@gmail.com>";
|
||||||
pshendry = "Paul Hendry <paul@pshendry.com>";
|
pshendry = "Paul Hendry <paul@pshendry.com>";
|
||||||
psibi = "Sibi <sibi@psibi.in>";
|
psibi = "Sibi <sibi@psibi.in>";
|
||||||
|
@ -656,15 +666,18 @@
|
||||||
sternenseemann = "Lukas Epple <post@lukasepple.de>";
|
sternenseemann = "Lukas Epple <post@lukasepple.de>";
|
||||||
stesie = "Stefan Siegl <stesie@brokenpipe.de>";
|
stesie = "Stefan Siegl <stesie@brokenpipe.de>";
|
||||||
steveej = "Stefan Junker <mail@stefanjunker.de>";
|
steveej = "Stefan Junker <mail@stefanjunker.de>";
|
||||||
|
StijnDW = "Stijn DW <stekke@airmail.cc>";
|
||||||
StillerHarpo = "Florian Engel <florianengel39@gmail.com>";
|
StillerHarpo = "Florian Engel <florianengel39@gmail.com>";
|
||||||
stumoss = "Stuart Moss <samoss@gmail.com>";
|
stumoss = "Stuart Moss <samoss@gmail.com>";
|
||||||
SuprDewd = "Bjarki Ágúst Guðmundsson <suprdewd@gmail.com>";
|
SuprDewd = "Bjarki Ágúst Guðmundsson <suprdewd@gmail.com>";
|
||||||
|
suvash = "Suvash Thapaliya <suvash+nixpkgs@gmail.com>";
|
||||||
swarren83 = "Shawn Warren <shawn.w.warren@gmail.com>";
|
swarren83 = "Shawn Warren <shawn.w.warren@gmail.com>";
|
||||||
swflint = "Samuel W. Flint <swflint@flintfam.org>";
|
swflint = "Samuel W. Flint <swflint@flintfam.org>";
|
||||||
swistak35 = "Rafał Łasocha <me@swistak35.com>";
|
swistak35 = "Rafał Łasocha <me@swistak35.com>";
|
||||||
symphorien = "Guillaume Girol <symphorien_nixpkgs@xlumurb.eu>";
|
symphorien = "Guillaume Girol <symphorien_nixpkgs@xlumurb.eu>";
|
||||||
szczyp = "Szczyp <qb@szczyp.com>";
|
szczyp = "Szczyp <qb@szczyp.com>";
|
||||||
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
|
||||||
|
tadfisher = "Tad Fisher <tadfisher@gmail.com>";
|
||||||
taeer = "Taeer Bar-Yam <taeer@necsi.edu>";
|
taeer = "Taeer Bar-Yam <taeer@necsi.edu>";
|
||||||
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
tailhook = "Paul Colomiets <paul@colomiets.name>";
|
||||||
taketwo = "Sergey Alexandrov <alexandrov88@gmail.com>";
|
taketwo = "Sergey Alexandrov <alexandrov88@gmail.com>";
|
||||||
|
@ -697,6 +710,7 @@
|
||||||
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
|
||||||
tomsmeets = "Tom Smeets <tom@tsmeets.nl>";
|
tomsmeets = "Tom Smeets <tom@tsmeets.nl>";
|
||||||
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
|
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
|
||||||
|
treemo = "Matthieu Chevrier <matthieu.chevrier@treemo.fr>";
|
||||||
trevorj = "Trevor Joynson <nix@trevor.joynson.io>";
|
trevorj = "Trevor Joynson <nix@trevor.joynson.io>";
|
||||||
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
|
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
|
||||||
tstrobel = "Thomas Strobel <4ZKTUB6TEP74PYJOPWIR013S2AV29YUBW5F9ZH2F4D5UMJUJ6S@hash.domains>";
|
tstrobel = "Thomas Strobel <4ZKTUB6TEP74PYJOPWIR013S2AV29YUBW5F9ZH2F4D5UMJUJ6S@hash.domains>";
|
||||||
|
@ -711,11 +725,13 @@
|
||||||
utdemir = "Utku Demir <me@utdemir.com>";
|
utdemir = "Utku Demir <me@utdemir.com>";
|
||||||
#urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012
|
#urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012
|
||||||
uwap = "uwap <me@uwap.name>";
|
uwap = "uwap <me@uwap.name>";
|
||||||
|
va1entin = "Valentin Heidelberger <github@valentinsblog.com>";
|
||||||
vaibhavsagar = "Vaibhav Sagar <vaibhavsagar@gmail.com>";
|
vaibhavsagar = "Vaibhav Sagar <vaibhavsagar@gmail.com>";
|
||||||
valeriangalliat = "Valérian Galliat <val@codejam.info>";
|
valeriangalliat = "Valérian Galliat <val@codejam.info>";
|
||||||
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
|
||||||
vanschelven = "Klaas van Schelven <klaas@vanschelven.com>";
|
vanschelven = "Klaas van Schelven <klaas@vanschelven.com>";
|
||||||
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
|
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
|
||||||
|
varunpatro = "Varun Patro <varun.kumar.patro@gmail.com>";
|
||||||
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
|
||||||
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
|
||||||
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
vcunat = "Vladimír Čunát <vcunat@gmail.com>";
|
||||||
|
@ -749,6 +765,7 @@
|
||||||
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
wscott = "Wayne Scott <wsc9tt@gmail.com>";
|
||||||
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
wyvie = "Elijah Rum <elijahrum@gmail.com>";
|
||||||
xaverdh = "Dominik Xaver Hörl <hoe.dom@gmx.de>";
|
xaverdh = "Dominik Xaver Hörl <hoe.dom@gmx.de>";
|
||||||
|
xeji = "xeji <xeji@cat3.de>";
|
||||||
xnwdd = "Guillermo NWDD <nwdd+nixos@no.team>";
|
xnwdd = "Guillermo NWDD <nwdd+nixos@no.team>";
|
||||||
xurei = "Olivier Bourdoux <olivier.bourdoux@gmail.com>";
|
xurei = "Olivier Bourdoux <olivier.bourdoux@gmail.com>";
|
||||||
xvapx = "Marti Serra <marti.serra.coscollano@gmail.com>";
|
xvapx = "Marti Serra <marti.serra.coscollano@gmail.com>";
|
||||||
|
@ -757,6 +774,7 @@
|
||||||
y0no = "Yoann Ono <y0no@y0no.fr>";
|
y0no = "Yoann Ono <y0no@y0no.fr>";
|
||||||
yarr = "Dmitry V. <savraz@gmail.com>";
|
yarr = "Dmitry V. <savraz@gmail.com>";
|
||||||
yegortimoshenko = "Yegor Timoshenko <yegortimoshenko@gmail.com>";
|
yegortimoshenko = "Yegor Timoshenko <yegortimoshenko@gmail.com>";
|
||||||
|
yesbox = "Jesper Geertsen Jonsson <jesper.geertsen.jonsson@gmail.com>";
|
||||||
ylwghst = "Burim Augustin Berisa <ylwghst@onionmail.info>";
|
ylwghst = "Burim Augustin Berisa <ylwghst@onionmail.info>";
|
||||||
yochai = "Yochai <yochai@titat.info>";
|
yochai = "Yochai <yochai@titat.info>";
|
||||||
yorickvp = "Yorick van Pelt <yorickvanpelt@gmail.com>";
|
yorickvp = "Yorick van Pelt <yorickvanpelt@gmail.com>";
|
||||||
|
|
|
@ -14,6 +14,7 @@ rec {
|
||||||
, defaultText ? null # Textual representation of the default, for in the manual.
|
, defaultText ? null # Textual representation of the default, for in the manual.
|
||||||
, example ? null # Example value used in the manual.
|
, example ? null # Example value used in the manual.
|
||||||
, description ? null # String describing the option.
|
, 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.
|
, type ? null # Option type, providing type-checking and value merging.
|
||||||
, apply ? null # Function that converts the option value to something else.
|
, apply ? null # Function that converts the option value to something else.
|
||||||
, internal ? null # Whether the option is for NixOS developers only.
|
, internal ? null # Whether the option is for NixOS developers only.
|
||||||
|
@ -76,7 +77,6 @@ rec {
|
||||||
getValues = map (x: x.value);
|
getValues = map (x: x.value);
|
||||||
getFiles = map (x: x.file);
|
getFiles = map (x: x.file);
|
||||||
|
|
||||||
|
|
||||||
# Generate documentation template from the list of option declaration like
|
# Generate documentation template from the list of option declaration like
|
||||||
# the set generated with filterOptionSets.
|
# the set generated with filterOptionSets.
|
||||||
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
optionAttrSetToDocList = optionAttrSetToDocList' [];
|
||||||
|
@ -85,6 +85,7 @@ rec {
|
||||||
concatMap (opt:
|
concatMap (opt:
|
||||||
let
|
let
|
||||||
docOption = rec {
|
docOption = rec {
|
||||||
|
loc = opt.loc;
|
||||||
name = showOption opt.loc;
|
name = showOption opt.loc;
|
||||||
description = opt.description or (throw "Option `${name}' has no description.");
|
description = opt.description or (throw "Option `${name}' has no description.");
|
||||||
declarations = filter (x: x != unknownModule) opt.declarations;
|
declarations = filter (x: x != unknownModule) opt.declarations;
|
||||||
|
@ -93,9 +94,10 @@ rec {
|
||||||
readOnly = opt.readOnly or false;
|
readOnly = opt.readOnly or false;
|
||||||
type = opt.type.description or null;
|
type = opt.type.description or null;
|
||||||
}
|
}
|
||||||
// (if opt ? example then { example = scrubOptionValue opt.example; } else {})
|
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; }
|
||||||
// (if opt ? default then { default = scrubOptionValue opt.default; } else {})
|
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; }
|
||||||
// (if opt ? defaultText then { default = opt.defaultText; } else {});
|
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; }
|
||||||
|
// optionalAttrs (opt ? relatedPackages && opt.relatedPackages != null) { inherit (opt) relatedPackages; };
|
||||||
|
|
||||||
subOptions =
|
subOptions =
|
||||||
let ss = opt.type.getSubOptions opt.loc;
|
let ss = opt.type.getSubOptions opt.loc;
|
||||||
|
|
|
@ -26,7 +26,8 @@ rec {
|
||||||
libc =
|
libc =
|
||||||
/**/ if final.isDarwin then "libSystem"
|
/**/ if final.isDarwin then "libSystem"
|
||||||
else if final.isMinGW then "msvcrt"
|
else if final.isMinGW then "msvcrt"
|
||||||
else if final.isLinux then "glibc"
|
else if final.isMusl then "musl"
|
||||||
|
else if final.isLinux /* default */ then "glibc"
|
||||||
# TODO(@Ericson2314) think more about other operating systems
|
# TODO(@Ericson2314) think more about other operating systems
|
||||||
else "native/impure";
|
else "native/impure";
|
||||||
extensions = {
|
extensions = {
|
||||||
|
|
|
@ -13,7 +13,6 @@ rec {
|
||||||
config = "armv5tel-unknown-linux-gnueabi";
|
config = "armv5tel-unknown-linux-gnueabi";
|
||||||
arch = "armv5tel";
|
arch = "armv5tel";
|
||||||
float = "soft";
|
float = "soft";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.sheevaplug;
|
platform = platforms.sheevaplug;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,7 +21,6 @@ rec {
|
||||||
arch = "armv6l";
|
arch = "armv6l";
|
||||||
float = "hard";
|
float = "hard";
|
||||||
fpu = "vfp";
|
fpu = "vfp";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.raspberrypi;
|
platform = platforms.raspberrypi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,14 +29,12 @@ rec {
|
||||||
arch = "armv7-a";
|
arch = "armv7-a";
|
||||||
float = "hard";
|
float = "hard";
|
||||||
fpu = "vfpv3-d16";
|
fpu = "vfpv3-d16";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.armv7l-hf-multiplatform;
|
platform = platforms.armv7l-hf-multiplatform;
|
||||||
};
|
};
|
||||||
|
|
||||||
aarch64-multiplatform = rec {
|
aarch64-multiplatform = rec {
|
||||||
config = "aarch64-unknown-linux-gnu";
|
config = "aarch64-unknown-linux-gnu";
|
||||||
arch = "aarch64";
|
arch = "aarch64";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.aarch64-multiplatform;
|
platform = platforms.aarch64-multiplatform;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +47,6 @@ rec {
|
||||||
arch = "armv5tel";
|
arch = "armv5tel";
|
||||||
config = "armv5tel-unknown-linux-gnueabi";
|
config = "armv5tel-unknown-linux-gnueabi";
|
||||||
float = "soft";
|
float = "soft";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.pogoplug4;
|
platform = platforms.pogoplug4;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,10 +54,28 @@ rec {
|
||||||
config = "mips64el-unknown-linux-gnu";
|
config = "mips64el-unknown-linux-gnu";
|
||||||
arch = "mips";
|
arch = "mips";
|
||||||
float = "hard";
|
float = "hard";
|
||||||
libc = "glibc";
|
|
||||||
platform = platforms.fuloong2f_n32;
|
platform = platforms.fuloong2f_n32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
muslpi = raspberryPi // {
|
||||||
|
config = "armv6l-unknown-linux-musleabihf";
|
||||||
|
};
|
||||||
|
|
||||||
|
aarch64-multiplatform-musl = aarch64-multiplatform // {
|
||||||
|
config = "aarch64-unknown-linux-musl";
|
||||||
|
};
|
||||||
|
|
||||||
|
musl64 = { config = "x86_64-unknown-linux-musl"; };
|
||||||
|
musl32 = { config = "i686-unknown-linux-musl"; };
|
||||||
|
|
||||||
|
riscv = bits: {
|
||||||
|
config = "riscv${bits}-unknown-linux-gnu";
|
||||||
|
platform = platforms.riscv-multiplatform bits;
|
||||||
|
};
|
||||||
|
riscv64 = riscv "64";
|
||||||
|
riscv32 = riscv "32";
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Darwin
|
# Darwin
|
||||||
#
|
#
|
||||||
|
|
|
@ -33,6 +33,8 @@ rec {
|
||||||
Windows = { kernel = kernels.windows; };
|
Windows = { kernel = kernels.windows; };
|
||||||
Cygwin = { kernel = kernels.windows; abi = abis.cygnus; };
|
Cygwin = { kernel = kernels.windows; abi = abis.cygnus; };
|
||||||
MinGW = { kernel = kernels.windows; abi = abis.gnu; };
|
MinGW = { kernel = kernels.windows; abi = abis.gnu; };
|
||||||
|
|
||||||
|
Musl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
|
||||||
};
|
};
|
||||||
|
|
||||||
matchAnyAttrs = patterns:
|
matchAnyAttrs = patterns:
|
||||||
|
|
|
@ -180,6 +180,9 @@ rec {
|
||||||
androideabi = {};
|
androideabi = {};
|
||||||
gnueabi = {};
|
gnueabi = {};
|
||||||
gnueabihf = {};
|
gnueabihf = {};
|
||||||
|
musleabi = {};
|
||||||
|
musleabihf = {};
|
||||||
|
musl = {};
|
||||||
|
|
||||||
unknown = {};
|
unknown = {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
rec {
|
rec {
|
||||||
pcBase = {
|
pcBase = {
|
||||||
name = "pc";
|
name = "pc";
|
||||||
kernelHeadersBaseConfig = "defconfig";
|
|
||||||
kernelBaseConfig = "defconfig";
|
kernelBaseConfig = "defconfig";
|
||||||
# Build whatever possible as a module, if not stated in the extra config.
|
# Build whatever possible as a module, if not stated in the extra config.
|
||||||
kernelAutoModules = true;
|
kernelAutoModules = true;
|
||||||
|
@ -30,7 +29,6 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
kernelMajor = "2.6";
|
kernelMajor = "2.6";
|
||||||
kernelHeadersBaseConfig = "multi_v5_defconfig";
|
|
||||||
kernelBaseConfig = "multi_v5_defconfig";
|
kernelBaseConfig = "multi_v5_defconfig";
|
||||||
kernelArch = "arm";
|
kernelArch = "arm";
|
||||||
kernelAutoModules = false;
|
kernelAutoModules = false;
|
||||||
|
@ -54,7 +52,6 @@ rec {
|
||||||
sheevaplug = {
|
sheevaplug = {
|
||||||
name = "sheevaplug";
|
name = "sheevaplug";
|
||||||
kernelMajor = "2.6";
|
kernelMajor = "2.6";
|
||||||
kernelHeadersBaseConfig = "multi_v5_defconfig";
|
|
||||||
kernelBaseConfig = "multi_v5_defconfig";
|
kernelBaseConfig = "multi_v5_defconfig";
|
||||||
kernelArch = "arm";
|
kernelArch = "arm";
|
||||||
kernelAutoModules = false;
|
kernelAutoModules = false;
|
||||||
|
@ -168,7 +165,6 @@ rec {
|
||||||
raspberrypi = {
|
raspberrypi = {
|
||||||
name = "raspberrypi";
|
name = "raspberrypi";
|
||||||
kernelMajor = "2.6";
|
kernelMajor = "2.6";
|
||||||
kernelHeadersBaseConfig = "bcm2835_defconfig";
|
|
||||||
kernelBaseConfig = "bcmrpi_defconfig";
|
kernelBaseConfig = "bcmrpi_defconfig";
|
||||||
kernelDTB = true;
|
kernelDTB = true;
|
||||||
kernelArch = "arm";
|
kernelArch = "arm";
|
||||||
|
@ -347,7 +343,6 @@ rec {
|
||||||
utilite = {
|
utilite = {
|
||||||
name = "utilite";
|
name = "utilite";
|
||||||
kernelMajor = "2.6";
|
kernelMajor = "2.6";
|
||||||
kernelHeadersBaseConfig = "multi_v7_defconfig";
|
|
||||||
kernelBaseConfig = "multi_v7_defconfig";
|
kernelBaseConfig = "multi_v7_defconfig";
|
||||||
kernelArch = "arm";
|
kernelArch = "arm";
|
||||||
kernelAutoModules = false;
|
kernelAutoModules = false;
|
||||||
|
@ -379,13 +374,11 @@ rec {
|
||||||
# patch.
|
# patch.
|
||||||
|
|
||||||
kernelBaseConfig = "guruplug_defconfig";
|
kernelBaseConfig = "guruplug_defconfig";
|
||||||
#kernelHeadersBaseConfig = "guruplug_defconfig";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fuloong2f_n32 = {
|
fuloong2f_n32 = {
|
||||||
name = "fuloong2f_n32";
|
name = "fuloong2f_n32";
|
||||||
kernelMajor = "2.6";
|
kernelMajor = "2.6";
|
||||||
kernelHeadersBaseConfig = "fuloong2e_defconfig";
|
|
||||||
kernelBaseConfig = "lemote2f_defconfig";
|
kernelBaseConfig = "lemote2f_defconfig";
|
||||||
kernelArch = "mips";
|
kernelArch = "mips";
|
||||||
kernelAutoModules = false;
|
kernelAutoModules = false;
|
||||||
|
@ -471,7 +464,6 @@ rec {
|
||||||
armv7l-hf-multiplatform = {
|
armv7l-hf-multiplatform = {
|
||||||
name = "armv7l-hf-multiplatform";
|
name = "armv7l-hf-multiplatform";
|
||||||
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
|
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
|
||||||
kernelHeadersBaseConfig = "multi_v7_defconfig";
|
|
||||||
kernelBaseConfig = "multi_v7_defconfig";
|
kernelBaseConfig = "multi_v7_defconfig";
|
||||||
kernelArch = "arm";
|
kernelArch = "arm";
|
||||||
kernelDTB = true;
|
kernelDTB = true;
|
||||||
|
@ -479,6 +471,11 @@ rec {
|
||||||
kernelPreferBuiltin = true;
|
kernelPreferBuiltin = true;
|
||||||
kernelTarget = "zImage";
|
kernelTarget = "zImage";
|
||||||
kernelExtraConfig = ''
|
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.
|
# Fix broken sunxi-sid nvmem driver.
|
||||||
TI_CPTS y
|
TI_CPTS y
|
||||||
|
|
||||||
|
@ -512,7 +509,6 @@ rec {
|
||||||
aarch64-multiplatform = {
|
aarch64-multiplatform = {
|
||||||
name = "aarch64-multiplatform";
|
name = "aarch64-multiplatform";
|
||||||
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
|
kernelMajor = "2.6"; # Using "2.6" enables 2.6 kernel syscalls in glibc.
|
||||||
kernelHeadersBaseConfig = "defconfig";
|
|
||||||
kernelBaseConfig = "defconfig";
|
kernelBaseConfig = "defconfig";
|
||||||
kernelArch = "arm64";
|
kernelArch = "arm64";
|
||||||
kernelDTB = true;
|
kernelDTB = true;
|
||||||
|
@ -545,6 +541,19 @@ rec {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
riscv-multiplatform = bits: {
|
||||||
|
name = "riscv-multiplatform";
|
||||||
|
kernelArch = "riscv";
|
||||||
|
bfdEmulation = "elf${bits}lriscv";
|
||||||
|
kernelTarget = "vmlinux";
|
||||||
|
kernelAutoModules = true;
|
||||||
|
kernelBaseConfig = "defconfig";
|
||||||
|
kernelExtraConfig = ''
|
||||||
|
FTRACE n
|
||||||
|
SERIAL_OF_PLATFORM y
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
selectBySystem = system: {
|
selectBySystem = system: {
|
||||||
"i686-linux" = pc32;
|
"i686-linux" = pc32;
|
||||||
"x86_64-linux" = pc64;
|
"x86_64-linux" = pc64;
|
||||||
|
|
|
@ -81,6 +81,42 @@ rec {
|
||||||
*/
|
*/
|
||||||
mod = base: int: base - (int * (builtins.div base int));
|
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. */
|
/* Reads a JSON file. */
|
||||||
importJSON = path:
|
importJSON = path:
|
||||||
builtins.fromJSON (builtins.readFile path);
|
builtins.fromJSON (builtins.readFile path);
|
||||||
|
|
|
@ -256,6 +256,10 @@ rec {
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
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 {
|
attrsOf = elemType: mkOptionType rec {
|
||||||
name = "attrsOf";
|
name = "attrsOf";
|
||||||
description = "attribute set of ${elemType.description}s";
|
description = "attribute set of ${elemType.description}s";
|
||||||
|
|
|
@ -9,8 +9,6 @@ let
|
||||||
modules = [ configuration ];
|
modules = [ configuration ];
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit (eval) pkgs;
|
|
||||||
|
|
||||||
# This is for `nixos-rebuild build-vm'.
|
# This is for `nixos-rebuild build-vm'.
|
||||||
vmConfig = (import ./lib/eval-config.nix {
|
vmConfig = (import ./lib/eval-config.nix {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
@ -30,7 +28,7 @@ let
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
inherit (eval) config options;
|
inherit (eval) pkgs config options;
|
||||||
|
|
||||||
system = eval.config.system.build.toplevel;
|
system = eval.config.system.build.toplevel;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ interfaces. However, you can configure an interface manually as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
|
networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
Typically you’ll also want to set a default gateway and set of name
|
Typically you’ll also want to set a default gateway and set of name
|
||||||
|
|
|
@ -26,7 +26,7 @@ boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
|
||||||
DHCPv6. You can configure an interface manually:
|
DHCPv6. You can configure an interface manually:
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ];
|
networking.interfaces.eth0.ipv6.addresses = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ];
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|
|
@ -36,17 +36,6 @@ services.compton = {
|
||||||
<literal>environment.systemPackages</literal>.
|
<literal>environment.systemPackages</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
NixOS’s default <emphasis>display manager</emphasis> is SLiM.
|
|
||||||
(DM is the program that provides a graphical login prompt
|
|
||||||
and manages the X server.)
|
|
||||||
You can, for example, select KDE’s
|
|
||||||
<command>sddm</command> instead:
|
|
||||||
<programlisting>
|
|
||||||
services.xserver.displayManager.sddm.enable = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<simplesect>
|
<simplesect>
|
||||||
<title>Thunar Volume Support</title>
|
<title>Thunar Volume Support</title>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ let
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
|
|
||||||
# Remove invisible and internal options.
|
# 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>
|
# Replace functions by the string <function>
|
||||||
substFunction = x:
|
substFunction = x:
|
||||||
|
@ -15,13 +15,43 @@ let
|
||||||
else if lib.isFunction x then "<function>"
|
else if lib.isFunction x then "<function>"
|
||||||
else x;
|
else x;
|
||||||
|
|
||||||
|
# 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.available) " <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.
|
# Clean up declaration sites to not refer to the NixOS source tree.
|
||||||
optionsList' = lib.flip map optionsList (opt: opt // {
|
|
||||||
declarations = map stripAnyPrefixes opt.declarations;
|
declarations = map stripAnyPrefixes opt.declarations;
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
|
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
|
||||||
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
|
// 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,
|
# We need to strip references to /nix/store/* from options,
|
||||||
# including any `extraSources` if some modules came from elsewhere,
|
# including any `extraSources` if some modules came from elsewhere,
|
||||||
|
@ -32,8 +62,21 @@ let
|
||||||
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
|
prefixesToStrip = map (p: "${toString p}/") ([ ../../.. ] ++ extraSources);
|
||||||
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
|
stripAnyPrefixes = lib.flip (lib.fold lib.removePrefix) prefixesToStrip;
|
||||||
|
|
||||||
|
# Custom "less" that pushes up all the things ending in ".enable*"
|
||||||
|
# and ".package*"
|
||||||
|
optionLess = a: b:
|
||||||
|
let
|
||||||
|
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 a.loc b.loc < 0;
|
||||||
|
|
||||||
|
# Customly sort option list for the man page.
|
||||||
|
optionsList = lib.sort optionLess optionsListDesc;
|
||||||
|
|
||||||
# Convert the list of options into an XML file.
|
# 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" {} ''
|
optionsDocBook = runCommand "options-db.xml" {} ''
|
||||||
optionsXML=${optionsXML}
|
optionsXML=${optionsXML}
|
||||||
|
@ -191,7 +234,7 @@ in rec {
|
||||||
mkdir -p $dst
|
mkdir -p $dst
|
||||||
|
|
||||||
cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
|
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
|
} $dst/options.json
|
||||||
|
|
||||||
mkdir -p $out/nix-support
|
mkdir -p $out/nix-support
|
||||||
|
|
|
@ -70,9 +70,21 @@ $ ./result/bin/run-*-vm
|
||||||
</screen>
|
</screen>
|
||||||
|
|
||||||
The VM does not have any data from your host system, so your existing
|
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
|
user accounts and home directories will not be available unless you
|
||||||
forward ports on the host to the guest. For instance, the following
|
have set <literal>mutableUsers = false</literal>. Another way is to
|
||||||
will forward host port 2222 to guest port 22 (SSH):
|
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>
|
<screen>
|
||||||
$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
|
$ QEMU_NET_OPTS="hostfwd=tcp::2222-:22" ./result/bin/run-*-vm
|
||||||
|
|
|
@ -275,11 +275,20 @@ Enter new UNIX password: ***
|
||||||
Retype new UNIX password: ***
|
Retype new UNIX password: ***
|
||||||
</screen>
|
</screen>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
To prevent the password prompt, set <code>users.mutableUsers = false;</code> in
|
||||||
|
<filename>configuration.nix</filename>, which allows unattended installation
|
||||||
|
necessary in automation.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem><para>If everything went well:
|
<listitem>
|
||||||
|
<para>If everything went well:
|
||||||
|
|
||||||
<screen>
|
<screen>
|
||||||
# reboot</screen>
|
# reboot</screen>
|
||||||
|
|
|
@ -70,6 +70,15 @@
|
||||||
</para>
|
</para>
|
||||||
</xsl:if>
|
</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">
|
<xsl:if test="count(attr[@name = 'declarations']/list/*) != 0">
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Declared by:</emphasis>
|
<emphasis>Declared by:</emphasis>
|
||||||
|
|
|
@ -38,6 +38,16 @@ has the following highlights: </para>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The GNOME version is now 3.26.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>PHP now defaults to PHP 7.2</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -133,6 +143,17 @@ following incompatible changes:</para>
|
||||||
<link xlink:href="https://search.nix.gsc.io/?q=stateVersion">here</link>.
|
<link xlink:href="https://search.nix.gsc.io/?q=stateVersion">here</link>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <literal>openssh</literal> package
|
||||||
|
now includes Kerberos support by default;
|
||||||
|
the <literal>openssh_with_kerberos</literal> package
|
||||||
|
is now a deprecated alias.
|
||||||
|
If you do not want Kerberos support,
|
||||||
|
you can do <literal>openssh.override { withKerboros = false; }</literal>.
|
||||||
|
Note, this also applies to the <literal>openssh_hpn</literal> package.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>cc-wrapper</literal> has been split in two; there is now also a <literal>bintools-wrapper</literal>.
|
<literal>cc-wrapper</literal> has been split in two; there is now also a <literal>bintools-wrapper</literal>.
|
||||||
|
@ -196,6 +217,28 @@ following incompatible changes:</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <literal>jid</literal> package has been removed, due to maintenance
|
||||||
|
overhead of a go package having non-versioned dependencies.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
When using <option>services.xserver.libinput</option> (enabled by default in GNOME),
|
||||||
|
it now handles all input devices, not just touchpads. As a result, you might need to
|
||||||
|
re-evaluate any custom Xorg configuration. In particular,
|
||||||
|
<literal>Option "XkbRules" "base"</literal> may result in broken keyboard layout.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <literal>attic</literal> package was removed. A maintained fork called
|
||||||
|
<link xlink:href="https://www.borgbackup.org/">Borg</link> should be used instead.
|
||||||
|
Migration instructions can be found
|
||||||
|
<link xlink:href="http://borgbackup.readthedocs.io/en/stable/usage/upgrade.html#attic-and-borg-0-xx-to-borg-1-x">here</link>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -226,10 +269,42 @@ following incompatible changes:</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The option <option>services.xserver.desktopManager.default</option> is now <literal>none</literal> by default.
|
In the module <option>networking.interfaces.<name></option> the
|
||||||
An assertion failure is thrown if WM's and DM's default are <literal>none</literal>.
|
following options have been removed:
|
||||||
To explicitly run a plain X session without and DM or WM, the newly introduced option <option>services.xserver.plainX</option>
|
<itemizedlist>
|
||||||
must be set to true.
|
<listitem>
|
||||||
|
<para><option>ipAddress</option></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><option>ipv6Address</option></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><option>prefixLength</option></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><option>ipv6PrefixLength</option></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para><option>subnetMask</option></para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
To assign static addresses to an interface the options
|
||||||
|
<option>ipv4.addresses</option> and <option>ipv6.addresses</option>
|
||||||
|
should be used instead.
|
||||||
|
The options <option>ip4</option> and <option>ip6</option> have been
|
||||||
|
renamed to <option>ipv4.addresses</option> <option>ipv6.addresses</option>
|
||||||
|
respectively.
|
||||||
|
The new options <option>ipv4.routes</option> and <option>ipv6.routes</option>
|
||||||
|
have been added to set up static routing.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The option <option>services.xserver.desktopManager.default</option> is now
|
||||||
|
<literal>none</literal> by default. An assertion failure is thrown if WM's
|
||||||
|
and DM's default are <literal>none</literal>.
|
||||||
|
To explicitly run a plain X session without and DM or WM, the newly
|
||||||
|
introduced option <option>services.xserver.plainX</option> must be set to true.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -51,7 +51,7 @@ rec {
|
||||||
let
|
let
|
||||||
interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255);
|
interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255);
|
||||||
interfaces = flip map interfacesNumbered ({ fst, snd }:
|
interfaces = flip map interfacesNumbered ({ fst, snd }:
|
||||||
nameValuePair "eth${toString snd}" { ip4 =
|
nameValuePair "eth${toString snd}" { ipv4.addresses =
|
||||||
[ { address = "192.168.${toString fst}.${toString m.snd}";
|
[ { address = "192.168.${toString fst}.${toString m.snd}";
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
} ];
|
} ];
|
||||||
|
@ -64,7 +64,7 @@ rec {
|
||||||
networking.interfaces = listToAttrs interfaces;
|
networking.interfaces = listToAttrs interfaces;
|
||||||
|
|
||||||
networking.primaryIPAddress =
|
networking.primaryIPAddress =
|
||||||
optionalString (interfaces != []) (head (head interfaces).value.ip4).address;
|
optionalString (interfaces != []) (head (head interfaces).value.ipv4.addresses).address;
|
||||||
|
|
||||||
# Put the IP addresses of all VMs in this machine's
|
# Put the IP addresses of all VMs in this machine's
|
||||||
# /etc/hosts file. If a machine has multiple
|
# /etc/hosts file. If a machine has multiple
|
||||||
|
|
|
@ -85,7 +85,7 @@ let format' = format; in let
|
||||||
nixpkgs = cleanSource pkgs.path;
|
nixpkgs = cleanSource pkgs.path;
|
||||||
|
|
||||||
# FIXME: merge with channel.nix / make-channel.nix.
|
# FIXME: merge with channel.nix / make-channel.nix.
|
||||||
channelSources = pkgs.runCommand "nixos-${config.system.nixosVersion}" {} ''
|
channelSources = pkgs.runCommand "nixos-${config.system.nixos.version}" {} ''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
cp -prd ${nixpkgs} $out/nixos
|
cp -prd ${nixpkgs} $out/nixos
|
||||||
chmod -R u+w $out/nixos
|
chmod -R u+w $out/nixos
|
||||||
|
@ -93,7 +93,7 @@ let format' = format; in let
|
||||||
ln -s . $out/nixos/nixpkgs
|
ln -s . $out/nixos/nixpkgs
|
||||||
fi
|
fi
|
||||||
rm -rf $out/nixos/.git
|
rm -rf $out/nixos/.git
|
||||||
echo -n ${config.system.nixosVersionSuffix} > $out/nixos/.version-suffix
|
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
binPath = with pkgs; makeBinPath (
|
binPath = with pkgs; makeBinPath (
|
||||||
|
|
|
@ -29,7 +29,7 @@ rec {
|
||||||
cp ${./test-driver/Logger.pm} $libDir/Logger.pm
|
cp ${./test-driver/Logger.pm} $libDir/Logger.pm
|
||||||
|
|
||||||
wrapProgram $out/bin/nixos-test-driver \
|
wrapProgram $out/bin/nixos-test-driver \
|
||||||
--prefix PATH : "${lib.makeBinPath [ qemu vde2 netpbm coreutils ]}" \
|
--prefix PATH : "${lib.makeBinPath [ qemu_test vde2 netpbm coreutils ]}" \
|
||||||
--prefix PERL5LIB : "${with perlPackages; lib.makePerlPath [ TermReadLineGnu XMLWriter IOTty FileSlurp ]}:$out/lib/perl5/site_perl"
|
--prefix PERL5LIB : "${with perlPackages; lib.makePerlPath [ TermReadLineGnu XMLWriter IOTty FileSlurp ]}:$out/lib/perl5/site_perl"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -78,7 +78,19 @@ rec {
|
||||||
} @ t:
|
} @ t:
|
||||||
|
|
||||||
let
|
let
|
||||||
testDriverName = "nixos-test-driver-${name}";
|
# A standard store path to the vm monitor is built like this:
|
||||||
|
# /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor
|
||||||
|
# The max filename length of a unix domain socket is 108 bytes.
|
||||||
|
# This means $name can at most be 50 bytes long.
|
||||||
|
maxTestNameLen = 50;
|
||||||
|
testNameLen = builtins.stringLength name;
|
||||||
|
|
||||||
|
testDriverName = with builtins;
|
||||||
|
if testNameLen > maxTestNameLen then
|
||||||
|
abort ("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " +
|
||||||
|
"it's currently ${toString testNameLen} characters long.")
|
||||||
|
else
|
||||||
|
"nixos-test-driver-${name}";
|
||||||
|
|
||||||
nodes = buildVirtualNetwork (
|
nodes = buildVirtualNetwork (
|
||||||
t.nodes or (if t ? machine then { machine = t.machine; } else { }));
|
t.nodes or (if t ? machine then { machine = t.machine; } else { }));
|
||||||
|
|
|
@ -12,7 +12,7 @@ let
|
||||||
# CD. These are installed into the "nixos" channel of the root
|
# CD. These are installed into the "nixos" channel of the root
|
||||||
# user, as expected by nixos-rebuild/nixos-install. FIXME: merge
|
# user, as expected by nixos-rebuild/nixos-install. FIXME: merge
|
||||||
# with make-channel.nix.
|
# with make-channel.nix.
|
||||||
channelSources = pkgs.runCommand "nixos-${config.system.nixosVersion}"
|
channelSources = pkgs.runCommand "nixos-${config.system.nixos.version}"
|
||||||
{ }
|
{ }
|
||||||
''
|
''
|
||||||
mkdir -p $out
|
mkdir -p $out
|
||||||
|
@ -21,7 +21,7 @@ let
|
||||||
if [ ! -e $out/nixos/nixpkgs ]; then
|
if [ ! -e $out/nixos/nixpkgs ]; then
|
||||||
ln -s . $out/nixos/nixpkgs
|
ln -s . $out/nixos/nixpkgs
|
||||||
fi
|
fi
|
||||||
echo -n ${config.system.nixosVersionSuffix} > $out/nixos/.version-suffix
|
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
|
@ -16,7 +16,7 @@ with lib;
|
||||||
];
|
];
|
||||||
|
|
||||||
# ISO naming.
|
# ISO naming.
|
||||||
isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosLabel}-${pkgs.stdenv.system}.iso";
|
isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixos.label}-${pkgs.stdenv.system}.iso";
|
||||||
|
|
||||||
isoImage.volumeID = substring 0 11 "NIXOS_ISO";
|
isoImage.volumeID = substring 0 11 "NIXOS_ISO";
|
||||||
|
|
||||||
|
|
|
@ -39,31 +39,31 @@ let
|
||||||
DEFAULT boot
|
DEFAULT boot
|
||||||
|
|
||||||
LABEL boot
|
LABEL boot
|
||||||
MENU LABEL NixOS ${config.system.nixosLabel}${config.isoImage.appendToMenuLabel}
|
MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
|
||||||
LINUX /boot/bzImage
|
LINUX /boot/${config.system.boot.loader.kernelFile}
|
||||||
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
||||||
INITRD /boot/initrd
|
INITRD /boot/${config.system.boot.loader.initrdFile}
|
||||||
|
|
||||||
# A variant to boot with 'nomodeset'
|
# A variant to boot with 'nomodeset'
|
||||||
LABEL boot-nomodeset
|
LABEL boot-nomodeset
|
||||||
MENU LABEL NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel} (nomodeset)
|
MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset)
|
||||||
LINUX /boot/bzImage
|
LINUX /boot/${config.system.boot.loader.kernelFile}
|
||||||
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
|
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
|
||||||
INITRD /boot/initrd
|
INITRD /boot/${config.system.boot.loader.initrdFile}
|
||||||
|
|
||||||
# A variant to boot with 'copytoram'
|
# A variant to boot with 'copytoram'
|
||||||
LABEL boot-copytoram
|
LABEL boot-copytoram
|
||||||
MENU LABEL NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel} (copytoram)
|
MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram)
|
||||||
LINUX /boot/bzImage
|
LINUX /boot/${config.system.boot.loader.kernelFile}
|
||||||
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
|
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
|
||||||
INITRD /boot/initrd
|
INITRD /boot/${config.system.boot.loader.initrdFile}
|
||||||
|
|
||||||
# A variant to boot with verbose logging to the console
|
# A variant to boot with verbose logging to the console
|
||||||
LABEL boot-nomodeset
|
LABEL boot-nomodeset
|
||||||
MENU LABEL NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel} (debug)
|
MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
|
||||||
LINUX /boot/bzImage
|
LINUX /boot/${config.system.boot.loader.kernelFile}
|
||||||
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
|
APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
|
||||||
INITRD /boot/initrd
|
INITRD /boot/${config.system.boot.loader.initrdFile}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
isolinuxMemtest86Entry = ''
|
isolinuxMemtest86Entry = ''
|
||||||
|
@ -82,35 +82,35 @@ let
|
||||||
mkdir -p $out/loader/entries
|
mkdir -p $out/loader/entries
|
||||||
|
|
||||||
cat << EOF > $out/loader/entries/nixos-iso.conf
|
cat << EOF > $out/loader/entries/nixos-iso.conf
|
||||||
title NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel}
|
title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
|
||||||
linux /boot/bzImage
|
linux /boot/${config.system.boot.loader.kernelFile}
|
||||||
initrd /boot/initrd
|
initrd /boot/${config.system.boot.loader.initrdFile}
|
||||||
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# A variant to boot with 'nomodeset'
|
# A variant to boot with 'nomodeset'
|
||||||
cat << EOF > $out/loader/entries/nixos-iso-nomodeset.conf
|
cat << EOF > $out/loader/entries/nixos-iso-nomodeset.conf
|
||||||
title NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel}
|
title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
|
||||||
version nomodeset
|
version nomodeset
|
||||||
linux /boot/bzImage
|
linux /boot/${config.system.boot.loader.kernelFile}
|
||||||
initrd /boot/initrd
|
initrd /boot/${config.system.boot.loader.initrdFile}
|
||||||
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
|
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# A variant to boot with 'copytoram'
|
# A variant to boot with 'copytoram'
|
||||||
cat << EOF > $out/loader/entries/nixos-iso-copytoram.conf
|
cat << EOF > $out/loader/entries/nixos-iso-copytoram.conf
|
||||||
title NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel}
|
title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
|
||||||
version copytoram
|
version copytoram
|
||||||
linux /boot/bzImage
|
linux /boot/${config.system.boot.loader.kernelFile}
|
||||||
initrd /boot/initrd
|
initrd /boot/${config.system.boot.loader.initrdFile}
|
||||||
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
|
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# A variant to boot with verbose logging to the console
|
# A variant to boot with verbose logging to the console
|
||||||
cat << EOF > $out/loader/entries/nixos-iso-debug.conf
|
cat << EOF > $out/loader/entries/nixos-iso-debug.conf
|
||||||
title NixOS ${config.system.nixosVersion}${config.isoImage.appendToMenuLabel} (debug)
|
title NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
|
||||||
linux /boot/bzImage
|
linux /boot/${config.system.boot.loader.kernelFile}
|
||||||
initrd /boot/initrd
|
initrd /boot/${config.system.boot.loader.initrdFile}
|
||||||
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
|
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ let
|
||||||
mkdir ./contents && cd ./contents
|
mkdir ./contents && cd ./contents
|
||||||
cp -rp "${efiDir}"/* .
|
cp -rp "${efiDir}"/* .
|
||||||
mkdir ./boot
|
mkdir ./boot
|
||||||
cp -p "${config.boot.kernelPackages.kernel}/bzImage" \
|
cp -p "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}" \
|
||||||
"${config.system.build.initialRamdisk}/initrd" ./boot/
|
"${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" ./boot/
|
||||||
touch --date=@0 ./*
|
touch --date=@0 ./*
|
||||||
|
|
||||||
usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]')
|
usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]')
|
||||||
|
@ -345,11 +345,11 @@ in
|
||||||
};
|
};
|
||||||
target = "/isolinux/isolinux.cfg";
|
target = "/isolinux/isolinux.cfg";
|
||||||
}
|
}
|
||||||
{ source = config.boot.kernelPackages.kernel + "/bzImage";
|
{ source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
|
||||||
target = "/boot/bzImage";
|
target = "/boot/" + config.system.boot.loader.kernelFile;
|
||||||
}
|
}
|
||||||
{ source = config.system.build.initialRamdisk + "/initrd";
|
{ source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
|
||||||
target = "/boot/initrd";
|
target = "/boot/" + config.system.boot.loader.initrdFile;
|
||||||
}
|
}
|
||||||
{ source = config.system.build.squashfsStore;
|
{ source = config.system.build.squashfsStore;
|
||||||
target = "/nix-store.squashfs";
|
target = "/nix-store.squashfs";
|
||||||
|
@ -360,7 +360,7 @@ in
|
||||||
{ source = config.isoImage.splashImage;
|
{ source = config.isoImage.splashImage;
|
||||||
target = "/isolinux/background.png";
|
target = "/isolinux/background.png";
|
||||||
}
|
}
|
||||||
{ source = pkgs.writeText "version" config.system.nixosVersion;
|
{ source = pkgs.writeText "version" config.system.nixos.label;
|
||||||
target = "/version.txt";
|
target = "/version.txt";
|
||||||
}
|
}
|
||||||
] ++ optionals config.isoImage.makeEfiBootable [
|
] ++ optionals config.isoImage.makeEfiBootable [
|
||||||
|
|
|
@ -43,11 +43,18 @@ in
|
||||||
sdImage = {
|
sdImage = {
|
||||||
populateBootCommands = let
|
populateBootCommands = let
|
||||||
configTxt = pkgs.writeText "config.txt" ''
|
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]
|
[pi2]
|
||||||
kernel=u-boot-rpi2.bin
|
kernel=u-boot-rpi2.bin
|
||||||
|
|
||||||
[pi3]
|
[pi3]
|
||||||
kernel=u-boot-rpi3.bin
|
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
|
enable_uart=1
|
||||||
'';
|
'';
|
||||||
in ''
|
in ''
|
||||||
|
|
|
@ -8,7 +8,7 @@ with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
versionFile = pkgs.writeText "nixos-version" config.system.nixosVersion;
|
versionFile = pkgs.writeText "nixos-label" config.system.nixos.label;
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ in
|
||||||
# Individual files to be included on the CD, outside of the Nix
|
# Individual files to be included on the CD, outside of the Nix
|
||||||
# store on the CD.
|
# store on the CD.
|
||||||
tarball.contents =
|
tarball.contents =
|
||||||
[ { source = config.system.build.initialRamdisk + "/initrd";
|
[ { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
|
||||||
target = "/boot/initrd";
|
target = "/boot/" + config.system.boot.loader.initrdFile;
|
||||||
}
|
}
|
||||||
{ source = versionFile;
|
{ source = versionFile;
|
||||||
target = "/nixos-version.txt";
|
target = "/nixos-version.txt";
|
||||||
|
|
|
@ -625,7 +625,7 @@ $bootLoaderConfig
|
||||||
# compatible, in order to avoid breaking some software such as database
|
# compatible, in order to avoid breaking some software such as database
|
||||||
# servers. You should change this only after NixOS release notes say you
|
# servers. You should change this only after NixOS release notes say you
|
||||||
# should.
|
# should.
|
||||||
system.stateVersion = "${\(qw(@nixosRelease@))}"; # Did you read the comment?
|
system.stateVersion = "${\(qw(@release@))}"; # Did you read the comment?
|
||||||
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
|
@ -6,9 +6,9 @@ case "$1" in
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
--hash|--revision)
|
--hash|--revision)
|
||||||
echo "@nixosRevision@"
|
echo "@revision@"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "@nixosVersion@ (@nixosCodeName@)"
|
echo "@version@ (@codeName@)"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -40,7 +40,7 @@ let
|
||||||
src = ./nixos-generate-config.pl;
|
src = ./nixos-generate-config.pl;
|
||||||
path = [ pkgs.btrfs-progs ];
|
path = [ pkgs.btrfs-progs ];
|
||||||
perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
|
perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
|
||||||
inherit (config.system) nixosRelease;
|
inherit (config.system.nixos) release;
|
||||||
};
|
};
|
||||||
|
|
||||||
nixos-option = makeProg {
|
nixos-option = makeProg {
|
||||||
|
@ -51,7 +51,7 @@ let
|
||||||
nixos-version = makeProg {
|
nixos-version = makeProg {
|
||||||
name = "nixos-version";
|
name = "nixos-version";
|
||||||
src = ./nixos-version.sh;
|
src = ./nixos-version.sh;
|
||||||
inherit (config.system) nixosVersion nixosCodeName nixosRevision;
|
inherit (config.system.nixos) version codeName revision;
|
||||||
};
|
};
|
||||||
|
|
||||||
nixos-enter = makeProg {
|
nixos-enter = makeProg {
|
||||||
|
|
|
@ -303,6 +303,7 @@
|
||||||
restya-board = 284;
|
restya-board = 284;
|
||||||
mighttpd2 = 285;
|
mighttpd2 = 285;
|
||||||
hass = 286;
|
hass = 286;
|
||||||
|
monero = 287;
|
||||||
|
|
||||||
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
|
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
|
||||||
|
|
||||||
|
@ -574,6 +575,7 @@
|
||||||
restya-board = 284;
|
restya-board = 284;
|
||||||
mighttpd2 = 285;
|
mighttpd2 = 285;
|
||||||
hass = 286;
|
hass = 286;
|
||||||
|
monero = 287;
|
||||||
|
|
||||||
# When adding a gid, make sure it doesn't match an existing
|
# When adding a gid, make sure it doesn't match an existing
|
||||||
# uid. Users and groups with the same name should have equal
|
# uid. Users and groups with the same name should have equal
|
||||||
|
|
72
nixos/modules/misc/label.nix
Normal file
72
nixos/modules/misc/label.nix
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.system.nixos;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
options.system = {
|
||||||
|
|
||||||
|
nixos.label = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
NixOS version name to be used in the names of generated
|
||||||
|
outputs and boot labels.
|
||||||
|
|
||||||
|
If you ever wanted to influence the labels in your GRUB menu,
|
||||||
|
this is the option for you.
|
||||||
|
|
||||||
|
The default is <option>system.nixos.tags</option> separated by
|
||||||
|
"-" + "-" + <envar>NIXOS_LABEL_VERSION</envar> environment
|
||||||
|
variable (defaults to the value of
|
||||||
|
<option>system.nixos.version</option>).
|
||||||
|
|
||||||
|
Can be overriden by setting <envar>NIXOS_LABEL</envar>.
|
||||||
|
|
||||||
|
Useful for not loosing track of configurations built from different
|
||||||
|
nixos branches/revisions, e.g.:
|
||||||
|
|
||||||
|
<screen>
|
||||||
|
#!/bin/sh
|
||||||
|
today=`date +%Y%m%d`
|
||||||
|
branch=`(cd nixpkgs ; git branch 2>/dev/null | sed -n '/^\* / { s|^\* ||; p; }')`
|
||||||
|
revision=`(cd nixpkgs ; git rev-parse HEAD)`
|
||||||
|
export NIXOS_LABEL_VERSION="$today.$branch-''${revision:0:7}"
|
||||||
|
nixos-rebuild switch</screen>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
nixos.tags = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = [ "with-xen" ];
|
||||||
|
description = ''
|
||||||
|
Strings to prefix to the default
|
||||||
|
<option>system.nixos.label</option>.
|
||||||
|
|
||||||
|
Useful for not loosing track of configurations built with
|
||||||
|
different options, e.g.:
|
||||||
|
|
||||||
|
<screen>
|
||||||
|
{
|
||||||
|
system.nixos.tags = [ "with-xen" ];
|
||||||
|
virtualisation.xen.enable = true;
|
||||||
|
}
|
||||||
|
</screen>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# This is set here rather than up there so that changing it would
|
||||||
|
# not rebuild the manual
|
||||||
|
system.nixos.label = mkDefault (maybeEnv "NIXOS_LABEL"
|
||||||
|
(concatStringsSep "-" (sort (x: y: x < y) cfg.tags)
|
||||||
|
+ "-" + maybeEnv "NIXOS_LABEL_VERSION" cfg.version));
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
cfg = config.nixpkgs;
|
||||||
|
|
||||||
isConfig = x:
|
isConfig = x:
|
||||||
builtins.isAttrs x || lib.isFunction x;
|
builtins.isAttrs x || lib.isFunction x;
|
||||||
|
|
||||||
|
@ -42,12 +44,51 @@ let
|
||||||
merge = lib.mergeOneOption;
|
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
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
options.nixpkgs = {
|
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 {
|
config = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
example = literalExample
|
example = literalExample
|
||||||
|
@ -59,6 +100,8 @@ in
|
||||||
The configuration of the Nix Packages collection. (For
|
The configuration of the Nix Packages collection. (For
|
||||||
details, see the Nixpkgs documentation.) It allows you to set
|
details, see the Nixpkgs documentation.) It allows you to set
|
||||||
package configuration options.
|
package configuration options.
|
||||||
|
|
||||||
|
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,6 +125,8 @@ in
|
||||||
takes as an argument the <emphasis>original</emphasis> Nixpkgs.
|
takes as an argument the <emphasis>original</emphasis> Nixpkgs.
|
||||||
The first argument should be used for finding dependencies, and
|
The first argument should be used for finding dependencies, and
|
||||||
the second should be used for overriding recipes.
|
the second should be used for overriding recipes.
|
||||||
|
|
||||||
|
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,14 +138,16 @@ in
|
||||||
If unset, it defaults to the platform type of your host system.
|
If unset, it defaults to the platform type of your host system.
|
||||||
Specifying this option is useful when doing distributed
|
Specifying this option is useful when doing distributed
|
||||||
multi-platform deployment, or when building virtual machines.
|
multi-platform deployment, or when building virtual machines.
|
||||||
|
|
||||||
|
Ignored when <code>nixpkgs.pkgs</code> is set.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
_module.args = {
|
_module.args = {
|
||||||
pkgs = _pkgs;
|
pkgs = cfg.pkgs;
|
||||||
pkgs_i686 = _pkgs.pkgsi686Linux;
|
pkgs_i686 = cfg.pkgs.pkgsi686Linux;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.system;
|
cfg = config.system.nixos;
|
||||||
|
|
||||||
releaseFile = "${toString pkgs.path}/.version";
|
releaseFile = "${toString pkgs.path}/.version";
|
||||||
suffixFile = "${toString pkgs.path}/.version-suffix";
|
suffixFile = "${toString pkgs.path}/.version-suffix";
|
||||||
|
@ -16,9 +16,44 @@ in
|
||||||
|
|
||||||
options.system = {
|
options.system = {
|
||||||
|
|
||||||
|
nixos.version = mkOption {
|
||||||
|
internal = true;
|
||||||
|
type = types.str;
|
||||||
|
description = "The full NixOS version (e.g. <literal>16.03.1160.f2d4ee1</literal>).";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixos.release = mkOption {
|
||||||
|
readOnly = true;
|
||||||
|
type = types.str;
|
||||||
|
default = fileContents releaseFile;
|
||||||
|
description = "The NixOS release (e.g. <literal>16.03</literal>).";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixos.versionSuffix = mkOption {
|
||||||
|
internal = true;
|
||||||
|
type = types.str;
|
||||||
|
default = if pathExists suffixFile then fileContents suffixFile else "pre-git";
|
||||||
|
description = "The NixOS version suffix (e.g. <literal>1160.f2d4ee1</literal>).";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixos.revision = mkOption {
|
||||||
|
internal = true;
|
||||||
|
type = types.str;
|
||||||
|
default = if pathIsDirectory gitRepo then commitIdFromGitRepo gitRepo
|
||||||
|
else if pathExists revisionFile then fileContents revisionFile
|
||||||
|
else "master";
|
||||||
|
description = "The Git revision from which this NixOS configuration was built.";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixos.codeName = mkOption {
|
||||||
|
readOnly = true;
|
||||||
|
type = types.str;
|
||||||
|
description = "The NixOS release code name (e.g. <literal>Emu</literal>).";
|
||||||
|
};
|
||||||
|
|
||||||
stateVersion = mkOption {
|
stateVersion = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = cfg.nixosRelease;
|
default = cfg.release;
|
||||||
description = ''
|
description = ''
|
||||||
Every once in a while, a new NixOS release may change
|
Every once in a while, a new NixOS release may change
|
||||||
configuration defaults in a way incompatible with stateful
|
configuration defaults in a way incompatible with stateful
|
||||||
|
@ -32,49 +67,6 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
nixosLabel = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
Label to be used in the names of generated outputs and boot
|
|
||||||
labels.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosVersion = mkOption {
|
|
||||||
internal = true;
|
|
||||||
type = types.str;
|
|
||||||
description = "The full NixOS version (e.g. <literal>16.03.1160.f2d4ee1</literal>).";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosRelease = mkOption {
|
|
||||||
readOnly = true;
|
|
||||||
type = types.str;
|
|
||||||
default = fileContents releaseFile;
|
|
||||||
description = "The NixOS release (e.g. <literal>16.03</literal>).";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosVersionSuffix = mkOption {
|
|
||||||
internal = true;
|
|
||||||
type = types.str;
|
|
||||||
default = if pathExists suffixFile then fileContents suffixFile else "pre-git";
|
|
||||||
description = "The NixOS version suffix (e.g. <literal>1160.f2d4ee1</literal>).";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosRevision = mkOption {
|
|
||||||
internal = true;
|
|
||||||
type = types.str;
|
|
||||||
default = if pathIsDirectory gitRepo then commitIdFromGitRepo gitRepo
|
|
||||||
else if pathExists revisionFile then fileContents revisionFile
|
|
||||||
else "master";
|
|
||||||
description = "The Git revision from which this NixOS configuration was built.";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosCodeName = mkOption {
|
|
||||||
readOnly = true;
|
|
||||||
type = types.str;
|
|
||||||
description = "The NixOS release code name (e.g. <literal>Emu</literal>).";
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultChannel = mkOption {
|
defaultChannel = mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
@ -86,16 +78,15 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
|
||||||
system = {
|
system.nixos = {
|
||||||
# These defaults are set here rather than up there so that
|
# These defaults are set here rather than up there so that
|
||||||
# changing them would not rebuild the manual
|
# changing them would not rebuild the manual
|
||||||
nixosLabel = mkDefault cfg.nixosVersion;
|
version = mkDefault (cfg.release + cfg.versionSuffix);
|
||||||
nixosVersion = mkDefault (cfg.nixosRelease + cfg.nixosVersionSuffix);
|
revision = mkIf (pathIsDirectory gitRepo) (mkDefault gitCommitId);
|
||||||
nixosRevision = mkIf (pathIsDirectory gitRepo) (mkDefault gitCommitId);
|
versionSuffix = mkIf (pathIsDirectory gitRepo) (mkDefault (".git." + gitCommitId));
|
||||||
nixosVersionSuffix = mkIf (pathIsDirectory gitRepo) (mkDefault (".git." + gitCommitId));
|
|
||||||
|
|
||||||
# Note: code names must only increase in alphabetical order.
|
# Note: code names must only increase in alphabetical order.
|
||||||
nixosCodeName = "Impala";
|
codeName = "Impala";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Generate /etc/os-release. See
|
# Generate /etc/os-release. See
|
||||||
|
@ -105,10 +96,10 @@ in
|
||||||
''
|
''
|
||||||
NAME=NixOS
|
NAME=NixOS
|
||||||
ID=nixos
|
ID=nixos
|
||||||
VERSION="${config.system.nixosVersion} (${config.system.nixosCodeName})"
|
VERSION="${cfg.version} (${cfg.codeName})"
|
||||||
VERSION_CODENAME=${toLower config.system.nixosCodeName}
|
VERSION_CODENAME=${toLower cfg.codeName}
|
||||||
VERSION_ID="${config.system.nixosVersion}"
|
VERSION_ID="${cfg.version}"
|
||||||
PRETTY_NAME="NixOS ${config.system.nixosVersion} (${config.system.nixosCodeName})"
|
PRETTY_NAME="NixOS ${cfg.version} (${cfg.codeName})"
|
||||||
HOME_URL="https://nixos.org/"
|
HOME_URL="https://nixos.org/"
|
||||||
SUPPORT_URL="https://nixos.org/nixos/support.html"
|
SUPPORT_URL="https://nixos.org/nixos/support.html"
|
||||||
BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
|
BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
./misc/extra-arguments.nix
|
./misc/extra-arguments.nix
|
||||||
./misc/ids.nix
|
./misc/ids.nix
|
||||||
./misc/lib.nix
|
./misc/lib.nix
|
||||||
|
./misc/label.nix
|
||||||
./misc/locate.nix
|
./misc/locate.nix
|
||||||
./misc/meta.nix
|
./misc/meta.nix
|
||||||
./misc/nixpkgs.nix
|
./misc/nixpkgs.nix
|
||||||
|
@ -75,6 +76,7 @@
|
||||||
./programs/cdemu.nix
|
./programs/cdemu.nix
|
||||||
./programs/chromium.nix
|
./programs/chromium.nix
|
||||||
./programs/command-not-found/command-not-found.nix
|
./programs/command-not-found/command-not-found.nix
|
||||||
|
./programs/criu.nix
|
||||||
./programs/dconf.nix
|
./programs/dconf.nix
|
||||||
./programs/environment.nix
|
./programs/environment.nix
|
||||||
./programs/fish.nix
|
./programs/fish.nix
|
||||||
|
@ -92,6 +94,7 @@
|
||||||
./programs/nano.nix
|
./programs/nano.nix
|
||||||
./programs/npm.nix
|
./programs/npm.nix
|
||||||
./programs/oblogout.nix
|
./programs/oblogout.nix
|
||||||
|
./programs/plotinus.nix
|
||||||
./programs/qt5ct.nix
|
./programs/qt5ct.nix
|
||||||
./programs/rootston.nix
|
./programs/rootston.nix
|
||||||
./programs/screen.nix
|
./programs/screen.nix
|
||||||
|
@ -102,6 +105,7 @@
|
||||||
./programs/ssh.nix
|
./programs/ssh.nix
|
||||||
./programs/ssmtp.nix
|
./programs/ssmtp.nix
|
||||||
./programs/sysdig.nix
|
./programs/sysdig.nix
|
||||||
|
./programs/systemtap.nix
|
||||||
./programs/sway.nix
|
./programs/sway.nix
|
||||||
./programs/thefuck.nix
|
./programs/thefuck.nix
|
||||||
./programs/tmux.nix
|
./programs/tmux.nix
|
||||||
|
@ -111,8 +115,10 @@
|
||||||
./programs/wireshark.nix
|
./programs/wireshark.nix
|
||||||
./programs/xfs_quota.nix
|
./programs/xfs_quota.nix
|
||||||
./programs/xonsh.nix
|
./programs/xonsh.nix
|
||||||
|
./programs/yabar.nix
|
||||||
./programs/zsh/oh-my-zsh.nix
|
./programs/zsh/oh-my-zsh.nix
|
||||||
./programs/zsh/zsh.nix
|
./programs/zsh/zsh.nix
|
||||||
|
./programs/zsh/zsh-autoenv.nix
|
||||||
./programs/zsh/zsh-syntax-highlighting.nix
|
./programs/zsh/zsh-syntax-highlighting.nix
|
||||||
./rename.nix
|
./rename.nix
|
||||||
./security/acme.nix
|
./security/acme.nix
|
||||||
|
@ -151,6 +157,7 @@
|
||||||
./services/backup/almir.nix
|
./services/backup/almir.nix
|
||||||
./services/backup/bacula.nix
|
./services/backup/bacula.nix
|
||||||
./services/backup/crashplan.nix
|
./services/backup/crashplan.nix
|
||||||
|
./services/backup/crashplan-small-business.nix
|
||||||
./services/backup/mysql-backup.nix
|
./services/backup/mysql-backup.nix
|
||||||
./services/backup/postgresql-backup.nix
|
./services/backup/postgresql-backup.nix
|
||||||
./services/backup/rsnapshot.nix
|
./services/backup/rsnapshot.nix
|
||||||
|
@ -200,6 +207,7 @@
|
||||||
./services/desktops/dleyna-renderer.nix
|
./services/desktops/dleyna-renderer.nix
|
||||||
./services/desktops/dleyna-server.nix
|
./services/desktops/dleyna-server.nix
|
||||||
./services/desktops/geoclue2.nix
|
./services/desktops/geoclue2.nix
|
||||||
|
./services/desktops/pipewire.nix
|
||||||
./services/desktops/gnome3/at-spi2-core.nix
|
./services/desktops/gnome3/at-spi2-core.nix
|
||||||
./services/desktops/gnome3/chrome-gnome-shell.nix
|
./services/desktops/gnome3/chrome-gnome-shell.nix
|
||||||
./services/desktops/gnome3/evolution-data-server.nix
|
./services/desktops/gnome3/evolution-data-server.nix
|
||||||
|
@ -238,6 +246,7 @@
|
||||||
./services/hardware/pcscd.nix
|
./services/hardware/pcscd.nix
|
||||||
./services/hardware/pommed.nix
|
./services/hardware/pommed.nix
|
||||||
./services/hardware/sane.nix
|
./services/hardware/sane.nix
|
||||||
|
./services/hardware/sane_extra_backends/brscan4.nix
|
||||||
./services/hardware/tcsd.nix
|
./services/hardware/tcsd.nix
|
||||||
./services/hardware/tlp.nix
|
./services/hardware/tlp.nix
|
||||||
./services/hardware/thinkfan.nix
|
./services/hardware/thinkfan.nix
|
||||||
|
@ -334,6 +343,7 @@
|
||||||
./services/misc/nix-optimise.nix
|
./services/misc/nix-optimise.nix
|
||||||
./services/misc/nixos-manual.nix
|
./services/misc/nixos-manual.nix
|
||||||
./services/misc/nix-ssh-serve.nix
|
./services/misc/nix-ssh-serve.nix
|
||||||
|
./services/misc/novacomd.nix
|
||||||
./services/misc/nzbget.nix
|
./services/misc/nzbget.nix
|
||||||
./services/misc/octoprint.nix
|
./services/misc/octoprint.nix
|
||||||
./services/misc/osrm.nix
|
./services/misc/osrm.nix
|
||||||
|
@ -417,7 +427,8 @@
|
||||||
./services/network-filesystems/ipfs.nix
|
./services/network-filesystems/ipfs.nix
|
||||||
./services/network-filesystems/netatalk.nix
|
./services/network-filesystems/netatalk.nix
|
||||||
./services/network-filesystems/nfsd.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/rsyncd.nix
|
||||||
./services/network-filesystems/samba.nix
|
./services/network-filesystems/samba.nix
|
||||||
./services/network-filesystems/tahoe.nix
|
./services/network-filesystems/tahoe.nix
|
||||||
|
@ -491,6 +502,7 @@
|
||||||
./services/networking/minidlna.nix
|
./services/networking/minidlna.nix
|
||||||
./services/networking/miniupnpd.nix
|
./services/networking/miniupnpd.nix
|
||||||
./services/networking/mosquitto.nix
|
./services/networking/mosquitto.nix
|
||||||
|
./services/networking/monero.nix
|
||||||
./services/networking/miredo.nix
|
./services/networking/miredo.nix
|
||||||
./services/networking/mstpd.nix
|
./services/networking/mstpd.nix
|
||||||
./services/networking/murmur.nix
|
./services/networking/murmur.nix
|
||||||
|
@ -501,6 +513,7 @@
|
||||||
./services/networking/ngircd.nix
|
./services/networking/ngircd.nix
|
||||||
./services/networking/nghttpx/default.nix
|
./services/networking/nghttpx/default.nix
|
||||||
./services/networking/nix-serve.nix
|
./services/networking/nix-serve.nix
|
||||||
|
./services/networking/nixops-dns.nix
|
||||||
./services/networking/nntp-proxy.nix
|
./services/networking/nntp-proxy.nix
|
||||||
./services/networking/nsd.nix
|
./services/networking/nsd.nix
|
||||||
./services/networking/ntopng.nix
|
./services/networking/ntopng.nix
|
||||||
|
@ -528,6 +541,7 @@
|
||||||
./services/networking/redsocks.nix
|
./services/networking/redsocks.nix
|
||||||
./services/networking/resilio.nix
|
./services/networking/resilio.nix
|
||||||
./services/networking/rpcbind.nix
|
./services/networking/rpcbind.nix
|
||||||
|
./services/networking/rxe.nix
|
||||||
./services/networking/sabnzbd.nix
|
./services/networking/sabnzbd.nix
|
||||||
./services/networking/searx.nix
|
./services/networking/searx.nix
|
||||||
./services/networking/seeks.nix
|
./services/networking/seeks.nix
|
||||||
|
@ -685,6 +699,7 @@
|
||||||
./services/x11/xserver.nix
|
./services/x11/xserver.nix
|
||||||
./system/activation/activation-script.nix
|
./system/activation/activation-script.nix
|
||||||
./system/activation/top-level.nix
|
./system/activation/top-level.nix
|
||||||
|
./system/boot/binfmt.nix
|
||||||
./system/boot/coredump.nix
|
./system/boot/coredump.nix
|
||||||
./system/boot/emergency-mode.nix
|
./system/boot/emergency-mode.nix
|
||||||
./system/boot/grow-partition.nix
|
./system/boot/grow-partition.nix
|
||||||
|
|
|
@ -16,6 +16,7 @@ with lib;
|
||||||
To grant access to a user, it must be part of adbusers group:
|
To grant access to a user, it must be part of adbusers group:
|
||||||
<code>users.extraUsers.alice.extraGroups = ["adbusers"];</code>
|
<code>users.extraUsers.alice.extraGroups = ["adbusers"];</code>
|
||||||
'';
|
'';
|
||||||
|
relatedPackages = [ ["androidenv" "platformTools"] ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
26
nixos/modules/programs/criu.nix
Normal file
26
nixos/modules/programs/criu.nix
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let cfg = config.programs.criu;
|
||||||
|
in {
|
||||||
|
|
||||||
|
options = {
|
||||||
|
programs.criu = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Install <command>criu</command> along with necessary kernel options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
||||||
|
(isYes "CHECKPOINT_RESTORE")
|
||||||
|
];
|
||||||
|
boot.kernel.features.criu = true;
|
||||||
|
environment.systemPackages = [ pkgs.criu ];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
36
nixos/modules/programs/plotinus.nix
Normal file
36
nixos/modules/programs/plotinus.nix
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.plotinus;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
meta = {
|
||||||
|
maintainers = pkgs.plotinus.meta.maintainers;
|
||||||
|
doc = ./plotinus.xml;
|
||||||
|
};
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
programs.plotinus = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to enable the Plotinus GTK+3 plugin. Plotinus provides a
|
||||||
|
popup (triggered by Ctrl-Shift-P) to search the menus of a
|
||||||
|
compatible application.
|
||||||
|
'';
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.variables.XDG_DATA_DIRS = [ "${pkgs.plotinus}/share/gsettings-schemas/${pkgs.plotinus.name}" ];
|
||||||
|
environment.variables.GTK3_MODULES = [ "${pkgs.plotinus}/lib/libplotinus.so" ];
|
||||||
|
};
|
||||||
|
}
|
25
nixos/modules/programs/plotinus.xml
Normal file
25
nixos/modules/programs/plotinus.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||||
|
version="5.0"
|
||||||
|
xml:id="module-program-plotinus">
|
||||||
|
|
||||||
|
<title>Plotinus</title>
|
||||||
|
|
||||||
|
<para><emphasis>Source:</emphasis> <filename>modules/programs/plotinus.nix</filename></para>
|
||||||
|
|
||||||
|
<para><emphasis>Upstream documentation:</emphasis> <link xlink:href="https://github.com/p-e-w/plotinus"/></para>
|
||||||
|
|
||||||
|
<para>Plotinus is a searchable command palette in every modern GTK+ application.</para>
|
||||||
|
|
||||||
|
<para>When in a GTK+3 application and Plotinus is enabled, you can press <literal>Ctrl+Shift+P</literal> to open the command palette. The command palette provides a searchable list of of all menu items in the application.</para>
|
||||||
|
|
||||||
|
<para>To enable Plotinus, add the following to your <filename>configuration.nix</filename>:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
programs.plotinus.enable = true;
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
</chapter>
|
28
nixos/modules/programs/systemtap.nix
Normal file
28
nixos/modules/programs/systemtap.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let cfg = config.programs.systemtap;
|
||||||
|
in {
|
||||||
|
|
||||||
|
options = {
|
||||||
|
programs.systemtap = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Install <command>systemtap</command> along with necessary kernel options.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
||||||
|
(isYes "DEBUG")
|
||||||
|
];
|
||||||
|
boot.kernel.features.debug = true;
|
||||||
|
environment.systemPackages = [
|
||||||
|
config.boot.kernelPackages.systemtap
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -61,7 +61,12 @@ in {
|
||||||
options = {
|
options = {
|
||||||
programs.tmux = {
|
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 {
|
aggressiveResize = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
|
|
149
nixos/modules/programs/yabar.nix
Normal file
149
nixos/modules/programs/yabar.nix
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
{ lib, pkgs, config, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.yabar;
|
||||||
|
|
||||||
|
mapExtra = v: lib.concatStringsSep "\n" (mapAttrsToList (
|
||||||
|
key: val: "${key} = ${if (isString val) then "\"${val}\"" else "${builtins.toString val}"};"
|
||||||
|
) v);
|
||||||
|
|
||||||
|
listKeys = r: concatStringsSep "," (map (n: "\"${n}\"") (attrNames r));
|
||||||
|
|
||||||
|
configFile = let
|
||||||
|
bars = mapAttrsToList (
|
||||||
|
name: cfg: ''
|
||||||
|
${name}: {
|
||||||
|
font: "${cfg.font}";
|
||||||
|
position: "${cfg.position}";
|
||||||
|
|
||||||
|
${mapExtra cfg.extra}
|
||||||
|
|
||||||
|
block-list: [${listKeys cfg.indicators}]
|
||||||
|
|
||||||
|
${concatStringsSep "\n" (mapAttrsToList (
|
||||||
|
name: cfg: ''
|
||||||
|
${name}: {
|
||||||
|
exec: "${cfg.exec}";
|
||||||
|
align: "${cfg.align}";
|
||||||
|
${mapExtra cfg.extra}
|
||||||
|
};
|
||||||
|
''
|
||||||
|
) cfg.indicators)}
|
||||||
|
};
|
||||||
|
''
|
||||||
|
) cfg.bars;
|
||||||
|
in pkgs.writeText "yabar.conf" ''
|
||||||
|
bar-list = [${listKeys cfg.bars}];
|
||||||
|
${concatStringsSep "\n" bars}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.programs.yabar = {
|
||||||
|
enable = mkEnableOption "yabar";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
default = pkgs.yabar;
|
||||||
|
example = literalExample "pkgs.yabar-unstable";
|
||||||
|
type = types.package;
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
The package which contains the `yabar` binary.
|
||||||
|
|
||||||
|
Nixpkgs provides the `yabar` and `yabar-unstable`
|
||||||
|
derivations since 18.03, so it's possible to choose.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
bars = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf(types.submodule {
|
||||||
|
options = {
|
||||||
|
font = mkOption {
|
||||||
|
default = "sans bold 9";
|
||||||
|
example = "Droid Sans, FontAwesome Bold 9";
|
||||||
|
type = types.string;
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
The font that will be used to draw the status bar.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
position = mkOption {
|
||||||
|
default = "top";
|
||||||
|
example = "bottom";
|
||||||
|
type = types.enum [ "top" "bottom" ];
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
The position where the bar will be rendered.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extra = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf types.string;
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
An attribute set which contains further attributes of a bar.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
indicators = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf(types.submodule {
|
||||||
|
options.exec = mkOption {
|
||||||
|
example = "YABAR_DATE";
|
||||||
|
type = types.string;
|
||||||
|
description = ''
|
||||||
|
The type of the indicator to be executed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
options.align = mkOption {
|
||||||
|
default = "left";
|
||||||
|
example = "right";
|
||||||
|
type = types.enum [ "left" "center" "right" ];
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
Whether to align the indicator at the left or right of the bar.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
options.extra = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.either types.string types.int);
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
An attribute set which contains further attributes of a indicator.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
Indicators that should be rendered by yabar.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
description = ''
|
||||||
|
List of bars that should be rendered by yabar.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.user.services.yabar = {
|
||||||
|
description = "yabar service";
|
||||||
|
wantedBy = [ "graphical-session.target" ];
|
||||||
|
partOf = [ "graphical-session.target" ];
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
${cfg.package}/bin/yabar -c ${configFile}
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig.Restart = "always";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
28
nixos/modules/programs/zsh/zsh-autoenv.nix
Normal file
28
nixos/modules/programs/zsh/zsh-autoenv.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.zsh.zsh-autoenv;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
programs.zsh.zsh-autoenv = {
|
||||||
|
enable = mkEnableOption "zsh-autoenv";
|
||||||
|
package = mkOption {
|
||||||
|
default = pkgs.zsh-autoenv;
|
||||||
|
defaultText = "pkgs.zsh-autoenv";
|
||||||
|
description = ''
|
||||||
|
Package to install for `zsh-autoenv` usage.
|
||||||
|
'';
|
||||||
|
|
||||||
|
type = types.package;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
programs.zsh.interactiveShellInit = ''
|
||||||
|
source ${cfg.package}/share/zsh-autoenv/autoenv.zsh
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -189,6 +189,14 @@ with lib;
|
||||||
# Profile splitting
|
# Profile splitting
|
||||||
(mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ])
|
(mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ])
|
||||||
|
|
||||||
|
# misc/version.nix
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosVersion" ] [ "config" "system" "nixos" "version" ])
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosRelease" ] [ "config" "system" "nixos" "release" ])
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosVersionSuffix" ] [ "config" "system" "nixos" "versionSuffix" ])
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosRevision" ] [ "config" "system" "nixos" "revision" ])
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosCodeName" ] [ "config" "system" "nixos" "codeName" ])
|
||||||
|
(mkRenamedOptionModule [ "config" "system" "nixosLabel" ] [ "config" "system" "nixos" "label" ])
|
||||||
|
|
||||||
# Options that are obsolete and have no replacement.
|
# Options that are obsolete and have no replacement.
|
||||||
(mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
|
(mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
|
||||||
(mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
|
(mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
|
||||||
|
@ -205,11 +213,14 @@ with lib;
|
||||||
"See the 16.09 release notes for more information.")
|
"See the 16.09 release notes for more information.")
|
||||||
(mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
|
(mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
|
||||||
(mkRemovedOptionModule [ "services" "dovecot2" "package" ] "")
|
(mkRemovedOptionModule [ "services" "dovecot2" "package" ] "")
|
||||||
|
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "user" ] "")
|
||||||
|
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "group" ] "")
|
||||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
|
(mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
|
||||||
(mkRemovedOptionModule [ "services" "xserver" "displayManager" "sddm" "themes" ]
|
(mkRemovedOptionModule [ "services" "xserver" "displayManager" "sddm" "themes" ]
|
||||||
"Set the option `services.xserver.displayManager.sddm.package' instead.")
|
"Set the option `services.xserver.displayManager.sddm.package' instead.")
|
||||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
|
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
|
||||||
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
|
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
|
||||||
|
(mkRemovedOptionModule [ "virtualisation" "xen" "qemu" ] "You don't need this option anymore, it will work without it.")
|
||||||
|
|
||||||
# ZSH
|
# ZSH
|
||||||
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
||||||
|
@ -220,5 +231,8 @@ with lib;
|
||||||
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "theme" ] [ "programs" "zsh" "ohMyZsh" "theme" ])
|
(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" "custom" ] [ "programs" "zsh" "ohMyZsh" "custom" ])
|
||||||
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "plugins" ] [ "programs" "zsh" "ohMyZsh" "plugins" ])
|
(mkRenamedOptionModule [ "programs" "zsh" "oh-my-zsh" "plugins" ] [ "programs" "zsh" "ohMyZsh" "plugins" ])
|
||||||
|
|
||||||
|
# Xen
|
||||||
|
(mkRenamedOptionModule [ "virtualisation" "xen" "qemu-package" ] [ "virtualisation" "xen" "package-qemu" ])
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,11 @@ let
|
||||||
|
|
||||||
cfg = config.security.acme;
|
cfg = config.security.acme;
|
||||||
|
|
||||||
certOpts = { ... }: {
|
certOpts = { name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
webroot = mkOption {
|
webroot = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
example = "/var/lib/acme/acme-challenges";
|
||||||
description = ''
|
description = ''
|
||||||
Where the webroot of the HTTP vhost is located.
|
Where the webroot of the HTTP vhost is located.
|
||||||
<filename>.well-known/acme-challenge/</filename> directory
|
<filename>.well-known/acme-challenge/</filename> directory
|
||||||
|
@ -20,8 +21,8 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
domain = mkOption {
|
domain = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.str;
|
||||||
default = null;
|
default = name;
|
||||||
description = "Domain to fetch certificate for (defaults to the entry name)";
|
description = "Domain to fetch certificate for (defaults to the entry name)";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ let
|
||||||
default = false;
|
default = false;
|
||||||
description = ''
|
description = ''
|
||||||
Give read permissions to the specified group
|
Give read permissions to the specified group
|
||||||
(<option>security.acme.group</option>) to read SSL private certificates.
|
(<option>security.acme.cert.<name>.group</option>) to read SSL private certificates.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ let
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
description = ''
|
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.
|
own server roots if needed.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -193,10 +194,9 @@ in
|
||||||
servicesLists = mapAttrsToList certToServices cfg.certs;
|
servicesLists = mapAttrsToList certToServices cfg.certs;
|
||||||
certToServices = cert: data:
|
certToServices = cert: data:
|
||||||
let
|
let
|
||||||
domain = if data.domain != null then data.domain else cert;
|
|
||||||
cpath = "${cfg.directory}/${cert}";
|
cpath = "${cfg.directory}/${cert}";
|
||||||
rights = if data.allowKeysForGroup then "750" else "700";
|
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 ]
|
++ optionals (data.email != null) [ "--email" data.email ]
|
||||||
++ concatMap (p: [ "-f" p ]) data.plugins
|
++ concatMap (p: [ "-f" p ]) data.plugins
|
||||||
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
|
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
|
||||||
|
|
|
@ -46,6 +46,18 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
googleAuthenticator = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
If set, users with enabled Google Authenticator (created
|
||||||
|
<filename>~/.google_authenticator</filename>) will be required
|
||||||
|
to provide Google Authenticator token to log in.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
usbAuth = mkOption {
|
usbAuth = mkOption {
|
||||||
default = config.security.pam.usb.enable;
|
default = config.security.pam.usb.enable;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
@ -284,7 +296,12 @@ let
|
||||||
# prompts the user for password so we run it once with 'required' at an
|
# 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.
|
# earlier point and it will run again with 'sufficient' further down.
|
||||||
# We use try_first_pass the second time to avoid prompting password twice
|
# 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
|
auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth
|
||||||
${optionalString config.security.pam.enableEcryptfs
|
${optionalString config.security.pam.enableEcryptfs
|
||||||
"auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
|
"auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
|
||||||
|
@ -295,6 +312,8 @@ let
|
||||||
" kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
|
" kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
|
||||||
${optionalString cfg.enableGnomeKeyring
|
${optionalString cfg.enableGnomeKeyring
|
||||||
("auth optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so")}
|
("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
|
${optionalString cfg.unixAuth
|
||||||
"auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
|
"auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
|
||||||
|
|
74
nixos/modules/services/backup/crashplan-small-business.nix
Normal file
74
nixos/modules/services/backup/crashplan-small-business.nix
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.crashplansb;
|
||||||
|
crashplansb = pkgs.crashplansb.override { maxRam = cfg.maxRam; };
|
||||||
|
varDir = "/var/lib/crashplan";
|
||||||
|
in
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.crashplansb = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Starts crashplan for small business background service.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
maxRam = mkOption {
|
||||||
|
default = "1024m";
|
||||||
|
example = "2G";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Maximum amount of ram that the crashplan engine should use.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
openPorts = mkOption {
|
||||||
|
description = "Open ports in the firewall for crashplan.";
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
ports = mkOption {
|
||||||
|
# https://support.code42.com/Administrator/6/Planning_and_installing/TCP_and_UDP_ports_used_by_the_Code42_platform
|
||||||
|
# used ports can also be checked in the desktop app console using the command connection.info
|
||||||
|
description = "which ports to open.";
|
||||||
|
default = [ 4242 4243 4244 4247 ];
|
||||||
|
type = types.listOf types.int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ crashplansb ];
|
||||||
|
networking.firewall.allowedTCPPorts = mkIf cfg.openPorts cfg.ports;
|
||||||
|
|
||||||
|
systemd.services.crashplansb = {
|
||||||
|
description = "CrashPlan Backup Engine";
|
||||||
|
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" "local-fs.target" ];
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
install -d -m 755 ${crashplansb.vardir}
|
||||||
|
install -d -m 700 ${crashplansb.vardir}/conf
|
||||||
|
install -d -m 700 ${crashplansb.manifestdir}
|
||||||
|
install -d -m 700 ${crashplansb.vardir}/cache
|
||||||
|
install -d -m 700 ${crashplansb.vardir}/backupArchives
|
||||||
|
install -d -m 777 ${crashplansb.vardir}/log
|
||||||
|
cp -avn ${crashplansb}/conf.template/* ${crashplansb.vardir}/conf
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "forking";
|
||||||
|
EnvironmentFile = "${crashplansb}/bin/run.conf";
|
||||||
|
ExecStart = "${crashplansb}/bin/CrashPlanEngine start";
|
||||||
|
ExecStop = "${crashplansb}/bin/CrashPlanEngine stop";
|
||||||
|
PIDFile = "${crashplansb.vardir}/CrashPlanEngine.pid";
|
||||||
|
WorkingDirectory = crashplansb;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -6,12 +6,12 @@ let
|
||||||
cfg = config.services.kubernetes.addons.dashboard;
|
cfg = config.services.kubernetes.addons.dashboard;
|
||||||
|
|
||||||
name = "gcr.io/google_containers/kubernetes-dashboard-amd64";
|
name = "gcr.io/google_containers/kubernetes-dashboard-amd64";
|
||||||
version = "v1.6.3";
|
version = "v1.8.2";
|
||||||
|
|
||||||
image = pkgs.dockerTools.pullImage {
|
image = pkgs.dockerTools.pullImage {
|
||||||
imageName = name;
|
imageName = name;
|
||||||
imageTag = version;
|
imageTag = version;
|
||||||
sha256 = "1sf54d96nkgic9hir9c6p14gw24ns1k5d5a0r1sg414kjrvic0b4";
|
sha256 = "11h0fz3wxp0f10fsyqaxjm7l2qg7xws50dv5iwlck5gb1fjmajad";
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
options.services.kubernetes.addons.dashboard = {
|
options.services.kubernetes.addons.dashboard = {
|
||||||
|
|
|
@ -301,8 +301,8 @@ in {
|
||||||
Kubernetes apiserver authorization mode (AlwaysAllow/AlwaysDeny/ABAC/RBAC). See
|
Kubernetes apiserver authorization mode (AlwaysAllow/AlwaysDeny/ABAC/RBAC). See
|
||||||
<link xlink:href="http://kubernetes.io/docs/admin/authorization.html"/>
|
<link xlink:href="http://kubernetes.io/docs/admin/authorization.html"/>
|
||||||
'';
|
'';
|
||||||
default = ["RBAC"];
|
default = ["RBAC" "Node"];
|
||||||
type = types.listOf (types.enum ["AlwaysAllow" "AlwaysDeny" "ABAC" "RBAC"]);
|
type = types.listOf (types.enum ["AlwaysAllow" "AlwaysDeny" "ABAC" "RBAC" "Node"]);
|
||||||
};
|
};
|
||||||
|
|
||||||
authorizationPolicy = mkOption {
|
authorizationPolicy = mkOption {
|
||||||
|
@ -344,7 +344,7 @@ in {
|
||||||
Kubernetes admission control plugins to use. See
|
Kubernetes admission control plugins to use. See
|
||||||
<link xlink:href="http://kubernetes.io/docs/admin/admission-controllers/"/>
|
<link xlink:href="http://kubernetes.io/docs/admin/admission-controllers/"/>
|
||||||
'';
|
'';
|
||||||
default = ["NamespaceLifecycle" "LimitRanger" "ServiceAccount" "ResourceQuota" "DefaultStorageClass" "DefaultTolerationSeconds"];
|
default = ["NamespaceLifecycle" "LimitRanger" "ServiceAccount" "ResourceQuota" "DefaultStorageClass" "DefaultTolerationSeconds" "NodeRestriction"];
|
||||||
example = [
|
example = [
|
||||||
"NamespaceLifecycle" "NamespaceExists" "LimitRanger"
|
"NamespaceLifecycle" "NamespaceExists" "LimitRanger"
|
||||||
"SecurityContextDeny" "ServiceAccount" "ResourceQuota"
|
"SecurityContextDeny" "ServiceAccount" "ResourceQuota"
|
||||||
|
|
|
@ -12,8 +12,14 @@ let
|
||||||
${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
|
${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
|
||||||
${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''}
|
${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''}
|
||||||
${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''}
|
${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''}
|
||||||
|
PlugStackConfig=${plugStackConfig}
|
||||||
${cfg.extraConfig}
|
${cfg.extraConfig}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
plugStackConfig = pkgs.writeText "plugstack.conf"
|
||||||
|
''
|
||||||
|
${optionalString cfg.enableSrunX11 ''optional ${pkgs.slurm-spank-x11}/lib/x11.so''}
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -86,6 +92,17 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enableSrunX11 = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
If enabled srun will accept the option "--x11" to allow for X11 forwarding
|
||||||
|
from within an interactive session or a batch job. This activates the
|
||||||
|
slurm-spank-x11 module. Note that this requires 'services.openssh.forwardX11'
|
||||||
|
to be enabled on the compute nodes.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraConfig = mkOption {
|
extraConfig = mkOption {
|
||||||
default = "";
|
default = "";
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
|
@ -134,7 +151,8 @@ in
|
||||||
environment.systemPackages = [ wrappedSlurm ];
|
environment.systemPackages = [ wrappedSlurm ];
|
||||||
|
|
||||||
systemd.services.slurmd = mkIf (cfg.client.enable) {
|
systemd.services.slurmd = mkIf (cfg.client.enable) {
|
||||||
path = with pkgs; [ wrappedSlurm coreutils ];
|
path = with pkgs; [ wrappedSlurm coreutils ]
|
||||||
|
++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "systemd-tmpfiles-clean.service" ];
|
after = [ "systemd-tmpfiles-clean.service" ];
|
||||||
|
@ -152,7 +170,8 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.slurmctld = mkIf (cfg.server.enable) {
|
systemd.services.slurmctld = mkIf (cfg.server.enable) {
|
||||||
path = with pkgs; [ wrappedSlurm munge coreutils ];
|
path = with pkgs; [ wrappedSlurm munge coreutils ]
|
||||||
|
++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" "munged.service" ];
|
after = [ "network.target" "munged.service" ];
|
||||||
|
|
|
@ -4,6 +4,31 @@ with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.buildkite-agent;
|
cfg = config.services.buildkite-agent;
|
||||||
|
|
||||||
|
mkHookOption = { name, description, example ? null }: {
|
||||||
|
inherit name;
|
||||||
|
value = mkOption {
|
||||||
|
default = null;
|
||||||
|
inherit description;
|
||||||
|
type = types.nullOr types.lines;
|
||||||
|
} // (if example == null then {} else { inherit example; });
|
||||||
|
};
|
||||||
|
mkHookOptions = hooks: listToAttrs (map mkHookOption hooks);
|
||||||
|
|
||||||
|
hooksDir = let
|
||||||
|
mkHookEntry = name: value: ''
|
||||||
|
cat > $out/${name} <<EOF
|
||||||
|
#! ${pkgs.stdenv.shell}
|
||||||
|
set -e
|
||||||
|
${value}
|
||||||
|
EOF
|
||||||
|
chmod 755 $out/${name}
|
||||||
|
'';
|
||||||
|
in pkgs.runCommand "buildkite-agent-hooks" {} ''
|
||||||
|
mkdir $out
|
||||||
|
${concatStringsSep "\n" (mapAttrsToList mkHookEntry (filterAttrs (n: v: v != null) cfg.hooks))}
|
||||||
|
'';
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -43,25 +68,28 @@ in
|
||||||
|
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
default = "%hostname-%n";
|
||||||
description = ''
|
description = ''
|
||||||
The name of the agent.
|
The name of the agent.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
hooksPath = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = "${pkgs.buildkite-agent}/share/hooks";
|
|
||||||
defaultText = "${pkgs.buildkite-agent}/share/hooks";
|
|
||||||
description = ''
|
|
||||||
Path to the directory storing the hooks.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
meta-data = mkOption {
|
meta-data = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
|
example = "queue=default,docker=true,ruby2=true";
|
||||||
description = ''
|
description = ''
|
||||||
Meta data for the agent.
|
Meta data for the agent. This is a comma-separated list of
|
||||||
|
<code>key=value</code> pairs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
example = "debug=true";
|
||||||
|
description = ''
|
||||||
|
Extra lines to be added verbatim to the configuration file.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,6 +113,74 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hooks = mkHookOptions [
|
||||||
|
{ name = "checkout";
|
||||||
|
description = ''
|
||||||
|
The `checkout` hook script will replace the default checkout routine of the
|
||||||
|
bootstrap.sh script. You can use this hook to do your own SCM checkout
|
||||||
|
behaviour
|
||||||
|
''; }
|
||||||
|
{ name = "command";
|
||||||
|
description = ''
|
||||||
|
The `command` hook script will replace the default implementation of running
|
||||||
|
the build command.
|
||||||
|
''; }
|
||||||
|
{ name = "environment";
|
||||||
|
description = ''
|
||||||
|
The `environment` hook will run before all other commands, and can be used
|
||||||
|
to set up secrets, data, etc. Anything exported in hooks will be available
|
||||||
|
to the build script.
|
||||||
|
|
||||||
|
Note: the contents of this file will be copied to the world-readable
|
||||||
|
Nix store.
|
||||||
|
'';
|
||||||
|
example = ''
|
||||||
|
export SECRET_VAR=`head -1 /run/keys/secret`
|
||||||
|
''; }
|
||||||
|
{ name = "post-artifact";
|
||||||
|
description = ''
|
||||||
|
The `post-artifact` hook will run just after artifacts are uploaded
|
||||||
|
''; }
|
||||||
|
{ name = "post-checkout";
|
||||||
|
description = ''
|
||||||
|
The `post-checkout` hook will run after the bootstrap script has checked out
|
||||||
|
your projects source code.
|
||||||
|
''; }
|
||||||
|
{ name = "post-command";
|
||||||
|
description = ''
|
||||||
|
The `post-command` hook will run after the bootstrap script has run your
|
||||||
|
build commands
|
||||||
|
''; }
|
||||||
|
{ name = "pre-artifact";
|
||||||
|
description = ''
|
||||||
|
The `pre-artifact` hook will run just before artifacts are uploaded
|
||||||
|
''; }
|
||||||
|
{ name = "pre-checkout";
|
||||||
|
description = ''
|
||||||
|
The `pre-checkout` hook will run just before your projects source code is
|
||||||
|
checked out from your SCM provider
|
||||||
|
''; }
|
||||||
|
{ name = "pre-command";
|
||||||
|
description = ''
|
||||||
|
The `pre-command` hook will run just before your build command runs
|
||||||
|
''; }
|
||||||
|
{ name = "pre-exit";
|
||||||
|
description = ''
|
||||||
|
The `pre-exit` hook will run just before your build job finishes
|
||||||
|
''; }
|
||||||
|
];
|
||||||
|
|
||||||
|
hooksPath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = hooksDir;
|
||||||
|
defaultText = "generated from services.buildkite-agent.hooks";
|
||||||
|
description = ''
|
||||||
|
Path to the directory storing the hooks.
|
||||||
|
Consider using <option>services.buildkite-agent.hooks.<name></option>
|
||||||
|
instead.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,13 +196,10 @@ in
|
||||||
environment.systemPackages = [ cfg.package ];
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
|
||||||
systemd.services.buildkite-agent =
|
systemd.services.buildkite-agent =
|
||||||
let copy = x: target: perms:
|
|
||||||
"cp -f ${x} ${target}; ${pkgs.coreutils}/bin/chmod ${toString perms} ${target}; ";
|
|
||||||
in
|
|
||||||
{ description = "Buildkite Agent";
|
{ description = "Buildkite Agent";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
path = cfg.runtimePackages;
|
path = cfg.runtimePackages ++ [ pkgs.coreutils ];
|
||||||
environment = config.networking.proxy.envVars // {
|
environment = config.networking.proxy.envVars // {
|
||||||
HOME = cfg.dataDir;
|
HOME = cfg.dataDir;
|
||||||
NIX_REMOTE = "daemon";
|
NIX_REMOTE = "daemon";
|
||||||
|
@ -114,10 +207,14 @@ in
|
||||||
|
|
||||||
## NB: maximum care is taken so that secrets (ssh keys and the CI token)
|
## NB: maximum care is taken so that secrets (ssh keys and the CI token)
|
||||||
## don't end up in the Nix store.
|
## don't end up in the Nix store.
|
||||||
preStart = ''
|
preStart = let
|
||||||
${pkgs.coreutils}/bin/mkdir -m 0700 -p ${cfg.dataDir}/.ssh
|
sshDir = "${cfg.dataDir}/.ssh";
|
||||||
${copy (toString cfg.openssh.privateKeyPath) "${cfg.dataDir}/.ssh/id_rsa" 600}
|
in
|
||||||
${copy (toString cfg.openssh.publicKeyPath) "${cfg.dataDir}/.ssh/id_rsa.pub" 600}
|
''
|
||||||
|
mkdir -m 0700 -p "${sshDir}"
|
||||||
|
cp -f "${toString cfg.openssh.privateKeyPath}" "${sshDir}/id_rsa"
|
||||||
|
cp -f "${toString cfg.openssh.publicKeyPath}" "${sshDir}/id_rsa.pub"
|
||||||
|
chmod 600 "${sshDir}"/id_rsa*
|
||||||
|
|
||||||
cat > "${cfg.dataDir}/buildkite-agent.cfg" <<EOF
|
cat > "${cfg.dataDir}/buildkite-agent.cfg" <<EOF
|
||||||
token="$(cat ${toString cfg.tokenPath})"
|
token="$(cat ${toString cfg.tokenPath})"
|
||||||
|
@ -125,7 +222,7 @@ in
|
||||||
meta-data="${cfg.meta-data}"
|
meta-data="${cfg.meta-data}"
|
||||||
build-path="${cfg.dataDir}/builds"
|
build-path="${cfg.dataDir}/builds"
|
||||||
hooks-path="${cfg.hooksPath}"
|
hooks-path="${cfg.hooksPath}"
|
||||||
bootstrap-script="${pkgs.buildkite-agent}/share/bootstrap.sh"
|
${cfg.extraConfig}
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -137,6 +234,15 @@ in
|
||||||
TimeoutSec = 10;
|
TimeoutSec = 10;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{ assertion = cfg.hooksPath == hooksDir || all isNull (attrValues cfg.hooks);
|
||||||
|
message = ''
|
||||||
|
Options `services.buildkite-agent.hooksPath' and
|
||||||
|
`services.buildkite-agent.hooks.<name>' are mutually exclusive.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
imports = [
|
imports = [
|
||||||
(mkRenamedOptionModule [ "services" "buildkite-agent" "token" ] [ "services" "buildkite-agent" "tokenPath" ])
|
(mkRenamedOptionModule [ "services" "buildkite-agent" "token" ] [ "services" "buildkite-agent" "tokenPath" ])
|
||||||
|
|
|
@ -289,10 +289,10 @@ in
|
||||||
# Create initial databases
|
# Create initial databases
|
||||||
if ! test -e "${cfg.dataDir}/${database.name}"; then
|
if ! test -e "${cfg.dataDir}/${database.name}"; then
|
||||||
echo "Creating initial database: ${database.name}"
|
echo "Creating initial database: ${database.name}"
|
||||||
( echo "create database ${database.name};"
|
( echo "create database `${database.name}`;"
|
||||||
|
|
||||||
${optionalString (database ? "schema") ''
|
${optionalString (database ? "schema") ''
|
||||||
echo "use ${database.name};"
|
echo "use `${database.name}`;"
|
||||||
|
|
||||||
if [ -f "${database.schema}" ]
|
if [ -f "${database.schema}" ]
|
||||||
then
|
then
|
||||||
|
|
23
nixos/modules/services/desktops/pipewire.nix
Normal file
23
nixos/modules/services/desktops/pipewire.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# pipewire service.
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
###### interface
|
||||||
|
options = {
|
||||||
|
services.pipewire = {
|
||||||
|
enable = mkEnableOption "pipewire service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
config = mkIf config.services.pipewire.enable {
|
||||||
|
environment.systemPackages = [ pkgs.pipewire ];
|
||||||
|
|
||||||
|
systemd.packages = [ pkgs.pipewire ];
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with lib.maintainers; [ jtojnar ];
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ let
|
||||||
''
|
''
|
||||||
fn=$out/${name}
|
fn=$out/${name}
|
||||||
echo "event=${handler.event}" > $fn
|
echo "event=${handler.event}" > $fn
|
||||||
echo "action=${pkgs.writeScript "${name}.sh" (concatStringsSep "\n" [ "#! ${pkgs.bash}/bin/sh" handler.action ])}" >> $fn
|
echo "action=${pkgs.writeShellScriptBin "${name}.sh" handler.action }/bin/${name}.sh '%e'" >> $fn
|
||||||
'';
|
'';
|
||||||
in concatStringsSep "\n" (mapAttrsToList f (canonicalHandlers // config.services.acpid.handlers))
|
in concatStringsSep "\n" (mapAttrsToList f (canonicalHandlers // config.services.acpid.handlers))
|
||||||
}
|
}
|
||||||
|
@ -69,11 +69,33 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
description = "Event handlers.";
|
description = ''
|
||||||
|
Event handlers.
|
||||||
|
|
||||||
|
<note><para>
|
||||||
|
Handler can be a single command.
|
||||||
|
</para></note>
|
||||||
|
'';
|
||||||
default = {};
|
default = {};
|
||||||
example = { mute = { event = "button/mute.*"; action = "amixer set Master toggle"; }; };
|
example = {
|
||||||
|
ac-power = {
|
||||||
|
event = "ac_adapter/*";
|
||||||
|
action = ''
|
||||||
|
vals=($1) # space separated string to array of multiple values
|
||||||
|
case ''${vals[3]} in
|
||||||
|
00000000)
|
||||||
|
echo unplugged >> /tmp/acpi.log
|
||||||
|
;;
|
||||||
|
00000001)
|
||||||
|
echo plugged in >> /tmp/acpi.log
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo unknown >> /tmp/acpi.log
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
powerEventCommands = mkOption {
|
powerEventCommands = mkOption {
|
||||||
|
|
|
@ -87,4 +87,8 @@ in {
|
||||||
"d /var/lib/fwupd 0755 root root -"
|
"d /var/lib/fwupd 0755 root root -"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
maintainers = pkgs.fwupd.maintainers;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ let kernel = config.boot.kernelPackages; in
|
||||||
###### implementation
|
###### implementation
|
||||||
|
|
||||||
config = lib.mkIf config.hardware.nvidiaOptimus.disable {
|
config = lib.mkIf config.hardware.nvidiaOptimus.disable {
|
||||||
boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb"];
|
boot.blacklistedKernelModules = ["nouveau" "nvidia" "nvidiafb" "nvidia-drm"];
|
||||||
boot.kernelModules = [ "bbswitch" ];
|
boot.kernelModules = [ "bbswitch" ];
|
||||||
boot.extraModulePackages = [ kernel.bbswitch ];
|
boot.extraModulePackages = [ kernel.bbswitch ];
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
mailboxConfig = mailbox: ''
|
mailboxConfig = mailbox: ''
|
||||||
mailbox ${mailbox.name} {
|
mailbox "${mailbox.name}" {
|
||||||
auto = ${toString mailbox.auto}
|
auto = ${toString mailbox.auto}
|
||||||
'' + optionalString (mailbox.specialUse != null) ''
|
'' + optionalString (mailbox.specialUse != null) ''
|
||||||
special_use = \${toString mailbox.specialUse}
|
special_use = \${toString mailbox.specialUse}
|
||||||
|
@ -113,7 +113,7 @@ let
|
||||||
mailboxes = { lib, pkgs, ... }: {
|
mailboxes = { lib, pkgs, ... }: {
|
||||||
options = {
|
options = {
|
||||||
name = mkOption {
|
name = mkOption {
|
||||||
type = types.str;
|
type = types.strMatching ''[^"]+'';
|
||||||
example = "Spam";
|
example = "Spam";
|
||||||
description = "The name of the mailbox.";
|
description = "The name of the mailbox.";
|
||||||
};
|
};
|
||||||
|
|
|
@ -414,7 +414,10 @@ in
|
||||||
postmasterAlias = mkOption {
|
postmasterAlias = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "root";
|
default = "root";
|
||||||
description = "Who should receive postmaster e-mail.";
|
description = "
|
||||||
|
Who should receive postmaster e-mail. Multiple values can be added by
|
||||||
|
separating values with comma.
|
||||||
|
";
|
||||||
};
|
};
|
||||||
|
|
||||||
rootAlias = mkOption {
|
rootAlias = mkOption {
|
||||||
|
@ -422,6 +425,7 @@ in
|
||||||
default = "";
|
default = "";
|
||||||
description = "
|
description = "
|
||||||
Who should receive root e-mail. Blank for no redirection.
|
Who should receive root e-mail. Blank for no redirection.
|
||||||
|
Multiple values can be added by separating values with comma.
|
||||||
";
|
";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,150 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, options, pkgs, lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
cfg = config.services.rspamd;
|
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"}";
|
||||||
|
};
|
||||||
|
|
||||||
|
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"
|
rspamdConfFile = pkgs.writeText "rspamd.conf"
|
||||||
''
|
''
|
||||||
|
@ -22,19 +160,33 @@ let
|
||||||
.include "$CONFDIR/logging.inc"
|
.include "$CONFDIR/logging.inc"
|
||||||
}
|
}
|
||||||
|
|
||||||
worker {
|
${concatStringsSep "\n" (mapAttrsToList (name: value: ''
|
||||||
${mkBindSockets cfg.bindSocket}
|
worker ${optionalString (value.name != "normal" && value.name != "controller") "${value.name}"} {
|
||||||
.include "$CONFDIR/worker-normal.inc"
|
type = "${value.type}";
|
||||||
}
|
${optionalString (value.enable != null)
|
||||||
|
"enabled = ${if value.enable != false then "yes" else "no"};"}
|
||||||
worker {
|
${mkBindSockets value.enable value.bindSockets}
|
||||||
${mkBindSockets cfg.bindUISocket}
|
${optionalString (value.count != null) "count = ${toString value.count};"}
|
||||||
.include "$CONFDIR/worker-controller.inc"
|
${concatStringsSep "\n " (map (each: ".include \"${each}\"") value.includes)}
|
||||||
|
${value.extraConfig}
|
||||||
}
|
}
|
||||||
|
'') cfg.workers)}
|
||||||
|
|
||||||
${cfg.extraConfig}
|
${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
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -48,36 +200,43 @@ in
|
||||||
enable = mkEnableOption "Whether to run the rspamd daemon.";
|
enable = mkEnableOption "Whether to run the rspamd daemon.";
|
||||||
|
|
||||||
debug = mkOption {
|
debug = mkOption {
|
||||||
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "Whether to run the rspamd daemon in debug mode.";
|
description = "Whether to run the rspamd daemon in debug mode.";
|
||||||
};
|
};
|
||||||
|
|
||||||
bindSocket = mkOption {
|
socketActivation = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.bool;
|
||||||
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}"
|
|
||||||
]'';
|
|
||||||
description = ''
|
description = ''
|
||||||
List of sockets to listen, in format acceptable by rspamd
|
Enable systemd socket activation for rspamd.
|
||||||
'';
|
|
||||||
example = ''
|
|
||||||
bindSocket = [
|
|
||||||
"/run/rspamd.sock mode=0666 owner=rspamd"
|
|
||||||
"*:11333"
|
|
||||||
];
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
bindUISocket = mkOption {
|
workers = mkOption {
|
||||||
type = types.listOf types.str;
|
type = with types; attrsOf (submodule workerOpts);
|
||||||
default = [
|
|
||||||
"localhost:11334"
|
|
||||||
];
|
|
||||||
description = ''
|
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 {
|
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'.
|
# Allow users to run 'rspamc' and 'rspamadm'.
|
||||||
environment.systemPackages = [ pkgs.rspamd ];
|
environment.systemPackages = [ pkgs.rspamd ];
|
||||||
|
|
||||||
|
@ -128,17 +294,22 @@ in
|
||||||
gid = config.ids.gids.rspamd;
|
gid = config.ids.gids.rspamd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.etc."rspamd.conf".source = rspamdConfFile;
|
||||||
|
|
||||||
systemd.services.rspamd = {
|
systemd.services.rspamd = {
|
||||||
description = "Rspamd Service";
|
description = "Rspamd Service";
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = mkIf (!cfg.socketActivation) [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ] ++
|
||||||
|
(if cfg.socketActivation then allSocketNames else []);
|
||||||
|
requires = mkIf cfg.socketActivation allSocketNames;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
|
ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
RuntimeDirectory = "rspamd";
|
RuntimeDirectory = "rspamd";
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
|
Sockets = mkIf cfg.socketActivation (concatStringsSep " " allSocketNames);
|
||||||
};
|
};
|
||||||
|
|
||||||
preStart = ''
|
preStart = ''
|
||||||
|
@ -146,5 +317,25 @@ in
|
||||||
${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /var/lib/rspamd
|
${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" ])
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,27 @@ let
|
||||||
|
|
||||||
availableComponents = pkgs.home-assistant.availableComponents;
|
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
|
# Returns whether component is used in config
|
||||||
useComponent = component: hasAttrByPath (splitString "." component) cfg.config;
|
useComponent = component:
|
||||||
|
hasAttrByPath (splitString "." component) cfg.config
|
||||||
|
|| useComponentPlatform component;
|
||||||
|
|
||||||
# List of components used in config
|
# List of components used in config
|
||||||
extraComponents = filter useComponent availableComponents;
|
extraComponents = filter useComponent availableComponents;
|
||||||
|
|
|
@ -16,10 +16,10 @@ let
|
||||||
It isn't perfect, but it seems to cover a vast majority of use cases.
|
It isn't perfect, but it seems to cover a vast majority of use cases.
|
||||||
Caveat: even if the package is reached by a different means,
|
Caveat: even if the package is reached by a different means,
|
||||||
the path above will be shown and not e.g. `${config.services.foo.package}`. */
|
the path above will be shown and not e.g. `${config.services.foo.package}`. */
|
||||||
manual = import ../../../doc/manual {
|
manual = import ../../../doc/manual rec {
|
||||||
inherit pkgs config;
|
inherit pkgs config;
|
||||||
version = config.system.nixosRelease;
|
version = config.system.nixos.release;
|
||||||
revision = "release-${config.system.nixosRelease}";
|
revision = "release-${version}";
|
||||||
options =
|
options =
|
||||||
let
|
let
|
||||||
scrubbedEval = evalModules {
|
scrubbedEval = evalModules {
|
||||||
|
|
31
nixos/modules/services/misc/novacomd.nix
Normal file
31
nixos/modules/services/misc/novacomd.nix
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.novacomd;
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
options = {
|
||||||
|
services.novacomd = {
|
||||||
|
enable = mkEnableOption "Novacom service for connecting to WebOS devices";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ pkgs.webos.novacom ];
|
||||||
|
|
||||||
|
systemd.services.novacomd = {
|
||||||
|
description = "Novacom WebOS daemon";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.webos.novacomd}/sbin/novacomd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with maintainers; [ dtzWill ];
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ let
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-i) echo "nixos";;
|
-i) echo "nixos";;
|
||||||
-r) echo "${config.system.nixosVersion}";;
|
-r) echo "${config.system.nixos.version}";;
|
||||||
esac
|
esac
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
|
|
|
@ -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 {
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [cfg.package];
|
||||||
|
|
||||||
systemd.services.zookeeper = {
|
systemd.services.zookeeper = {
|
||||||
description = "Zookeeper Daemon";
|
description = "Zookeeper Daemon";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
@ -118,7 +127,7 @@ in {
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = ''
|
ExecStart = ''
|
||||||
${pkgs.jre}/bin/java \
|
${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} \
|
${escapeShellArgs cfg.extraCmdLineOptions} \
|
||||||
-Dzookeeper.datadir.autocreate=false \
|
-Dzookeeper.datadir.autocreate=false \
|
||||||
${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
|
${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
|
||||||
|
|
|
@ -111,11 +111,11 @@ in {
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
script = ''
|
script = ''
|
||||||
${pkgs.prometheus-alertmanager.bin}/bin/alertmanager \
|
${pkgs.prometheus-alertmanager.bin}/bin/alertmanager \
|
||||||
-config.file ${alertmanagerYml} \
|
--config.file ${alertmanagerYml} \
|
||||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||||
-log.level ${cfg.logLevel} \
|
--log.level ${cfg.logLevel} \
|
||||||
${optionalString (cfg.webExternalUrl != null) ''-web.external-url ${cfg.webExternalUrl} \''}
|
${optionalString (cfg.webExternalUrl != null) ''--web.external-url ${cfg.webExternalUrl} \''}
|
||||||
${optionalString (cfg.logFormat != null) "-log.format ${cfg.logFormat}"}
|
${optionalString (cfg.logFormat != null) "--log.format ${cfg.logFormat}"}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib) mkOption mkIf;
|
|
||||||
|
|
||||||
cfg = config.services.openafsClient;
|
|
||||||
|
|
||||||
cellServDB = pkgs.fetchurl {
|
|
||||||
url = http://dl.central.org/dl/cellservdb/CellServDB.2017-03-14;
|
|
||||||
sha256 = "1197z6c5xrijgf66rhaymnm5cvyg2yiy1i20y4ah4mrzmjx0m7sc";
|
|
||||||
};
|
|
||||||
|
|
||||||
afsConfig = pkgs.runCommand "afsconfig" {} ''
|
|
||||||
mkdir -p $out
|
|
||||||
echo ${cfg.cellName} > $out/ThisCell
|
|
||||||
cp ${cellServDB} $out/CellServDB
|
|
||||||
echo "/afs:${cfg.cacheDirectory}:${cfg.cacheSize}" > $out/cacheinfo
|
|
||||||
'';
|
|
||||||
|
|
||||||
openafsPkgs = config.boot.kernelPackages.openafsClient;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
###### interface
|
|
||||||
|
|
||||||
options = {
|
|
||||||
|
|
||||||
services.openafsClient = {
|
|
||||||
|
|
||||||
enable = mkOption {
|
|
||||||
default = false;
|
|
||||||
description = "Whether to enable the OpenAFS client.";
|
|
||||||
};
|
|
||||||
|
|
||||||
cellName = mkOption {
|
|
||||||
default = "grand.central.org";
|
|
||||||
description = "Cell name.";
|
|
||||||
};
|
|
||||||
|
|
||||||
cacheSize = mkOption {
|
|
||||||
default = "100000";
|
|
||||||
description = "Cache size.";
|
|
||||||
};
|
|
||||||
|
|
||||||
cacheDirectory = mkOption {
|
|
||||||
default = "/var/cache/openafs";
|
|
||||||
description = "Cache directory.";
|
|
||||||
};
|
|
||||||
|
|
||||||
crypt = mkOption {
|
|
||||||
default = false;
|
|
||||||
description = "Whether to enable (weak) protocol encryption.";
|
|
||||||
};
|
|
||||||
|
|
||||||
sparse = mkOption {
|
|
||||||
default = false;
|
|
||||||
description = "Minimal cell list in /afs.";
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
###### implementation
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
environment.systemPackages = [ openafsPkgs ];
|
|
||||||
|
|
||||||
environment.etc = [
|
|
||||||
{ source = afsConfig;
|
|
||||||
target = "openafs";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
systemd.services.afsd = {
|
|
||||||
description = "AFS client";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
serviceConfig = { RemainAfterExit = true; };
|
|
||||||
|
|
||||||
preStart = ''
|
|
||||||
mkdir -p -m 0755 /afs
|
|
||||||
mkdir -m 0700 -p ${cfg.cacheDirectory}
|
|
||||||
${pkgs.kmod}/bin/insmod ${openafsPkgs}/lib/openafs/libafs-*.ko || true
|
|
||||||
${openafsPkgs}/sbin/afsd -confdir ${afsConfig} -cachedir ${cfg.cacheDirectory} ${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} -fakestat -afsdb
|
|
||||||
${openafsPkgs}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Doing this in preStop, because after these commands AFS is basically
|
|
||||||
# stopped, so systemd has nothing to do, just noticing it. If done in
|
|
||||||
# postStop, then we get a hang + kernel oops, because AFS can't be
|
|
||||||
# stopped simply by sending signals to processes.
|
|
||||||
preStop = ''
|
|
||||||
${pkgs.utillinux}/bin/umount /afs
|
|
||||||
${openafsPkgs}/sbin/afsd -shutdown
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
239
nixos/modules/services/network-filesystems/openafs/client.nix
Normal file
239
nixos/modules/services/network-filesystems/openafs/client.nix
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with import ./lib.nix { inherit lib; };
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) getBin mkOption mkIf optionalString singleton types;
|
||||||
|
|
||||||
|
cfg = config.services.openafsClient;
|
||||||
|
|
||||||
|
cellServDB = pkgs.fetchurl {
|
||||||
|
url = http://dl.central.org/dl/cellservdb/CellServDB.2017-03-14;
|
||||||
|
sha256 = "1197z6c5xrijgf66rhaymnm5cvyg2yiy1i20y4ah4mrzmjx0m7sc";
|
||||||
|
};
|
||||||
|
|
||||||
|
clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.cellServDB);
|
||||||
|
|
||||||
|
afsConfig = pkgs.runCommand "afsconfig" {} ''
|
||||||
|
mkdir -p $out
|
||||||
|
echo ${cfg.cellName} > $out/ThisCell
|
||||||
|
cat ${cellServDB} ${clientServDB} > $out/CellServDB
|
||||||
|
echo "${cfg.mountPoint}:${cfg.cache.directory}:${toString cfg.cache.blocks}" > $out/cacheinfo
|
||||||
|
'';
|
||||||
|
|
||||||
|
openafsMod = config.boot.kernelPackages.openafs;
|
||||||
|
openafsBin = lib.getBin pkgs.openafs;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.openafsClient = {
|
||||||
|
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether to enable the OpenAFS client.";
|
||||||
|
};
|
||||||
|
|
||||||
|
afsdb = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Resolve cells via AFSDB DNS records.";
|
||||||
|
};
|
||||||
|
|
||||||
|
cellName = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Cell name.";
|
||||||
|
example = "grand.central.org";
|
||||||
|
};
|
||||||
|
|
||||||
|
cellServDB = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = with types; listOf (submodule { options = cellServDBConfig; });
|
||||||
|
description = ''
|
||||||
|
This cell's database server records, added to the global
|
||||||
|
CellServDB. See CellServDB(5) man page for syntax. Ignored when
|
||||||
|
<literal>afsdb</literal> is set to <literal>true</literal>.
|
||||||
|
'';
|
||||||
|
example = ''
|
||||||
|
[ { ip = "1.2.3.4"; dnsname = "first.afsdb.server.dns.fqdn.org"; }
|
||||||
|
{ ip = "2.3.4.5"; dnsname = "second.afsdb.server.dns.fqdn.org"; }
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
cache = {
|
||||||
|
blocks = mkOption {
|
||||||
|
default = 100000;
|
||||||
|
type = types.int;
|
||||||
|
description = "Cache size in 1KB blocks.";
|
||||||
|
};
|
||||||
|
|
||||||
|
chunksize = mkOption {
|
||||||
|
default = 0;
|
||||||
|
type = types.ints.between 0 30;
|
||||||
|
description = ''
|
||||||
|
Size of each cache chunk given in powers of
|
||||||
|
2. <literal>0</literal> resets the chunk size to its default
|
||||||
|
values (13 (8 KB) for memcache, 18-20 (256 KB to 1 MB) for
|
||||||
|
diskcache). Maximum value is 30. Important performance
|
||||||
|
parameter. Set to higher values when dealing with large files.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
directory = mkOption {
|
||||||
|
default = "/var/cache/openafs";
|
||||||
|
type = types.str;
|
||||||
|
description = "Cache directory.";
|
||||||
|
};
|
||||||
|
|
||||||
|
diskless = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Use in-memory cache for diskless machines. Has no real
|
||||||
|
performance benefit anymore.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
crypt = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether to enable (weak) protocol encryption.";
|
||||||
|
};
|
||||||
|
|
||||||
|
daemons = mkOption {
|
||||||
|
default = 2;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
Number of daemons to serve user requests. Numbers higher than 6
|
||||||
|
usually do no increase performance. Default is sufficient for up
|
||||||
|
to five concurrent users.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
fakestat = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Return fake data on stat() calls. If <literal>true</literal>,
|
||||||
|
always do so. If <literal>false</literal>, only do so for
|
||||||
|
cross-cell mounts (as these are potentially expensive).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
inumcalc = mkOption {
|
||||||
|
default = "compat";
|
||||||
|
type = types.strMatching "compat|md5";
|
||||||
|
description = ''
|
||||||
|
Inode calculation method. <literal>compat</literal> is
|
||||||
|
computationally less expensive, but <literal>md5</literal> greatly
|
||||||
|
reduces the likelihood of inode collisions in larger scenarios
|
||||||
|
involving multiple cells mounted into one AFS space.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mountPoint = mkOption {
|
||||||
|
default = "/afs";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Mountpoint of the AFS file tree, conventionally
|
||||||
|
<literal>/afs</literal>. When set to a different value, only
|
||||||
|
cross-cells that use the same value can be accessed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sparse = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Minimal cell list in /afs.";
|
||||||
|
};
|
||||||
|
|
||||||
|
startDisconnected = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Start up in disconnected mode. You need to execute
|
||||||
|
<literal>fs disco online</literal> (as root) to switch to
|
||||||
|
connected mode. Useful for roaming devices.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{ assertion = cfg.afsdb || cfg.cellServDB != [];
|
||||||
|
message = "You should specify all cell-local database servers in config.services.openafsClient.cellServDB or set config.services.openafsClient.afsdb.";
|
||||||
|
}
|
||||||
|
{ assertion = cfg.cellName != "";
|
||||||
|
message = "You must specify the local cell name in config.services.openafsClient.cellName.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.openafs ];
|
||||||
|
|
||||||
|
environment.etc = {
|
||||||
|
clientCellServDB = {
|
||||||
|
source = pkgs.runCommand "CellServDB" {} ''
|
||||||
|
cat ${cellServDB} ${clientServDB} > $out
|
||||||
|
'';
|
||||||
|
target = "openafs/CellServDB";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
clientCell = {
|
||||||
|
text = ''
|
||||||
|
${cfg.cellName}
|
||||||
|
'';
|
||||||
|
target = "openafs/ThisCell";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.afsd = {
|
||||||
|
description = "AFS client";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = singleton (if cfg.startDisconnected then "network.target" else "network-online.target");
|
||||||
|
serviceConfig = { RemainAfterExit = true; };
|
||||||
|
restartIfChanged = false;
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
mkdir -p -m 0755 ${cfg.mountPoint}
|
||||||
|
mkdir -m 0700 -p ${cfg.cache.directory}
|
||||||
|
${pkgs.kmod}/bin/insmod ${openafsMod}/lib/modules/*/extra/openafs/libafs.ko.xz
|
||||||
|
${openafsBin}/sbin/afsd \
|
||||||
|
-mountdir ${cfg.mountPoint} \
|
||||||
|
-confdir ${afsConfig} \
|
||||||
|
${optionalString (!cfg.cache.diskless) "-cachedir ${cfg.cache.directory}"} \
|
||||||
|
-blocks ${toString cfg.cache.blocks} \
|
||||||
|
-chunksize ${toString cfg.cache.chunksize} \
|
||||||
|
${optionalString cfg.cache.diskless "-memcache"} \
|
||||||
|
-inumcalc ${cfg.inumcalc} \
|
||||||
|
${if cfg.fakestat then "-fakestat-all" else "-fakestat"} \
|
||||||
|
${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} \
|
||||||
|
${optionalString cfg.afsdb "-afsdb"}
|
||||||
|
${openafsBin}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"}
|
||||||
|
${optionalString cfg.startDisconnected "${openafsBin}/bin/fs discon offline"}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Doing this in preStop, because after these commands AFS is basically
|
||||||
|
# stopped, so systemd has nothing to do, just noticing it. If done in
|
||||||
|
# postStop, then we get a hang + kernel oops, because AFS can't be
|
||||||
|
# stopped simply by sending signals to processes.
|
||||||
|
preStop = ''
|
||||||
|
${pkgs.utillinux}/bin/umount ${cfg.mountPoint}
|
||||||
|
${openafsBin}/sbin/afsd -shutdown
|
||||||
|
${pkgs.kmod}/sbin/rmmod libafs
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
28
nixos/modules/services/network-filesystems/openafs/lib.nix
Normal file
28
nixos/modules/services/network-filesystems/openafs/lib.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ lib, ...}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) concatStringsSep mkOption types;
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
|
||||||
|
mkCellServDB = cellName: db: ''
|
||||||
|
>${cellName}
|
||||||
|
'' + (concatStringsSep "\n" (map (dbm: if (dbm.ip != "" && dbm.dnsname != "") then dbm.ip + " #" + dbm.dnsname else "")
|
||||||
|
db));
|
||||||
|
|
||||||
|
# CellServDB configuration type
|
||||||
|
cellServDBConfig = {
|
||||||
|
ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
example = "1.2.3.4";
|
||||||
|
description = "IP Address of a database server";
|
||||||
|
};
|
||||||
|
dnsname = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
example = "afs.example.org";
|
||||||
|
description = "DNS full-qualified domain name of a database server";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
260
nixos/modules/services/network-filesystems/openafs/server.nix
Normal file
260
nixos/modules/services/network-filesystems/openafs/server.nix
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with import ./lib.nix { inherit lib; };
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) concatStringsSep intersperse mapAttrsToList mkForce mkIf mkMerge mkOption optionalString types;
|
||||||
|
|
||||||
|
bosConfig = pkgs.writeText "BosConfig" (''
|
||||||
|
restrictmode 1
|
||||||
|
restarttime 16 0 0 0 0
|
||||||
|
checkbintime 3 0 5 0 0
|
||||||
|
'' + (optionalString cfg.roles.database.enable ''
|
||||||
|
bnode simple vlserver 1
|
||||||
|
parm ${openafsBin}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs}
|
||||||
|
end
|
||||||
|
bnode simple ptserver 1
|
||||||
|
parm ${openafsBin}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs}
|
||||||
|
end
|
||||||
|
'') + (optionalString cfg.roles.fileserver.enable ''
|
||||||
|
bnode dafs dafs 1
|
||||||
|
parm ${openafsBin}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs}
|
||||||
|
parm ${openafsBin}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs}
|
||||||
|
parm ${openafsBin}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs}
|
||||||
|
parm ${openafsBin}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs}
|
||||||
|
end
|
||||||
|
'') + (optionalString (cfg.roles.database.enable && cfg.roles.backup.enable) ''
|
||||||
|
bnode simple buserver 1
|
||||||
|
parm ${openafsBin}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString (cfg.roles.backup.cellServDB != []) "-cellservdb /etc/openafs/backup/"}
|
||||||
|
end
|
||||||
|
''));
|
||||||
|
|
||||||
|
netInfo = if (cfg.advertisedAddresses != []) then
|
||||||
|
pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n")
|
||||||
|
else null;
|
||||||
|
|
||||||
|
buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.roles.backup.cellServDB);
|
||||||
|
|
||||||
|
cfg = config.services.openafsServer;
|
||||||
|
|
||||||
|
udpSizeStr = toString cfg.udpPacketSize;
|
||||||
|
|
||||||
|
openafsBin = lib.getBin pkgs.openafs;
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.openafsServer = {
|
||||||
|
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to enable the OpenAFS server. An OpenAFS server needs a
|
||||||
|
complex setup. So, be aware that enabling this service and setting
|
||||||
|
some options does not give you a turn-key-ready solution. You need
|
||||||
|
at least a running Kerberos 5 setup, as OpenAFS relies on it for
|
||||||
|
authentication. See the Guide "QuickStartUnix" coming with
|
||||||
|
<literal>pkgs.openafs.doc</literal> for complete setup
|
||||||
|
instructions.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
advertisedAddresses = mkOption {
|
||||||
|
default = [];
|
||||||
|
description = "List of IP addresses this server is advertised under. See NetInfo(5)";
|
||||||
|
};
|
||||||
|
|
||||||
|
cellName = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Cell name, this server will serve.";
|
||||||
|
example = "grand.central.org";
|
||||||
|
};
|
||||||
|
|
||||||
|
cellServDB = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
|
||||||
|
description = "Definition of all cell-local database server machines.";
|
||||||
|
};
|
||||||
|
|
||||||
|
roles = {
|
||||||
|
fileserver = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Fileserver role, serves files and volumes from its local storage.";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileserverArgs = mkOption {
|
||||||
|
default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the dafileserver process. See its man page.";
|
||||||
|
};
|
||||||
|
|
||||||
|
volserverArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the davolserver process. See its man page.";
|
||||||
|
example = "-sync never";
|
||||||
|
};
|
||||||
|
|
||||||
|
salvageserverArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the salvageserver process. See its man page.";
|
||||||
|
example = "-showlog";
|
||||||
|
};
|
||||||
|
|
||||||
|
salvagerArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the dasalvager process. See its man page.";
|
||||||
|
example = "-showlog -showmounts";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
database = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Database server role, maintains the Volume Location Database,
|
||||||
|
Protection Database (and Backup Database, see
|
||||||
|
<literal>backup</literal> role). There can be multiple
|
||||||
|
servers in the database role for replication, which then need
|
||||||
|
reliable network connection to each other.
|
||||||
|
|
||||||
|
Servers in this role appear in AFSDB DNS records or the
|
||||||
|
CellServDB.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
vlserverArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the vlserver process. See its man page.";
|
||||||
|
example = "-rxbind";
|
||||||
|
};
|
||||||
|
|
||||||
|
ptserverArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the ptserver process. See its man page.";
|
||||||
|
example = "-restricted -default_access S---- S-M---";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
backup = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
Backup server role. Use in conjunction with the
|
||||||
|
<literal>database</literal> role to maintain the Backup
|
||||||
|
Database. Normally only used in conjunction with tape storage
|
||||||
|
or IBM's Tivoli Storage Manager.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
buserverArgs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = "Arguments to the buserver process. See its man page.";
|
||||||
|
example = "-p 8";
|
||||||
|
};
|
||||||
|
|
||||||
|
cellServDB = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
|
||||||
|
description = ''
|
||||||
|
Definition of all cell-local backup database server machines.
|
||||||
|
Use this when your cell uses less backup database servers than
|
||||||
|
other database server machines.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dottedPrincipals= mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
If enabled, allow principal names containing (.) dots. Enabling
|
||||||
|
this has security implications!
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
udpPacketSize = mkOption {
|
||||||
|
default = 1310720;
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
UDP packet size to use in Bytes. Higher values can speed up
|
||||||
|
communications. The default of 1 MB is a sufficient in most
|
||||||
|
cases. Make sure to increase the kernel's UDP buffer size
|
||||||
|
accordingly via <literal>net.core(w|r|opt)mem_max</literal>
|
||||||
|
sysctl.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{ assertion = cfg.cellServDB != [];
|
||||||
|
message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB.";
|
||||||
|
}
|
||||||
|
{ assertion = cfg.cellName != "";
|
||||||
|
message = "You must specify the local cell name in config.services.openafsServer.cellName.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.openafs ];
|
||||||
|
|
||||||
|
environment.etc = {
|
||||||
|
bosConfig = {
|
||||||
|
source = bosConfig;
|
||||||
|
target = "openafs/BosConfig";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
cellServDB = {
|
||||||
|
text = mkCellServDB cfg.cellName cfg.cellServDB;
|
||||||
|
target = "openafs/server/CellServDB";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
thisCell = {
|
||||||
|
text = cfg.cellName;
|
||||||
|
target = "openafs/server/ThisCell";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
buCellServDB = {
|
||||||
|
enable = (cfg.roles.backup.cellServDB != []);
|
||||||
|
text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB;
|
||||||
|
target = "openafs/backup/CellServDB";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services = {
|
||||||
|
openafs-server = {
|
||||||
|
description = "OpenAFS server";
|
||||||
|
after = [ "syslog.target" "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
restartIfChanged = false;
|
||||||
|
unitConfig.ConditionPathExists = [ "/etc/openafs/server/rxkad.keytab" ];
|
||||||
|
preStart = ''
|
||||||
|
mkdir -m 0755 -p /var/openafs
|
||||||
|
${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"}
|
||||||
|
${optionalString (cfg.roles.backup.cellServDB != []) "cp ${buCellServDB}"}
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${openafsBin}/bin/bosserver -nofork";
|
||||||
|
ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -7,21 +7,27 @@ let
|
||||||
let
|
let
|
||||||
cfg = config.services.${variant};
|
cfg = config.services.${variant};
|
||||||
pkg = pkgs.${variant};
|
pkg = pkgs.${variant};
|
||||||
|
birdBin = if variant == "bird6" then "bird6" else "bird";
|
||||||
birdc = if variant == "bird6" then "birdc6" else "birdc";
|
birdc = if variant == "bird6" then "birdc6" else "birdc";
|
||||||
|
descr =
|
||||||
|
{ bird = "1.9.x with IPv4 suport";
|
||||||
|
bird6 = "1.9.x with IPv6 suport";
|
||||||
|
bird2 = "2.x";
|
||||||
|
}.${variant};
|
||||||
configFile = pkgs.stdenv.mkDerivation {
|
configFile = pkgs.stdenv.mkDerivation {
|
||||||
name = "${variant}.conf";
|
name = "${variant}.conf";
|
||||||
text = cfg.config;
|
text = cfg.config;
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
buildCommand = ''
|
buildCommand = ''
|
||||||
echo -n "$text" > $out
|
echo -n "$text" > $out
|
||||||
${pkg}/bin/${variant} -d -p -c $out
|
${pkg}/bin/${birdBin} -d -p -c $out
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
###### interface
|
###### interface
|
||||||
options = {
|
options = {
|
||||||
services.${variant} = {
|
services.${variant} = {
|
||||||
enable = mkEnableOption "BIRD Internet Routing Daemon";
|
enable = mkEnableOption "BIRD Internet Routing Daemon (${descr})";
|
||||||
config = mkOption {
|
config = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
description = ''
|
description = ''
|
||||||
|
@ -36,12 +42,12 @@ let
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
environment.systemPackages = [ pkg ];
|
environment.systemPackages = [ pkg ];
|
||||||
systemd.services.${variant} = {
|
systemd.services.${variant} = {
|
||||||
description = "BIRD Internet Routing Daemon";
|
description = "BIRD Internet Routing Daemon (${descr})";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "forking";
|
Type = "forking";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
ExecStart = "${pkg}/bin/${variant} -c ${configFile} -u ${variant} -g ${variant}";
|
ExecStart = "${pkg}/bin/${birdBin} -c ${configFile} -u ${variant} -g ${variant}";
|
||||||
ExecReload = "${pkg}/bin/${birdc} configure";
|
ExecReload = "${pkg}/bin/${birdc} configure";
|
||||||
ExecStop = "${pkg}/bin/${birdc} down";
|
ExecStop = "${pkg}/bin/${birdc} down";
|
||||||
CapabilityBoundingSet = [ "CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_SETUID" "CAP_SETGID"
|
CapabilityBoundingSet = [ "CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_SETUID" "CAP_SETGID"
|
||||||
|
@ -56,14 +62,15 @@ let
|
||||||
users = {
|
users = {
|
||||||
extraUsers.${variant} = {
|
extraUsers.${variant} = {
|
||||||
description = "BIRD Internet Routing Daemon user";
|
description = "BIRD Internet Routing Daemon user";
|
||||||
group = "${variant}";
|
group = variant;
|
||||||
};
|
};
|
||||||
extraGroups.${variant} = {};
|
extraGroups.${variant} = {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inherit (config.services) bird bird6;
|
in
|
||||||
in {
|
|
||||||
imports = [(generic "bird") (generic "bird6")];
|
{
|
||||||
|
imports = map generic [ "bird" "bird6" "bird2" ];
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,15 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extraFlags = mkOption {
|
||||||
|
type = with types; listOf string;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "--nodnsproxy" ];
|
||||||
|
description = ''
|
||||||
|
Extra flags to pass to connmand
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -81,7 +90,7 @@ in {
|
||||||
Type = "dbus";
|
Type = "dbus";
|
||||||
BusName = "net.connman";
|
BusName = "net.connman";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
ExecStart = "${pkgs.connman}/sbin/connmand --config=${configFile} --nodaemon";
|
ExecStart = "${pkgs.connman}/sbin/connmand --config=${configFile} --nodaemon ${toString cfg.extraFlags}";
|
||||||
StandardOutput = "null";
|
StandardOutput = "null";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,7 +47,7 @@ in
|
||||||
|
|
||||||
systemd.services.dante = {
|
systemd.services.dante = {
|
||||||
description = "Dante SOCKS v4 and v5 compatible proxy server";
|
description = "Dante SOCKS v4 and v5 compatible proxy server";
|
||||||
after = [ "network.target" ];
|
after = [ "network-online.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
|
|
@ -16,7 +16,7 @@ let
|
||||||
# Don't start dhcpcd on explicitly configured interfaces or on
|
# Don't start dhcpcd on explicitly configured interfaces or on
|
||||||
# interfaces that are part of a bridge, bond or sit device.
|
# interfaces that are part of a bridge, bond or sit device.
|
||||||
ignoredInterfaces =
|
ignoredInterfaces =
|
||||||
map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces)
|
map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces)
|
||||||
++ mapAttrsToList (i: _: i) config.networking.sits
|
++ mapAttrsToList (i: _: i) config.networking.sits
|
||||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
|
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
|
||||||
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
|
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
|
||||||
|
@ -156,11 +156,11 @@ in
|
||||||
systemd.services.dhcpcd = let
|
systemd.services.dhcpcd = let
|
||||||
cfgN = config.networking;
|
cfgN = config.networking;
|
||||||
hasDefaultGatewaySet = (cfgN.defaultGateway != null && cfgN.defaultGateway.address != "")
|
hasDefaultGatewaySet = (cfgN.defaultGateway != null && cfgN.defaultGateway.address != "")
|
||||||
|| (cfgN.defaultGateway6 != null && cfgN.defaultGateway6.address != "");
|
&& (!cfgN.enableIPv6 || (cfgN.defaultGateway6 != null && cfgN.defaultGateway6.address != ""));
|
||||||
in
|
in
|
||||||
{ description = "DHCP Client";
|
{ description = "DHCP Client";
|
||||||
|
|
||||||
wantedBy = optional (!hasDefaultGatewaySet) "network-online.target";
|
wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target";
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wants = [ "network.target" ];
|
wants = [ "network.target" ];
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ let
|
||||||
in
|
in
|
||||||
|
|
||||||
{
|
{
|
||||||
|
meta.maintainers = with lib.maintainers; [ nadrieril ];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
services.firefox.syncserver = {
|
services.firefox.syncserver = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
|
@ -70,18 +72,6 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
user = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "syncserver";
|
|
||||||
description = "User account under which syncserver runs.";
|
|
||||||
};
|
|
||||||
|
|
||||||
group = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "syncserver";
|
|
||||||
description = "Group account under which syncserver runs.";
|
|
||||||
};
|
|
||||||
|
|
||||||
publicUrl = mkOption {
|
publicUrl = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "http://localhost:5000/";
|
default = "http://localhost:5000/";
|
||||||
|
@ -137,7 +127,9 @@ in
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
systemd.services.syncserver = let
|
systemd.services.syncserver = let
|
||||||
syncServerEnv = pkgs.python.withPackages(ps: with ps; [ syncserver pasteScript ]);
|
syncServerEnv = pkgs.python.withPackages(ps: with ps; [ syncserver pasteScript requests ]);
|
||||||
|
user = "syncserver";
|
||||||
|
group = "syncserver";
|
||||||
in {
|
in {
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
description = "Firefox Sync Server";
|
description = "Firefox Sync Server";
|
||||||
|
@ -145,43 +137,43 @@ in
|
||||||
path = [ pkgs.coreutils syncServerEnv ];
|
path = [ pkgs.coreutils syncServerEnv ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
User = cfg.user;
|
User = user;
|
||||||
Group = cfg.group;
|
Group = group;
|
||||||
PermissionsStartOnly = true;
|
PermissionsStartOnly = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
preStart = ''
|
preStart = ''
|
||||||
if ! test -e ${cfg.privateConfig}; then
|
if ! test -e ${cfg.privateConfig}; then
|
||||||
mkdir -m 700 -p $(dirname ${cfg.privateConfig})
|
mkdir -p $(dirname ${cfg.privateConfig})
|
||||||
echo > ${cfg.privateConfig} '[syncserver]'
|
echo > ${cfg.privateConfig} '[syncserver]'
|
||||||
|
chmod 600 ${cfg.privateConfig}
|
||||||
echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')"
|
echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')"
|
||||||
fi
|
fi
|
||||||
chown ${cfg.user}:${cfg.group} ${cfg.privateConfig}
|
chmod 600 ${cfg.privateConfig}
|
||||||
|
chmod 755 $(dirname ${cfg.privateConfig})
|
||||||
|
chown ${user}:${group} ${cfg.privateConfig}
|
||||||
|
|
||||||
'' + optionalString (cfg.sqlUri == defaultSqlUri) ''
|
'' + optionalString (cfg.sqlUri == defaultSqlUri) ''
|
||||||
if ! test -e $(dirname ${defaultDbLocation}); then
|
if ! test -e $(dirname ${defaultDbLocation}); then
|
||||||
mkdir -m 700 -p $(dirname ${defaultDbLocation})
|
mkdir -m 700 -p $(dirname ${defaultDbLocation})
|
||||||
chown ${cfg.user}:${cfg.group} $(dirname ${defaultDbLocation})
|
chown ${user}:${group} $(dirname ${defaultDbLocation})
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Move previous database file if it exists
|
# Move previous database file if it exists
|
||||||
oldDb="/var/db/firefox-sync-server.db"
|
oldDb="/var/db/firefox-sync-server.db"
|
||||||
if test -f $oldDb; then
|
if test -f $oldDb; then
|
||||||
mv $oldDb ${defaultDbLocation}
|
mv $oldDb ${defaultDbLocation}
|
||||||
chown ${cfg.user}:${cfg.group} ${defaultDbLocation}
|
chown ${user}:${group} ${defaultDbLocation}
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
serviceConfig.ExecStart = "${syncServerEnv}/bin/paster serve ${syncServerIni}";
|
serviceConfig.ExecStart = "${syncServerEnv}/bin/paster serve ${syncServerIni}";
|
||||||
};
|
};
|
||||||
|
|
||||||
users.extraUsers = optionalAttrs (cfg.user == "syncserver")
|
users.users.syncserver = {
|
||||||
(singleton {
|
group = "syncserver";
|
||||||
name = "syncserver";
|
|
||||||
group = cfg.group;
|
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
});
|
};
|
||||||
|
|
||||||
users.extraGroups = optionalAttrs (cfg.group == "syncserver")
|
users.groups.syncserver = {};
|
||||||
(singleton {
|
|
||||||
name = "syncserver";
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
72
nixos/modules/services/networking/freeradius.nix
Normal file
72
nixos/modules/services/networking/freeradius.nix
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.freeradius;
|
||||||
|
|
||||||
|
freeradiusService = cfg:
|
||||||
|
{
|
||||||
|
description = "FreeRadius server";
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
after = ["network-online.target"];
|
||||||
|
wants = ["network-online.target"];
|
||||||
|
preStart = ''
|
||||||
|
${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
|
||||||
|
'';
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout -xx";
|
||||||
|
ExecReload = [
|
||||||
|
"${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
|
||||||
|
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
|
||||||
|
];
|
||||||
|
User = "radius";
|
||||||
|
ProtectSystem = "full";
|
||||||
|
ProtectHome = "on";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
freeradiusConfig = {
|
||||||
|
enable = mkEnableOption "the freeradius server";
|
||||||
|
|
||||||
|
configDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/etc/raddb";
|
||||||
|
description = ''
|
||||||
|
The path of the freeradius server configuration directory.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
services.freeradius = freeradiusConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf (cfg.enable) {
|
||||||
|
|
||||||
|
users = {
|
||||||
|
extraUsers.radius = {
|
||||||
|
/*uid = config.ids.uids.radius;*/
|
||||||
|
description = "Radius daemon user";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.freeradius = freeradiusService cfg;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -137,6 +137,8 @@ in
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
path = [ pkgs.gnunet pkgs.miniupnpc ];
|
path = [ pkgs.gnunet pkgs.miniupnpc ];
|
||||||
|
environment.TMPDIR = "/tmp";
|
||||||
|
serviceConfig.PrivateTemp = true;
|
||||||
serviceConfig.ExecStart = "${pkgs.gnunet}/lib/gnunet/libexec/gnunet-service-arm -c ${configFile}";
|
serviceConfig.ExecStart = "${pkgs.gnunet}/lib/gnunet/libexec/gnunet-service-arm -c ${configFile}";
|
||||||
serviceConfig.User = "gnunet";
|
serviceConfig.User = "gnunet";
|
||||||
serviceConfig.UMask = "0007";
|
serviceConfig.UMask = "0007";
|
||||||
|
|
|
@ -46,6 +46,15 @@ in
|
||||||
What addresses the server should listen on. (UDP+TCP 53)
|
What addresses the server should listen on. (UDP+TCP 53)
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
listenTLS = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [];
|
||||||
|
example = [ "198.51.100.1:853" "[2001:db8::1]:853" "853" ];
|
||||||
|
description = ''
|
||||||
|
Addresses on which kresd should provide DNS over TLS (see RFC 7858).
|
||||||
|
For detailed syntax see ListenStream in man systemd.socket.
|
||||||
|
'';
|
||||||
|
};
|
||||||
# TODO: perhaps options for more common stuff like cache size or forwarding
|
# TODO: perhaps options for more common stuff like cache size or forwarding
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,6 +84,18 @@ in
|
||||||
socketConfig.FreeBind = true;
|
socketConfig.FreeBind = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec {
|
||||||
|
wantedBy = [ "sockets.target" ];
|
||||||
|
before = wantedBy;
|
||||||
|
partOf = [ "kresd.socket" ];
|
||||||
|
listenStreams = cfg.listenTLS;
|
||||||
|
socketConfig = {
|
||||||
|
FileDescriptorName = "tls";
|
||||||
|
FreeBind = true;
|
||||||
|
Service = "kresd.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.sockets.kresd-control = rec {
|
systemd.sockets.kresd-control = rec {
|
||||||
wantedBy = [ "sockets.target" ];
|
wantedBy = [ "sockets.target" ];
|
||||||
before = wantedBy;
|
before = wantedBy;
|
||||||
|
@ -97,6 +118,8 @@ in
|
||||||
Type = "notify";
|
Type = "notify";
|
||||||
WorkingDirectory = cfg.cacheDir;
|
WorkingDirectory = cfg.cacheDir;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
|
Sockets = [ "kresd.socket" "kresd-control.socket" ]
|
||||||
|
++ optional (cfg.listenTLS != []) "kresd-tls.socket";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Trust anchor goes from dns-root-data by default.
|
# Trust anchor goes from dns-root-data by default.
|
||||||
|
|
238
nixos/modules/services/networking/monero.nix
Normal file
238
nixos/modules/services/networking/monero.nix
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.monero;
|
||||||
|
dataDir = "/var/lib/monero";
|
||||||
|
|
||||||
|
listToConf = option: list:
|
||||||
|
concatMapStrings (value: "${option}=${value}\n") list;
|
||||||
|
|
||||||
|
login = (cfg.rpc.user != null && cfg.rpc.password != null);
|
||||||
|
|
||||||
|
configFile = with cfg; pkgs.writeText "monero.conf" ''
|
||||||
|
log-file=/dev/stdout
|
||||||
|
data-dir=${dataDir}
|
||||||
|
|
||||||
|
${optionalString mining.enable ''
|
||||||
|
start-mining=${mining.address}
|
||||||
|
mining-threads=${toString mining.threads}
|
||||||
|
''}
|
||||||
|
|
||||||
|
rpc-bind-ip=${rpc.address}
|
||||||
|
rpc-bind-port=${toString rpc.port}
|
||||||
|
${optionalString login ''
|
||||||
|
rpc-login=${rpc.user}:${rpc.password}
|
||||||
|
''}
|
||||||
|
${optionalString rpc.restricted ''
|
||||||
|
restrict-rpc=1
|
||||||
|
''}
|
||||||
|
|
||||||
|
limit-rate-up=${toString limits.upload}
|
||||||
|
limit-rate-down=${toString limits.download}
|
||||||
|
max-concurrency=${toString limits.threads}
|
||||||
|
block-sync-size=${toString limits.syncSize}
|
||||||
|
|
||||||
|
${listToConf "add-peer" extraNodes}
|
||||||
|
${listToConf "add-priority-node" priorityNodes}
|
||||||
|
${listToConf "add-exclusive-node" exclusiveNodes}
|
||||||
|
|
||||||
|
${extraConfig}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.monero = {
|
||||||
|
|
||||||
|
enable = mkEnableOption "Monero node daemon.";
|
||||||
|
|
||||||
|
mining.enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to mine moneroj.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mining.address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Monero address where to send mining rewards.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mining.threads = mkOption {
|
||||||
|
type = types.addCheck types.int (x: x>=0);
|
||||||
|
default = 0;
|
||||||
|
description = ''
|
||||||
|
Number of threads used for mining.
|
||||||
|
Set to <literal>0</literal> to use all available.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc.user = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
User name for RPC connections.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc.password = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Password for RPC connections.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc.address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
description = ''
|
||||||
|
IP address the RPC server will bind to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc.port = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 18081;
|
||||||
|
description = ''
|
||||||
|
Port the RPC server will bind to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
rpc.restricted = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to restrict RPC to view only commands.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
limits.upload = mkOption {
|
||||||
|
type = types.addCheck types.int (x: x>=-1);
|
||||||
|
default = -1;
|
||||||
|
description = ''
|
||||||
|
Limit of the upload rate in kB/s.
|
||||||
|
Set to <literal>-1</literal> to leave unlimited.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
limits.download = mkOption {
|
||||||
|
type = types.addCheck types.int (x: x>=-1);
|
||||||
|
default = -1;
|
||||||
|
description = ''
|
||||||
|
Limit of the download rate in kB/s.
|
||||||
|
Set to <literal>-1</literal> to leave unlimited.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
limits.threads = mkOption {
|
||||||
|
type = types.addCheck types.int (x: x>=0);
|
||||||
|
default = 0;
|
||||||
|
description = ''
|
||||||
|
Maximum number of threads used for a parallel job.
|
||||||
|
Set to <literal>0</literal> to leave unlimited.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
limits.syncSize = mkOption {
|
||||||
|
type = types.addCheck types.int (x: x>=0);
|
||||||
|
default = 0;
|
||||||
|
description = ''
|
||||||
|
Maximum number of blocks to sync at once.
|
||||||
|
Set to <literal>0</literal> for adaptive.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraNodes = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
List of additional peer IP addresses to add to the local list.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
priorityNodes = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
List of peer IP addresses to connect to and
|
||||||
|
attempt to keep the connection open.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
exclusiveNodes = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
List of peer IP addresses to connect to *only*.
|
||||||
|
If given the other peer options will be ignored.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Extra lines to be added verbatim to monerod configuration.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
users.extraUsers = singleton {
|
||||||
|
name = "monero";
|
||||||
|
uid = config.ids.uids.monero;
|
||||||
|
description = "Monero daemon user";
|
||||||
|
home = dataDir;
|
||||||
|
createHome = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
users.extraGroups = singleton {
|
||||||
|
name = "monero";
|
||||||
|
gid = config.ids.gids.monero;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.monero = {
|
||||||
|
description = "monero daemon";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
User = "monero";
|
||||||
|
Group = "monero";
|
||||||
|
ExecStart = "${pkgs.monero}/bin/monerod --config-file=${configFile} --non-interactive";
|
||||||
|
Restart = "always";
|
||||||
|
SuccessExitStatus = [ 0 1 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
assertions = singleton {
|
||||||
|
assertion = cfg.mining.enable -> cfg.mining.address != "";
|
||||||
|
message = ''
|
||||||
|
You need a Monero address to receive mining rewards:
|
||||||
|
specify one using option monero.mining.address.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -212,7 +212,7 @@ in
|
||||||
'' + concatStringsSep "\n" (
|
'' + concatStringsSep "\n" (
|
||||||
mapAttrsToList (n: c:
|
mapAttrsToList (n: c:
|
||||||
if c.hashedPassword != null then
|
if c.hashedPassword != null then
|
||||||
"echo '${n}:${c.hashedPassword}' > ${cfg.dataDir}/passwd"
|
"echo '${n}:${c.hashedPassword}' >> ${cfg.dataDir}/passwd"
|
||||||
else optionalString (c.password != null)
|
else optionalString (c.password != null)
|
||||||
"${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}"
|
"${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}"
|
||||||
) cfg.users);
|
) cfg.users);
|
||||||
|
|
|
@ -53,6 +53,30 @@ let
|
||||||
-i ${cfg.externalInterface} -p ${fwd.proto} \
|
-i ${cfg.externalInterface} -p ${fwd.proto} \
|
||||||
--dport ${builtins.toString fwd.sourcePort} \
|
--dport ${builtins.toString fwd.sourcePort} \
|
||||||
-j DNAT --to-destination ${fwd.destination}
|
-j DNAT --to-destination ${fwd.destination}
|
||||||
|
|
||||||
|
${concatMapStrings (loopbackip:
|
||||||
|
let
|
||||||
|
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
|
||||||
|
destinationIP = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 0;
|
||||||
|
destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 1;
|
||||||
|
in ''
|
||||||
|
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from the host itself
|
||||||
|
iptables -w -t nat -A OUTPUT \
|
||||||
|
-d ${loopbackip} -p ${fwd.proto} \
|
||||||
|
--dport ${builtins.toString fwd.sourcePort} \
|
||||||
|
-j DNAT --to-destination ${fwd.destination}
|
||||||
|
|
||||||
|
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from other hosts behind NAT
|
||||||
|
iptables -w -t nat -A nixos-nat-pre \
|
||||||
|
-d ${loopbackip} -p ${fwd.proto} \
|
||||||
|
--dport ${builtins.toString fwd.sourcePort} \
|
||||||
|
-j DNAT --to-destination ${fwd.destination}
|
||||||
|
|
||||||
|
iptables -w -t nat -A nixos-nat-post \
|
||||||
|
-d ${destinationIP} -p ${fwd.proto} \
|
||||||
|
--dport ${destinationPorts} \
|
||||||
|
-j SNAT --to-source ${loopbackip}
|
||||||
|
'') fwd.loopbackIPs}
|
||||||
'') cfg.forwardPorts}
|
'') cfg.forwardPorts}
|
||||||
|
|
||||||
${optionalString (cfg.dmzHost != null) ''
|
${optionalString (cfg.dmzHost != null) ''
|
||||||
|
@ -152,6 +176,13 @@ in
|
||||||
example = "udp";
|
example = "udp";
|
||||||
description = "Protocol of forwarded connection";
|
description = "Protocol of forwarded connection";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
loopbackIPs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = literalExample ''[ "55.1.2.3" ]'';
|
||||||
|
description = "Public IPs for NAT reflection; for connections to `loopbackip:sourcePort' from the host itself and from other hosts behind NAT";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
default = [];
|
default = [];
|
||||||
|
|
79
nixos/modules/services/networking/nixops-dns.nix
Normal file
79
nixos/modules/services/networking/nixops-dns.nix
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
pkg = pkgs.nixops-dns;
|
||||||
|
cfg = config.services.nixops-dns;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.nixops-dns = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to enable the nixops-dns resolution
|
||||||
|
of NixOps virtual machines via dnsmasq and fake domain name.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
The user the nixops-dns daemon should run as.
|
||||||
|
This should be the user, which is also used for nixops and
|
||||||
|
have the .nixops directory in its home.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
domain = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Fake domain name to resolve to NixOps virtual machines.
|
||||||
|
|
||||||
|
For example "ops" will resolve "vm.ops".
|
||||||
|
'';
|
||||||
|
example = "ops";
|
||||||
|
default = "ops";
|
||||||
|
};
|
||||||
|
|
||||||
|
dnsmasq = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Enable dnsmasq forwarding to nixops-dns. This allows to use
|
||||||
|
nixops-dns for `services.nixops-dns.domain` resolution
|
||||||
|
while forwarding the rest of the queries to original resolvers.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.nixops-dns = {
|
||||||
|
description = "nixops-dns: DNS server for resolving NixOps machines";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = cfg.user;
|
||||||
|
ExecStart="${pkg}/bin/nixops-dns --domain=.${cfg.domain}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.dnsmasq = mkIf cfg.dnsmasq {
|
||||||
|
enable = true;
|
||||||
|
resolveLocalQueries = true;
|
||||||
|
servers = [
|
||||||
|
"/${cfg.domain}/127.0.0.1#5300"
|
||||||
|
];
|
||||||
|
extraConfig = ''
|
||||||
|
bind-interfaces
|
||||||
|
listen-address=127.0.0.1
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -179,6 +179,19 @@ in
|
||||||
description = "Whether to enable the prosody server";
|
description = "Whether to enable the prosody server";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
description = "Prosody package to use";
|
||||||
|
default = pkgs.prosody;
|
||||||
|
defaultText = "pkgs.prosody";
|
||||||
|
example = literalExample ''
|
||||||
|
pkgs.prosody.override {
|
||||||
|
withExtraLibs = [ pkgs.luaPackages.lpty ];
|
||||||
|
withCommunityModules = [ "auth_external" ];
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
allowRegistration = mkOption {
|
allowRegistration = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
@ -306,7 +319,7 @@ in
|
||||||
User = "prosody";
|
User = "prosody";
|
||||||
Type = "forking";
|
Type = "forking";
|
||||||
PIDFile = "/var/lib/prosody/prosody.pid";
|
PIDFile = "/var/lib/prosody/prosody.pid";
|
||||||
ExecStart = "${pkgs.prosody}/bin/prosodyctl start";
|
ExecStart = "${cfg.package}/bin/prosodyctl start";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,24 +59,11 @@ in
|
||||||
|
|
||||||
systemd.services.radvd =
|
systemd.services.radvd =
|
||||||
{ description = "IPv6 Router Advertisement Daemon";
|
{ description = "IPv6 Router Advertisement Daemon";
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
|
|
||||||
path = [ pkgs.radvd ];
|
|
||||||
|
|
||||||
preStart = ''
|
|
||||||
mkdir -m 755 -p /run/radvd
|
|
||||||
chown radvd /run/radvd
|
|
||||||
'';
|
|
||||||
|
|
||||||
serviceConfig =
|
serviceConfig =
|
||||||
{ ExecStart = "@${pkgs.radvd}/sbin/radvd radvd"
|
{ ExecStart = "@${pkgs.radvd}/bin/radvd radvd -n -u radvd -C ${confFile}";
|
||||||
+ " -p /run/radvd/radvd.pid -m syslog -u radvd -C ${confFile}";
|
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
Type = "forking";
|
|
||||||
PIDFile = "/run/radvd/radvd.pid";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
63
nixos/modules/services/networking/rxe.nix
Normal file
63
nixos/modules/services/networking/rxe.nix
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.networking.rxe;
|
||||||
|
|
||||||
|
runRxeCmd = cmd: ifcs:
|
||||||
|
concatStrings ( map (x: "${pkgs.rdma-core}/bin/rxe_cfg -n ${cmd} ${x};") ifcs);
|
||||||
|
|
||||||
|
startScript = pkgs.writeShellScriptBin "rxe-start" ''
|
||||||
|
${pkgs.rdma-core}/bin/rxe_cfg -n start
|
||||||
|
${runRxeCmd "add" cfg.interfaces}
|
||||||
|
${pkgs.rdma-core}/bin/rxe_cfg
|
||||||
|
'';
|
||||||
|
|
||||||
|
stopScript = pkgs.writeShellScriptBin "rxe-stop" ''
|
||||||
|
${runRxeCmd "remove" cfg.interfaces }
|
||||||
|
${pkgs.rdma-core}/bin/rxe_cfg -n stop
|
||||||
|
'';
|
||||||
|
|
||||||
|
in {
|
||||||
|
###### interface
|
||||||
|
|
||||||
|
options = {
|
||||||
|
networking.rxe = {
|
||||||
|
enable = mkEnableOption "RDMA over converged ethernet";
|
||||||
|
interfaces = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "eth0" ];
|
||||||
|
description = ''
|
||||||
|
Enable RDMA on the listed interfaces. The corresponding virtual
|
||||||
|
RDMA interfaces will be named rxe0 ... rxeN where the ordering
|
||||||
|
will be as they are named in the list. UDP port 4791 must be
|
||||||
|
open on the respective ethernet interfaces.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
###### implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
systemd.services.rxe = {
|
||||||
|
path = with pkgs; [ kmod rdma-core ];
|
||||||
|
description = "RoCE interfaces";
|
||||||
|
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "systemd-modules-load.service" "network-online.target" ];
|
||||||
|
wants = [ "network-pre.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = "${startScript}/bin/rxe-start";
|
||||||
|
ExecStop = "${stopScript}/bin/rxe-stop";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -375,9 +375,6 @@ in
|
||||||
# LogLevel VERBOSE logs user's key fingerprint on login.
|
# LogLevel VERBOSE logs user's key fingerprint on login.
|
||||||
# Needed to have a clear audit track of which key was used to log in.
|
# Needed to have a clear audit track of which key was used to log in.
|
||||||
LogLevel VERBOSE
|
LogLevel VERBOSE
|
||||||
|
|
||||||
# Use kernel sandbox mechanisms where possible in unprivileged processes.
|
|
||||||
UsePrivilegeSeparation sandbox
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
|
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
|
||||||
|
|
|
@ -35,10 +35,9 @@ in {
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
boot.kernelModules = [ "dummy" ];
|
boot.kernelModules = [ "dummy" ];
|
||||||
|
|
||||||
networking.interfaces.dummy0 = {
|
networking.interfaces.dummy0.ipv4.addresses = [
|
||||||
ipAddress = "169.254.169.254";
|
{ address = "169.254.169.254"; prefixLength = 32; }
|
||||||
prefixLength = 32;
|
];
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.hologram-agent = {
|
systemd.services.hologram-agent = {
|
||||||
description = "Provide EC2 instance credentials to machines outside of EC2";
|
description = "Provide EC2 instance credentials to machines outside of EC2";
|
||||||
|
|
|
@ -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 {
|
disableSysRq = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
|
@ -79,7 +93,8 @@ in
|
||||||
|
|
||||||
###### implementation
|
###### implementation
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable (mkMerge [
|
||||||
|
{
|
||||||
|
|
||||||
# for physlock -l and physlock -L
|
# for physlock -l and physlock -L
|
||||||
environment.systemPackages = [ pkgs.physlock ];
|
environment.systemPackages = [ pkgs.physlock ];
|
||||||
|
@ -93,14 +108,21 @@ in
|
||||||
before = optional cfg.lockOn.suspend "systemd-suspend.service"
|
before = optional cfg.lockOn.suspend "systemd-suspend.service"
|
||||||
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
||||||
++ cfg.lockOn.extraTargets;
|
++ cfg.lockOn.extraTargets;
|
||||||
serviceConfig.Type = "forking";
|
serviceConfig = {
|
||||||
script = ''
|
Type = "forking";
|
||||||
${pkgs.physlock}/bin/physlock -d${optionalString cfg.disableSysRq "s"}
|
ExecStart = "${pkgs.physlock}/bin/physlock -d${optionalString cfg.disableSysRq "s"}";
|
||||||
'';
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
security.pam.services.physlock = {};
|
security.pam.services.physlock = {};
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
|
(mkIf cfg.allowAnyUser {
|
||||||
|
|
||||||
|
security.wrappers.physlock = { source = "${pkgs.physlock}/bin/physlock"; user = "root"; };
|
||||||
|
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,9 @@ let
|
||||||
${flip concatMapStrings v.map (p: ''
|
${flip concatMapStrings v.map (p: ''
|
||||||
HiddenServicePort ${toString p.port} ${p.destination}
|
HiddenServicePort ${toString p.port} ${p.destination}
|
||||||
'')}
|
'')}
|
||||||
|
${optionalString (v.authorizeClient != null) ''
|
||||||
|
HiddenServiceAuthorizeClient ${v.authorizeClient.authType} ${concatStringsSep "," v.authorizeClient.clientNames}
|
||||||
|
''}
|
||||||
''))
|
''))
|
||||||
+ cfg.extraConfig;
|
+ 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 = {
|
config = {
|
||||||
|
|
|
@ -64,8 +64,8 @@ in
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# Note: this is set here rather than up there so that changing
|
# Note: this is set here rather than up there so that changing
|
||||||
# nixosLabel would not rebuild manual pages
|
# nixos.label would not rebuild manual pages
|
||||||
services.mingetty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixosLabel} (\m) - \l >>>'';
|
services.mingetty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixos.label} (\m) - \l >>>'';
|
||||||
|
|
||||||
systemd.services."getty@" =
|
systemd.services."getty@" =
|
||||||
{ serviceConfig.ExecStart = [
|
{ serviceConfig.ExecStart = [
|
||||||
|
|
|
@ -578,6 +578,7 @@ in
|
||||||
mkdir -p ${cfg.stateDir}/logs
|
mkdir -p ${cfg.stateDir}/logs
|
||||||
chmod 700 ${cfg.stateDir}
|
chmod 700 ${cfg.stateDir}
|
||||||
chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
|
chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
|
||||||
|
${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
|
ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}";
|
||||||
|
|
|
@ -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 {
|
package = mkOption {
|
||||||
default = pkgs.traefik;
|
default = pkgs.traefik;
|
||||||
defaultText = "pkgs.traefik";
|
defaultText = "pkgs.traefik";
|
||||||
|
@ -87,7 +97,7 @@ in {
|
||||||
];
|
];
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
User = "traefik";
|
User = "traefik";
|
||||||
Group = "traefik";
|
Group = cfg.group;
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
StartLimitInterval = 86400;
|
StartLimitInterval = 86400;
|
||||||
StartLimitBurst = 5;
|
StartLimitBurst = 5;
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
{ config, lib, pkgs, ...}:
|
{ config, lib, pkgs, ...}:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.services.varnish;
|
cfg = config.services.varnish;
|
||||||
|
|
||||||
|
commandLine = "-f ${pkgs.writeText "default.vcl" cfg.config}" +
|
||||||
|
optionalString (cfg.extraModules != []) " -p vmod_path='${makeSearchPathOutput "lib" "lib/varnish/vmods" ([pkgs.varnish] ++ cfg.extraModules)}' -r vmod_path";
|
||||||
in
|
in
|
||||||
with lib;
|
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
services.varnish = {
|
services.varnish = {
|
||||||
|
@ -69,8 +73,7 @@ with lib;
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
PermissionsStartOnly = true;
|
PermissionsStartOnly = true;
|
||||||
ExecStart = "${pkgs.varnish}/sbin/varnishd -a ${cfg.http_address} -f ${pkgs.writeText "default.vcl" cfg.config} -n ${cfg.stateDir} -F ${cfg.extraCommandLine}"
|
ExecStart = "${pkgs.varnish}/sbin/varnishd -a ${cfg.http_address} -n ${cfg.stateDir} -F ${cfg.extraCommandLine} ${commandLine}";
|
||||||
+ optionalString (cfg.extraModules != []) " -p vmod_path='${makeSearchPathOutput "lib" "lib/varnish/vmods" ([pkgs.varnish] ++ cfg.extraModules)}' -r vmod_path";
|
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
RestartSec = "5s";
|
RestartSec = "5s";
|
||||||
User = "varnish";
|
User = "varnish";
|
||||||
|
@ -83,6 +86,14 @@ with lib;
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.varnish ];
|
environment.systemPackages = [ pkgs.varnish ];
|
||||||
|
|
||||||
|
# check .vcl syntax at compile time (e.g. before nixops deployment)
|
||||||
|
system.extraDependencies = [
|
||||||
|
(pkgs.stdenv.mkDerivation {
|
||||||
|
name = "check-varnish-syntax";
|
||||||
|
buildCommand = "${pkgs.varnish}/sbin/varnishd -C ${commandLine} 2> $out";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
users.extraUsers.varnish = {
|
users.extraUsers.varnish = {
|
||||||
group = "varnish";
|
group = "varnish";
|
||||||
uid = config.ids.uids.varnish;
|
uid = config.ids.uids.varnish;
|
||||||
|
|
|
@ -66,6 +66,10 @@ in
|
||||||
security.wrappers = {
|
security.wrappers = {
|
||||||
kcheckpass.source = "${lib.getBin plasma5.plasma-workspace}/lib/libexec/kcheckpass";
|
kcheckpass.source = "${lib.getBin plasma5.plasma-workspace}/lib/libexec/kcheckpass";
|
||||||
"start_kdeinit".source = "${lib.getBin pkgs.kinit}/lib/libexec/kf5/start_kdeinit";
|
"start_kdeinit".source = "${lib.getBin pkgs.kinit}/lib/libexec/kf5/start_kdeinit";
|
||||||
|
kwin_wayland = {
|
||||||
|
source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
|
||||||
|
capabilities = "cap_sys_nice+ep";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; with qt5; with libsForQt5; with plasma5; with kdeApplications;
|
environment.systemPackages = with pkgs; with qt5; with libsForQt5; with plasma5; with kdeApplications;
|
||||||
|
|
|
@ -30,6 +30,8 @@ let
|
||||||
let
|
let
|
||||||
kernelPath = "${config.boot.kernelPackages.kernel}/" +
|
kernelPath = "${config.boot.kernelPackages.kernel}/" +
|
||||||
"${config.system.boot.loader.kernelFile}";
|
"${config.system.boot.loader.kernelFile}";
|
||||||
|
initrdPath = "${config.system.build.initialRamdisk}/" +
|
||||||
|
"${config.system.boot.loader.initrdFile}";
|
||||||
in ''
|
in ''
|
||||||
mkdir $out
|
mkdir $out
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ let
|
||||||
|
|
||||||
echo -n "$kernelParams" > $out/kernel-params
|
echo -n "$kernelParams" > $out/kernel-params
|
||||||
|
|
||||||
ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd
|
ln -s ${initrdPath} $out/initrd
|
||||||
|
|
||||||
ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
|
ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
|
||||||
|
|
||||||
|
@ -106,7 +108,7 @@ let
|
||||||
if [] == failed then pkgs.stdenvNoCC.mkDerivation {
|
if [] == failed then pkgs.stdenvNoCC.mkDerivation {
|
||||||
name = let hn = config.networking.hostName;
|
name = let hn = config.networking.hostName;
|
||||||
nn = if (hn != "") then hn else "unnamed";
|
nn = if (hn != "") then hn else "unnamed";
|
||||||
in "nixos-system-${nn}-${config.system.nixosLabel}";
|
in "nixos-system-${nn}-${config.system.nixos.label}";
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
allowSubstitutes = false;
|
allowSubstitutes = false;
|
||||||
buildCommand = systemBuilder;
|
buildCommand = systemBuilder;
|
||||||
|
@ -120,7 +122,7 @@ let
|
||||||
config.system.build.installBootLoader
|
config.system.build.installBootLoader
|
||||||
or "echo 'Warning: do not know how to make this configuration bootable; please enable a boot loader.' 1>&2; true";
|
or "echo 'Warning: do not know how to make this configuration bootable; please enable a boot loader.' 1>&2; true";
|
||||||
activationScript = config.system.activationScripts.script;
|
activationScript = config.system.activationScripts.script;
|
||||||
nixosLabel = config.system.nixosLabel;
|
nixosLabel = config.system.nixos.label;
|
||||||
|
|
||||||
configurationName = config.boot.loader.grub.configurationName;
|
configurationName = config.boot.loader.grub.configurationName;
|
||||||
|
|
||||||
|
@ -179,6 +181,15 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
system.boot.loader.initrdFile = mkOption {
|
||||||
|
internal = true;
|
||||||
|
default = "initrd";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Name of the initrd file to be passed to the bootloader.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
system.copySystemConfiguration = mkOption {
|
system.copySystemConfiguration = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue