Merge remote-tracking branch 'upstream/master' into hardened-stdenv

This commit is contained in:
Robin Gloster 2016-07-15 14:41:01 +00:00
commit 5185bc1773
1603 changed files with 132259 additions and 39569 deletions

View File

@ -4,8 +4,8 @@
###### Things done
- [ ] Tested using sandboxing
([nix.useSandbox](http://nixos.org/nixos/manual/options.html#opt-nix.useSandbox) on NixOS,
or option `build-use-sandbox` in [`nix.conf`](http://nixos.org/nix/manual/#sec-conf-file)
([nix.useChroot](http://nixos.org/nixos/manual/options.html#opt-nix.useChroot) on NixOS,
or option `build-use-chroot` in [`nix.conf`](http://nixos.org/nix/manual/#sec-conf-file)
on non-NixOS)
- Built on platform(s)
- [ ] NixOS

View File

@ -57,11 +57,11 @@ stdenv.mkDerivation {
outputFile = "./languages-frameworks/haskell.xml";
}
+ toDocbook {
inputFile = ./../pkgs/development/idris-modules/README.md;
inputFile = ../pkgs/development/idris-modules/README.md;
outputFile = "languages-frameworks/idris.xml";
}
+ toDocbook {
inputFile = ./../pkgs/development/r-modules/README.md;
inputFile = ../pkgs/development/r-modules/README.md;
outputFile = "languages-frameworks/r.xml";
}
+ ''

View File

@ -89,27 +89,27 @@ in ...</programlisting>
<title>&lt;pkg&gt;.overrideDerivation</title>
<warning>
<para>Do not use this function in Nixpkgs. Because it breaks
package abstraction and doesnt provide error checking for
function arguments, it is only intended for ad-hoc customisation
(such as in <filename>~/.nixpkgs/config.nix</filename>).
</para>
<para>
Additionally, <varname>overrideDerivation</varname> forces an evaluation
of the Derivation which can be quite a performance penalty if there are many
overrides used.
<para>Do not use this function in Nixpkgs as it evaluates a Derivation
before modifying it, which breaks package abstraction and removes
error-checking of function arguments. In addition, this
evaluation-per-function application incurs a performance penalty,
which can become a problem if many overrides are used.
It is only intended for ad-hoc customisation, such as in
<filename>~/.nixpkgs/config.nix</filename>.
</para>
</warning>
<para>
The function <varname>overrideDerivation</varname> is usually available for all the
derivations in the nixpkgs expression (<varname>pkgs</varname>).
The function <varname>overrideDerivation</varname> creates a new derivation
based on an existing one by overriding the original's attributes with
the attribute set produced by the specified function.
This function is available on all
derivations defined using the <varname>makeOverridable</varname> function.
Most standard derivation-producing functions, such as
<varname>stdenv.mkDerivation</varname>, are defined using this
function, which means most packages in the nixpkgs expression,
<varname>pkgs</varname>, have this function.
</para>
<para>
It is used to create a new derivation by overriding the attributes of
the original derivation according to the given function.
</para>
<para>
Example usage:
@ -125,9 +125,9 @@ in ...</programlisting>
</para>
<para>
In the above example, the name, src and patches of the derivation
will be overridden, while all other attributes will be retained from the
original derivation.
In the above example, the <varname>name</varname>, <varname>src</varname>,
and <varname>patches</varname> of the derivation will be overridden, while
all other attributes will be retained from the original derivation.
</para>
<para>
@ -135,6 +135,20 @@ in ...</programlisting>
the original derivation.
</para>
<note>
<para>
A package's attributes are evaluated *before* being modified by
the <varname>overrideDerivation</varname> function.
For example, the <varname>name</varname> attribute reference
in <varname>url = "mirror://gnu/hello/${name}.tar.gz";</varname>
is filled-in *before* the <varname>overrideDerivation</varname> function
modifies the attribute set. This means that overriding the
<varname>name</varname> attribute, in this example, *will not* change the
value of the <varname>url</varname> attribute. Instead, we need to override
both the <varname>name</varname> *and* <varname>url</varname> attributes.
</para>
</note>
</section>
<section xml:id="sec-lib-makeOverridable">
@ -171,42 +185,18 @@ c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
<section xml:id="sec-fhs-environments">
<title>buildFHSChrootEnv/buildFHSUserEnv</title>
<title>buildFHSUserEnv</title>
<para>
<function>buildFHSChrootEnv</function> and
<function>buildFHSUserEnv</function> provide a way to build and run
FHS-compatible lightweight sandboxes. They get their own isolated root with
binded <filename>/nix/store</filename>, so their footprint in terms of disk
<function>buildFHSUserEnv</function> provides a way to build and run
FHS-compatible lightweight sandboxes. It creates an isolated root with
bound <filename>/nix/store</filename>, so its footprint in terms of disk
space needed is quite small. This allows one to run software which is hard or
unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions,
games distributed as tarballs, software with integrity checking and/or external
self-updated binaries.
</para>
<para>
<function>buildFHSChrootEnv</function> allows to create persistent
environments, which can be constructed, deconstructed and entered by
multiple users at once. A downside is that it requires
<literal>root</literal> access for both those who create and destroy and
those who enter it. It can be useful to create environments for daemons that
one can enter and observe.
</para>
<para>
<function>buildFHSUserEnv</function> uses Linux namespaces feature to create
self-updated binaries. It uses Linux namespaces feature to create
temporary lightweight environments which are destroyed after all child
processes exit. It does not require root access, and can be useful to create
sandboxes and wrap applications.
</para>
<para>
Those functions both rely on <function>buildFHSEnv</function>, which creates
an actual directory structure given a list of necessary packages and extra
build commands.
<function>buildFHSChrootEnv</function> and <function>buildFHSUserEnv</function>
both accept those arguments which are passed to
<function>buildFHSEnv</function>:
processes exit, without root user rights requirement. Accepted arguments are:
</para>
<variablelist>
@ -220,14 +210,16 @@ c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
<term><literal>targetPkgs</literal></term>
<listitem><para>Packages to be installed for the main host's architecture
(i.e. x86_64 on x86_64 installations).</para></listitem>
(i.e. x86_64 on x86_64 installations). Along with libraries binaries are also
installed.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>multiPkgs</literal></term>
<listitem><para>Packages to be installed for all architectures supported by
a host (i.e. i686 and x86_64 on x86_64 installations).</para></listitem>
a host (i.e. i686 and x86_64 on x86_64 installations). Only libraries are
installed by default.</para></listitem>
</varlistentry>
<varlistentry>
@ -240,29 +232,33 @@ c = lib.makeOverridable f { a = 1; b = 2; }</programlisting>
<varlistentry>
<term><literal>extraBuildCommandsMulti</literal></term>
<listitem><para>Like <literal>extraBuildCommandsMulti</literal>, but
<listitem><para>Like <literal>extraBuildCommands</literal>, but
executed only on multilib architectures.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>extraOutputsToInstall</literal></term>
<listitem><para>Additional derivation outputs to be linked for both
target and multi-architecture packages.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>extraInstallCommands</literal></term>
<listitem><para>Additional commands to be executed for finalizing the
derivation with runner script.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>runScript</literal></term>
<listitem><para>A command that would be executed inside the sandbox and
passed all the command line arguments. It defaults to
<literal>bash</literal>.</para></listitem>
</varlistentry>
</variablelist>
<para>
Additionally, <function>buildFHSUserEnv</function> accepts
<literal>runScript</literal> parameter, which is a command that would be
executed inside the sandbox and passed all the command line arguments. It
default to <literal>bash</literal>.
</para>
<para>
It also uses <literal>CHROOTENV_EXTRA_BINDS</literal> environment variable
for binding extra directories in the sandbox to outside places. The format of
the variable is <literal>/mnt=test-mnt:/data</literal>, where
<literal>/mnt</literal> would be mounted as <literal>/test-mnt</literal>
and <literal>/data</literal> would be mounted as <literal>/data</literal>.
<literal>extraBindMounts</literal> array argument to
<function>buildFHSUserEnv</function> function is prepended to this variable.
Latter entries take priority if defined several times -- i.e. in case of
<literal>/data=data1:/data=data2</literal> the actual bind path would be
<literal>/data2</literal>.
</para>
<para>
One can create a simple environment using a <literal>shell.nix</literal>
like that:

View File

@ -5,27 +5,29 @@
<title>Go</title>
<para>The function <varname>buildGoPackage</varname> builds
standard Go packages.
standard Go programs.
</para>
<example xml:id='ex-buildGoPackage'><title>buildGoPackage</title>
<programlisting>
net = buildGoPackage rec {
name = "go.net-${rev}";
goPackagePath = "golang.org/x/net"; <co xml:id='ex-buildGoPackage-1' />
subPackages = [ "ipv4" "ipv6" ]; <co xml:id='ex-buildGoPackage-2' />
rev = "e0403b4e005";
deis = buildGoPackage rec {
name = "deis-${version}";
version = "1.13.0";
goPackagePath = "github.com/deis/deis"; <co xml:id='ex-buildGoPackage-1' />
subPackages = [ "client" ]; <co xml:id='ex-buildGoPackage-2' />
src = fetchFromGitHub {
inherit rev;
owner = "golang";
repo = "net";
sha256 = "1g7cjzw4g4301a3yqpbk8n1d4s97sfby2aysl275x04g0zh8jxqp";
owner = "deis";
repo = "deis";
rev = "v${version}";
sha256 = "1qv9lxqx7m18029lj8cw3k7jngvxs4iciwrypdy0gd2nnghc68sw";
};
goPackageAliases = [ "code.google.com/p/go.net" ]; <co xml:id='ex-buildGoPackage-3' />
propagatedBuildInputs = [ goPackages.text ]; <co xml:id='ex-buildGoPackage-4' />
buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-5' />
disabled = isGo13;<co xml:id='ex-buildGoPackage-6' />
};
goDeps = ./deps.json; <co xml:id='ex-buildGoPackage-3' />
buildFlags = "--tags release"; <co xml:id='ex-buildGoPackage-4' />
}
</programlisting>
</example>
@ -47,50 +49,90 @@ the following arguments are of special significance to the function:
packages will be built.
</para>
<para>
In this example only <literal>code.google.com/p/go.net/ipv4</literal> and
<literal>code.google.com/p/go.net/ipv6</literal> will be built.
In this example only <literal>github.com/deis/deis/client</literal> will be built.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-3'>
<para>
<varname>goPackageAliases</varname> is a list of alternative import paths
that are valid for this library.
Packages that depend on this library will automatically rename
import paths that match any of the aliases to <literal>goPackagePath</literal>.
</para>
<para>
In this example imports will be renamed from
<literal>code.google.com/p/go.net</literal> to
<literal>golang.org/x/net</literal> in every package that depend on the
<literal>go.net</literal> library.
<varname>goDeps</varname> is where the Go dependencies of a Go program are listed
in a JSON format described below.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-4'>
<para>
<varname>propagatedBuildInputs</varname> is where the dependencies of a Go library are
listed. Only libraries should list <varname>propagatedBuildInputs</varname>. If a standalone
program is being built instead, use <varname>buildInputs</varname>. If a library's tests require
additional dependencies that are not propagated, they should be listed in <varname>buildInputs</varname>.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-5'>
<para>
<varname>buildFlags</varname> is a list of flags passed to the go build command.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-6'>
</calloutlist>
</para>
<para>The <varname>goDeps</varname> attribute should point to a JSON file that defines which Go libraries
are needed and should be included in <varname>GOPATH</varname> for <varname>buildPhase</varname>.
</para>
<example xml:id='ex-goDeps'><title>deps.json</title>
<programlisting>
[ <co xml:id='ex-goDeps-1' />
{
"goPackagePath": "gopkg.in/yaml.v2", <co xml:id='ex-goDeps-2' />
"fetch": {
"type": "git", <co xml:id='ex-goDeps-3' />
"url": "https://gopkg.in/yaml.v2",
"rev": "a83829b6f1293c91addabc89d0571c246397bbf4",
"sha256": "1m4dsmk90sbi17571h6pld44zxz7jc4lrnl4f27dpd1l8g5xvjhh"
}
},
{
"include": "../../libs.json", <co xml:id='ex-goDeps-4' />
"packages": [ <co xml:id='ex-goDeps-5' />
"github.com/docopt/docopt-go",
"golang.org/x/crypto",
]
}
]
</programlisting>
</example>
<para>
<calloutlist>
<callout arearefs='ex-goDeps-1'>
<para>
If <varname>disabled</varname> is <literal>true</literal>,
nix will refuse to build this package.
<varname>goDeps</varname> is a list of Go dependencies.
</para>
</callout>
<callout arearefs='ex-goDeps-2'>
<para>
In this example the package will not be built for go 1.3. The <literal>isGo13</literal>
is an utility function that returns <literal>true</literal> if go used to build the
package has version 1.3.x.
<varname>goPackagePath</varname> specifies Go package import path.
</para>
</callout>
<callout arearefs='ex-goDeps-3'>
<para>
<varname>fetch type</varname> that needs to be used to get package source. If <varname>git</varname>
is used there should be <varname>url</varname>, <varname>rev</varname> and <varname>sha256</varname>
defined next to it.
</para>
</callout>
<callout arearefs='ex-goDeps-4'>
<para>
<varname>include</varname> could be used to reuse <varname>goDeps</varname> between Go programs.
There is a common libs set in <varname>&lt;nixpkgs/pkgs/development/go-modules/libs.json&gt;</varname>
with pinned versions of many packages that you can reuse.
</para>
</callout>
<callout arearefs='ex-goDeps-5'>
<para>
<varname>packages</varname> enumerates all Go packages that will be imported from included file.
</para>
</callout>
@ -99,12 +141,21 @@ the following arguments are of special significance to the function:
</para>
<para>
Reusable Go libraries may be found in the <varname>goPackages</varname> set. You can test
build a Go package as follows:
<varname>buildGoPackage</varname> produces <xref linkend='chap-multiple-output' xrefstyle="select: title" />
where <varname>bin</varname> includes program binaries. You can test build a Go binary as follows:
<screen>
$ nix-build -A goPackages.net
</screen>
<screen>
$ nix-build -A deis.bin
</screen>
or build all outputs with:
<screen>
$ nix-build -A deis.all
</screen>
<varname>bin</varname> output will be installed by default with <varname>nix-env -i</varname>
or <varname>systemPackages</varname>.
</para>
@ -119,6 +170,7 @@ done
</screen>
</para>
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/kamilchm/go2nix">go2nix</link>.</para>
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/kamilchm/go2nix">go2nix</link>.
It can produce complete derivation and <varname>goDeps</varname> file for Go programs.</para>
</section>

View File

@ -378,6 +378,23 @@ special options turned on:
buildInputs = [ R zeromq zlib ];
}
You can select a particular GHC version to compile with by setting the
`ghc` attribute as an argument to `buildStackProject`. Better yet, let
Stack choose what GHC version it wants based on the snapshot specified
in `stack.yaml` (only works with Stack >= 1.1.3):
{nixpkgs ? import <nixpkgs> { }, ghc ? nixpkgs.ghc}
with nixpkgs;
let R = pkgs.R.override { enableStrictBarrier = true; };
in
haskell.lib.buildStackProject {
name = "HaskellR";
buildInputs = [ R zeromq zlib ];
inherit ghc;
}
[stack-nix-doc]: http://docs.haskellstack.org/en/stable/nix_integration.html
### How to create ad hoc environments for `nix-shell`
@ -636,7 +653,7 @@ then you have to download and re-install `foo` and all its dependents from
scratch:
# nix-store -q --referrers /nix/store/*-haskell-text-1.2.0.4 \
| xargs -L 1 nix-store --repair-path --option binary-caches http://hydra.nixos.org
| xargs -L 1 nix-store --repair-path
If you're using additional Hydra servers other than `hydra.nixos.org`, then it
might be necessary to purge the local caches that store data from those

View File

@ -532,6 +532,7 @@ All parameters from `mkDerivation` function are still supported.
* `makeWrapperArgs`: A list of strings. Arguments to be passed to `makeWrapper`, which wraps generated binaries. By default, the arguments to `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling the binary. Additional arguments here can allow a developer to set environment variables which will be available when the binary is run. For example, `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`.
* `installFlags`: A list of strings. Arguments to be passed to `pip install`. To pass options to `python setup.py install`, use `--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"].
* `format`: Format of the source. Options are `setup` for when the source has a `setup.py` and `setuptools` is used to build a wheel, and `wheel` in case the source is already a binary wheel. The default value is `setup`.
* `catchConflicts` If `true`, abort package build if a package name appears more than once in dependency tree. Default is `true`.
#### `buildPythonApplication` function
@ -648,6 +649,56 @@ community to help save time. No tool is preferred at the moment.
## FAQ
### How can I install a working Python environment?
As explained in the user's guide installing individual Python packages
imperatively with `nix-env -i` or declaratively in `environment.systemPackages`
is not supported. However, it is possible to install a Python environment with packages (`python.buildEnv`).
In the following examples we create an environment with Python 3.5, `numpy` and `ipython`.
As you might imagine there is one limitation here, and that's you can install
only one environment at a time. You will notice the complaints about collisions
when you try to install a second environment.
#### Environment defined in separate `.nix` file
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> {};
with python35Packages;
python.withPackages (ps: with ps; [ numpy ipython ])
```
and install it in your profile with
```
nix-env -if build.nix
```
Now you can use the Python interpreter, as well as the extra packages that you added to the environment.
#### Environment defined in `~/.nixpkgs/config.nix`
If you prefer to, you could also add the environment as a package override to the Nixpkgs set.
```
packageOverrides = pkgs: with pkgs; with python35Packages; {
myEnv = python.withPackages (ps: with ps; [ numpy ipython ]);
};
```
and install it in your profile with
```
nix-env -iA nixos.blogEnv
```
Note that I'm using the attribute path here.
#### Environment defined in `/etc/nixos/configuration.nix`
For the sake of completeness, here's another example how to install the environment system-wide.
```nix
environment.systemPackages = with pkgs; [
(python35Packages.python.withPackages (ps: callPackage ../packages/common-python-packages.nix { pythonPackages = ps; }))
];
```
### How to solve circular dependencies?
Consider the packages `A` and `B` that depend on each other. When packaging `B`,

View File

@ -1196,10 +1196,24 @@ echo @foo@
<term><function>stripHash</function>
<replaceable>path</replaceable></term>
<listitem><para>Strips the directory and hash part of a store
path, and prints (on standard output) only the name part. For
instance, <literal>stripHash
/nix/store/68afga4khv0w...-coreutils-6.12</literal> print
<literal>coreutils-6.12</literal>.</para></listitem>
path, storing the name part in the environment variable
<literal>strippedName</literal>. For example:
<programlisting>
stripHash "/nix/store/9s9r019176g7cvn2nvcw41gsp862y6b4-coreutils-8.24"
# prints coreutils-8.24
echo $strippedName
</programlisting>
If you wish to store the result in another variable, then the
following idiom may be useful:
<programlisting>
name="/nix/store/9s9r019176g7cvn2nvcw41gsp862y6b4-coreutils-8.24"
someVar=$(stripHash $name; echo $strippedName)
</programlisting>
</para></listitem>
</varlistentry>

View File

@ -457,7 +457,6 @@ rec {
/*** deprecated stuff ***/
deepSeqAttrs = throw "removed 2016-02-29 because unused and broken";
zipWithNames = zipAttrsWithNames;
zip = builtins.trace
"lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;

View File

@ -68,18 +68,7 @@ rec {
imap (i: v: "${v}-${toString i}") ["a" "b"]
=> [ "a-1" "b-2" ]
*/
imap =
if builtins ? genList then
f: list: genList (n: f (n + 1) (elemAt list n)) (length list)
else
f: list:
let
len = length list;
imap' = n:
if n == len
then []
else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
in imap' 0;
imap = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
/* Map and concatenate the result.
@ -216,17 +205,11 @@ rec {
range 3 2
=> [ ]
*/
range =
if builtins ? genList then
first: last:
if first > last
then []
else genList (n: first + n) (last - first + 1)
range = first: last:
if first > last then
[]
else
first: last:
if last < first
then []
else [first] ++ range (first + 1) last;
genList (n: first + n) (last - first + 1);
/* Splits the elements of a list in two lists, `right' and
`wrong', depending on the evaluation of a predicate.
@ -250,19 +233,9 @@ rec {
zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
=> ["he" "lo"]
*/
zipListsWith =
if builtins ? genList then
f: fst: snd: genList (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd))
else
f: fst: snd:
let
len = min (length fst) (length snd);
zipListsWith' = n:
if n != len then
[ (f (elemAt fst n) (elemAt snd n)) ]
++ zipListsWith' (n + 1)
else [];
in zipListsWith' 0;
zipListsWith = f: fst: snd:
genList
(n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
/* Merges two lists of the same size together. If the sizes aren't the same
the merging stops at the shortest.
@ -280,11 +253,8 @@ rec {
reverseList [ "b" "o" "j" ]
=> [ "j" "o" "b" ]
*/
reverseList =
if builtins ? genList then
xs: let l = length xs; in genList (n: elemAt xs (l - n - 1)) l
else
fold (e: acc: acc ++ [ e ]) [];
reverseList = xs:
let l = length xs; in genList (n: elemAt xs (l - n - 1)) l;
/* Sort a list based on a comparator function which compares two
elements and returns true if the first argument is strictly below
@ -320,19 +290,7 @@ rec {
take 2 [ ]
=> [ ]
*/
take =
if builtins ? genList then
count: sublist 0 count
else
count: list:
let
len = length list;
take' = n:
if n == len || n == count
then []
else
[ (elemAt list n) ] ++ take' (n + 1);
in take' 0;
take = count: sublist 0 count;
/* Remove the first (at most) N elements of a list.
@ -342,19 +300,7 @@ rec {
drop 2 [ ]
=> [ ]
*/
drop =
if builtins ? genList then
count: list: sublist count (length list) list
else
count: list:
let
len = length list;
drop' = n:
if n == -1 || n < count
then []
else
drop' (n - 1) ++ [ (elemAt list n) ];
in drop' (len - 1);
drop = count: list: sublist count (length list) list;
/* Return a list consisting of at most count elements of list,
starting at index start.
@ -428,8 +374,4 @@ rec {
*/
subtractLists = e: filter (x: !(elem x e));
/*** deprecated stuff ***/
deepSeqList = throw "removed 2016-02-29 because unused and broken";
}

View File

@ -15,6 +15,7 @@
adev = "Adrien Devresse <adev@adev.name>";
Adjective-Object = "Maxwell Huang-Hobbs <mhuan13@gmail.com>";
adnelson = "Allen Nelson <ithinkican@gmail.com>";
adolfogc = "Adolfo E. García Castro <adolfo.garcia.cr@gmail.com>";
aespinosa = "Allan Espinosa <allan.espinosa@outlook.com>";
aflatter = "Alexander Flatter <flatter@fastmail.fm>";
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
@ -70,6 +71,7 @@
c0dehero = "CodeHero <codehero@nerdpol.ch>";
calrama = "Moritz Maxeiner <moritz@ucworks.org>";
campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
carlsverre = "Carl Sverre <accounts@carlsverre.com>";
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
@ -78,6 +80,7 @@
chris-martin = "Chris Martin <ch.martin@gmail.com>";
chrisjefferson = "Christopher Jefferson <chris@bubblescope.net>";
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
cko = "Christine Koppelt <christine.koppelt@gmail.com>";
cleverca22 = "Michael Bishop <cleverca22@gmail.com>";
cmcdragonkai = "Roger Qiu <roger.qiu@matrix.ai>";
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
@ -131,6 +134,7 @@
falsifian = "James Cook <james.cook@utoronto.ca>";
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
fmthoma = "Franz Thoma <f.m.thoma@googlemail.com>";
forkk = "Andrew Okin <forkk@forkk.net>";
fornever = "Friedrich von Never <friedrich@fornever.me>";
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
@ -182,6 +186,7 @@
joamaki = "Jussi Maki <joamaki@gmail.com>";
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
joelteon = "Joel Taylor <me@joelt.io>";
joko = "Ioannis Koutras <ioannis.koutras@gmail.com>";
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
jraygauthier = "Raymond Gauthier <jraygauthier@gmail.com>";
juliendehos = "Julien Dehos <dehos@lisic.univ-littoral.fr>";
@ -228,6 +233,7 @@
markus1189 = "Markus Hauck <markus1189@gmail.com>";
markWot = "Markus Wotringer <markus@wotringer.de>";
martijnvermaat = "Martijn Vermaat <martijn@vermaat.name>";
martingms = "Martin Gammelsæter <martin@mg.am>";
matejc = "Matej Cotman <cotman.matej@gmail.com>";
mathnerd314 = "Mathnerd314 <mathnerd314.gph+hs@gmail.com>";
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
@ -252,6 +258,7 @@
mornfall = "Petr Ročkai <me@mornfall.net>";
MostAwesomeDude = "Corbin Simpson <cds@corbinsimpson.com>";
MP2E = "Cray Elliott <MP2E@archlinux.us>";
mpscholten = "Marc Scholten <marc@mpscholten.de>";
msackman = "Matthew Sackman <matthew@wellquite.org>";
mschristiansen = "Mikkel Christiansen <mikkel@rheosystems.com>";
msteen = "Matthijs Steen <emailmatthijs@gmail.com>";
@ -260,6 +267,7 @@
muflax = "Stefan Dorn <mail@muflax.com>";
myrl = "Myrl Hex <myrl.0xf@gmail.com>";
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
Nate-Devv = "Nathan Moore <natedevv@gmail.com>";
nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>";
nequissimus = "Tim Steinbach <tim@nequissimus.com>";
nfjinjing = "Jinjing Wang <nfjinjing@gmail.com>";
@ -273,6 +281,7 @@
odi = "Oliver Dunkl <oliver.dunkl@gmail.com>";
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
olcai = "Erik Timan <dev@timan.info>";
olejorgenb = "Ole Jørgen Brønner <olejorgenb@yahoo.no>";
orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
osener = "Ozan Sener <ozan@ozansener.com>";
otwieracz = "Slawomir Gonet <slawek@otwiera.cz>";
@ -282,6 +291,7 @@
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
palo = "Ingolf Wanger <palipalo9@googlemail.com>";
pashev = "Igor Pashev <pashev.igor@gmail.com>";
pawelpacana = "Paweł Pacana <pawel.pacana@gmail.com>";
pesterhazy = "Paulus Esterhazy <pesterhazy@gmail.com>";
peterhoeg = "Peter Hoeg <peter@hoeg.com>";
peti = "Peter Simons <simons@cryp.to>";
@ -307,6 +317,8 @@
pxc = "Patrick Callahan <patrick.callahan@latitudeengineering.com>";
qknight = "Joachim Schiele <js@lastlog.de>";
ragge = "Ragnar Dahlen <r.dahlen@gmail.com>";
ralith = "Benjamin Saunders <ben.e.saunders@gmail.com>";
ramkromberg = "Ram Kromberg <ramkromberg@mail.com>";
rardiol = "Ricardo Ardissone <ricardo.ardissone@gmail.com>";
rasendubi = "Alexey Shmalko <rasen.dubi@gmail.com>";
raskin = "Michael Raskin <7c6f434c@mail.ru>";
@ -352,11 +364,13 @@
skrzyp = "Jakub Skrzypnik <jot.skrzyp@gmail.com>";
sleexyz = "Sean Lee <freshdried@gmail.com>";
smironov = "Sergey Mironov <ierton@gmail.com>";
solson = "Scott Olson <scott@solson.me>";
spacefrogg = "Michael Raitza <spacefrogg-nixos@meterriblecrew.net>";
spencerjanssen = "Spencer Janssen <spencerjanssen@gmail.com>";
spinus = "Tomasz Czyż <tomasz.czyz@gmail.com>";
sprock = "Roger Mason <rmason@mun.ca>";
spwhitt = "Spencer Whitt <sw@swhitt.me>";
SShrike = "Severen Redwood <severen@shrike.me>";
stephenmw = "Stephen Weinberg <stephen@q5comm.com>";
steveej = "Stefan Junker <mail@stefanjunker.de>";
swistak35 = "Rafał Łasocha <me@swistak35.com>";
@ -409,6 +423,7 @@
wscott = "Wayne Scott <wsc9tt@gmail.com>";
wyvie = "Elijah Rum <elijahrum@gmail.com>";
yarr = "Dmitry V. <savraz@gmail.com>";
yurrriq = "Eric Bailey <eric@ericb.me>";
z77z = "Marco Maggesi <maggesi@math.unifi.it>";
zagy = "Christian Zagrodnick <cz@flyingcircus.io>";
zef = "Zef Hemel <zef@zef.me>";

View File

@ -16,11 +16,7 @@ rec {
concatStrings ["foo" "bar"]
=> "foobar"
*/
concatStrings =
if builtins ? concatStringsSep then
builtins.concatStringsSep ""
else
lib.foldl' (x: y: x + y) "";
concatStrings = builtins.concatStringsSep "";
/* Map a function over a list and concatenate the resulting strings.
@ -207,13 +203,21 @@ rec {
*/
escape = list: replaceChars list (map (c: "\\${c}") list);
/* Escape all characters that have special meaning in the Bourne shell.
/* Quote string to be used safely within the Bourne shell.
Example:
escapeShellArg "so([<>])me"
=> "so\\(\\[\\<\\>\\]\\)me"
escapeShellArg "esc'ape\nme"
=> "'esc'\\''ape\nme'"
*/
escapeShellArg = lib.escape (stringToCharacters "\\ ';$`()|<>\t*[]");
escapeShellArg = arg: "'${replaceStrings ["'"] ["'\\''"] (toString arg)}'";
/* Quote all arguments to be safely passed to the Bourne shell.
Example:
escapeShellArgs ["one" "two three" "four'five"]
=> "'one' 'two three' 'four'\\''five'"
*/
escapeShellArgs = concatMapStringsSep " " escapeShellArg;
/* Obsolete - use replaceStrings instead. */
replaceChars = builtins.replaceStrings or (

View File

@ -1,6 +1,6 @@
{ nixpkgs }:
with import ./../.. { };
with import ../.. { };
with lib;
stdenv.mkDerivation {

View File

@ -100,6 +100,10 @@ rec {
in if isDerivation res then res else toDerivation res;
};
shellPackage = package // {
check = x: (package.check x) && (hasAttr "shellPath" x);
};
path = mkOptionType {
name = "path";
# Hacky: there is no isPath primop.

View File

@ -0,0 +1,49 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils findutils gnused nix wget
tmp=$(mktemp -d)
pushd $tmp >/dev/null
wget -nH -r -c --no-parent "$@" >/dev/null
csv=$(mktemp)
find . -type f | while read src; do
# Sanitize file name
filename=$(basename "$src" | tr '@' '_')
nameVersion="${filename%.tar.*}"
name=$(echo "$nameVersion" | sed -e 's,-[[:digit:]].*,,' | sed -e 's,-opensource-src$,,')
version=$(echo "$nameVersion" | sed -e 's,^\([[:alpha:]][[:alnum:]]*-\)\+,,')
echo "$name,$version,$src,$filename" >>$csv
done
cat <<EOF
# DO NOT EDIT! This file is generated automatically by fetchsrcs.sh
{ fetchurl, mirror }:
{
EOF
gawk -F , "{ print \$1 }" $csv | sort | uniq | while read name; do
versions=$(gawk -F , "/^$name,/ { print \$2 }" $csv)
latestVersion=$(echo "$versions" | sort -rV | head -n 1)
src=$(gawk -F , "/^$name,$latestVersion,/ { print \$3 }" $csv)
filename=$(gawk -F , "/^$name,$latestVersion,/ { print \$4 }" $csv)
url="${src:2}"
sha256=$(nix-hash --type sha256 --base32 --flat "$src")
cat <<EOF
$name = {
version = "$latestVersion";
src = fetchurl {
url = "\${mirror}/$url";
sha256 = "$sha256";
name = "$filename";
};
};
EOF
done
echo "}"
popd >/dev/null
rm -fr $tmp >/dev/null
rm -f $csv >/dev/null

View File

@ -0,0 +1,5 @@
#!/bin/sh
./maintainers/scripts/fetch-kde-qt.sh \
http://download.kde.org/stable/applications/16.04.3/ -A '*.tar.xz' \
>pkgs/desktops/kde-5/applications/srcs.nix

View File

@ -0,0 +1,5 @@
#!/bin/sh
./maintainers/scripts/fetch-kde-qt.sh \
http://download.kde.org/stable/frameworks/5.24/ -A '*.tar.xz' \
>pkgs/desktops/kde-5/frameworks/srcs.nix

View File

@ -0,0 +1,5 @@
#!/bin/sh
./maintainers/scripts/fetch-kde-qt.sh \
http://download.kde.org/stable/plasma/5.7.1/ -A '*.tar.xz' \
>pkgs/desktops/kde-5/plasma/srcs.nix

View File

@ -0,0 +1,3 @@
#!/bin/sh
./fetch-kde-qt.sh http://download.qt.io/official_releases/qt/5.6/5.6.1/submodules/ -A '*.tar.xz'

View File

@ -13,10 +13,6 @@ if [[ $1 == nix ]]; then
sudo mkdir /etc/nix
sudo sh -c 'echo "build-max-jobs = 4" > /etc/nix/nix.conf'
# Nix builds in /tmp and we need exec support
sudo mount
sudo mount -o remount,exec /run
# Verify evaluation
echo "=== Verifying that nixpkgs evaluates..."
nix-env -f. -qa --json >/dev/null
@ -30,6 +26,11 @@ elif [[ $1 == build ]]; then
if [[ $TRAVIS_OS_NAME == "osx" ]]; then
echo "Skipping NixOS things on darwin"
else
# Nix builds in /tmp and we need exec support
sudo mount -o remount,exec /run
sudo mount -o remount,exec /run/user
sudo mount
echo "=== Checking NixOS options"
nix-build nixos/release.nix -A options --show-trace

View File

@ -22,7 +22,7 @@
(with empty password).</para></listitem>
<listitem><para>If you downloaded the graphical ISO image, you can
run <command>start display-manager</command> to start KDE. If you
run <command>systemctl start display-manager</command> to start KDE. If you
want to continue on the terminal, you can use
<command>loadkeys</command> to switch to your preferred keyboard layout.
(We even provide neo2 via <command>loadkeys de neo</command>!)</para></listitem>

View File

@ -0,0 +1,97 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><command>nixos-version</command></refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
</refmeta>
<refnamediv>
<refname><command>nixos-version</command></refname>
<refpurpose>show the NixOS version</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-version</command>
<arg><option>--hash</option></arg>
<arg><option>--revision</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command shows the version of the currently active NixOS
configuration. For example:
<screen>$ nixos-version
16.03.1011.6317da4 (Emu)
</screen>
The version consists of the following elements:
<variablelist>
<varlistentry>
<term><literal>16.03</literal></term>
<listitem><para>The NixOS release, indicating the year and month
in which it was released (e.g. March 2016).</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>1011</literal></term>
<listitem><para>The number of commits in the Nixpkgs Git
repository between the start of the release branch and the commit
from which this version was built. This ensures that NixOS
versions are monotonically increasing. It is
<literal>git</literal> when the current NixOS configuration was
built from a checkout of the Nixpkgs Git repository rather than
from a NixOS channel.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>6317da4</literal></term>
<listitem><para>The first 7 characters of the commit in the
Nixpkgs Git repository from which this version was
built.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>Emu</literal></term>
<listitem><para>The code name of the NixOS release. The first
letter of the code name indicates that this is the N'th stable
NixOS release; for example, Emu is the fifth
release.</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--hash</option></term>
<term><option>--revision</option></term>
<listitem>
<para>Show the full SHA1 hash of the Git commit from which this
configuration was built, e.g.
<screen>$ nixos-version --hash
6317da40006f6bc2480c6781999c52d88dde2acf
</screen>
</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
</refentry>

View File

@ -27,5 +27,6 @@
<xi:include href="man-nixos-install.xml" />
<xi:include href="man-nixos-option.xml" />
<xi:include href="man-nixos-rebuild.xml" />
<xi:include href="man-nixos-version.xml" />
</reference>

View File

@ -113,14 +113,14 @@ rec {
--add-flags "$vms" \
${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
--run "testScript=\"\$(cat $out/test-script)\"" \
--set testScript '"$testScript"' \
--set VLANS '"${toString vlans}"'
--set testScript '$testScript' \
--set VLANS '${toString vlans}'
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
wrapProgram $out/bin/nixos-run-vms \
--add-flags "$vms" \
${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
--set tests '"startAll; joinAll;"' \
--set VLANS '"${toString vlans}"' \
--set tests 'startAll; joinAll;' \
--set VLANS '${toString vlans}' \
${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"}
''; # "

View File

@ -8,4 +8,12 @@ rec {
replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
(if hasPrefix "/" s then substring 1 (stringLength s) s else s);
# Returns a system path for a given shell package
toShellPath = shell:
if types.shellPackage.check shell then
"/run/current-system/sw${shell.shellPath}"
else if types.package.check shell then
throw "${shell} is not a shell package"
else
shell;
}

View File

@ -13,8 +13,11 @@ echo "NixOS version is $version ($major)"
rm -f ec2-amis.nix
types="hvm pv"
stores="ebs s3"
regions="eu-west-1 eu-central-1 us-east-1 us-west-1 us-west-2 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
for type in hvm pv; do
for type in $types; do
link=$stateDir/$type
imageFile=$link/nixos.qcow2
system=x86_64-linux
@ -31,7 +34,7 @@ for type in hvm pv; do
--arg configuration "{ imports = [ <nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix> ]; ec2.hvm = $hvmFlag; }"
fi
for store in ebs s3; do
for store in $stores; do
bucket=nixos-amis
bucketDir="$version-$type-$store"
@ -39,7 +42,7 @@ for type in hvm pv; do
prevAmi=
prevRegion=
for region in eu-west-1 eu-central-1 us-east-1 us-west-1 us-west-2 ap-southeast-1 ap-southeast-2 ap-northeast-1 sa-east-1; do
for region in $regions; do
name=nixos-$version-$arch-$type-$store
description="NixOS $system $version ($type-$store)"
@ -51,10 +54,11 @@ for type in hvm pv; do
echo "doing $name in $region..."
if [ -n "$prevAmi" ]; then
ami=$(ec2-copy-image \
ami=$(aws ec2 copy-image \
--region "$region" \
--source-region "$prevRegion" --source-ami-id "$prevAmi" \
--name "$name" --description "$description" | cut -f 2)
--source-region "$prevRegion" --source-image-id "$prevAmi" \
--name "$name" --description "$description" | json -q .ImageId)
if [ "$ami" = null ]; then break; fi
else
if [ $store = s3 ]; then
@ -85,12 +89,12 @@ for type in hvm pv; do
ec2-upload-bundle \
-m $imageDir/$type.raw.manifest.xml \
-b "$bucket/$bucketDir" \
-a "$EC2_ACCESS_KEY" -s "$EC2_SECRET_KEY" \
-a "$AWS_ACCESS_KEY_ID" -s "$AWS_SECRET_ACCESS_KEY" \
--location EU
touch $imageDir/uploaded
fi
extraFlags="$bucket/$bucketDir/$type.raw.manifest.xml"
extraFlags="--image-location $bucket/$bucketDir/$type.raw.manifest.xml"
else
@ -115,7 +119,8 @@ for type in hvm pv; do
if [ -z "$snapId" -a -z "$volId" -a -z "$taskId" ]; then
echo "importing $vhdFile..."
taskId=$(ec2-import-volume $vhdFile --no-upload -f vhd \
-o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY" \
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" \
--region "$region" -z "${region}a" \
--bucket "$bucket" --prefix "$bucketDir/" \
| tee /dev/stderr \
@ -125,15 +130,16 @@ for type in hvm pv; do
if [ -z "$snapId" -a -z "$volId" ]; then
ec2-resume-import $vhdFile -t "$taskId" --region "$region" \
-o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY"
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY"
fi
# Wait for the volume creation to finish.
if [ -z "$snapId" -a -z "$volId" ]; then
echo "waiting for import to finish..."
while true; do
volId=$(ec2-describe-conversion-tasks "$taskId" --region "$region" | sed 's/.*VolumeId.*\(vol-[0-9a-f]\+\).*/\1/ ; t ; d')
if [ -n "$volId" ]; then break; fi
volId=$(aws ec2 describe-conversion-tasks --conversion-task-ids "$taskId" --region "$region" | jq -r .ConversionTasks[0].ImportVolume.Volume.Id)
if [ "$volId" != null ]; then break; fi
sleep 10
done
@ -143,22 +149,24 @@ for type in hvm pv; do
# Delete the import task.
if [ -n "$volId" -a -n "$taskId" ]; then
echo "removing import task..."
ec2-delete-disk-image -t "$taskId" --region "$region" -o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY" || true
ec2-delete-disk-image -t "$taskId" --region "$region" \
-O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
-o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" || true
rm -f $stateDir/$region.$type.task-id
fi
# Create a snapshot.
if [ -z "$snapId" ]; then
echo "creating snapshot..."
snapId=$(ec2-create-snapshot "$volId" --region "$region" | cut -f 2)
snapId=$(aws ec2 create-snapshot --volume-id "$volId" --region "$region" --description "$description" | jq -r .SnapshotId)
if [ "$snapId" = null ]; then exit 1; fi
echo -n "$snapId" > $stateDir/$region.$type.snap-id
ec2-create-tags "$snapId" -t "Name=$description" --region "$region"
fi
# Wait for the snapshot to finish.
echo "waiting for snapshot to finish..."
while true; do
status=$(ec2-describe-snapshots "$snapId" --region "$region" | head -n1 | cut -f 4)
status=$(aws ec2 describe-snapshots --snapshot-ids "$snapId" --region "$region" | jq -r .Snapshots[0].State)
if [ "$status" = completed ]; then break; fi
sleep 10
done
@ -166,35 +174,50 @@ for type in hvm pv; do
# Delete the volume.
if [ -n "$volId" ]; then
echo "deleting volume..."
ec2-delete-volume "$volId" --region "$region" || true
aws ec2 delete-volume --volume-id "$volId" --region "$region" || true
rm -f $stateDir/$region.$type.vol-id
fi
extraFlags="-b /dev/sda1=$snapId:$vhdFileLogicalGigaBytes:true:gp2"
blockDeviceMappings="DeviceName=/dev/sda1,Ebs={SnapshotId=$snapId,VolumeSize=$vhdFileLogicalGigaBytes,DeleteOnTermination=true,VolumeType=gp2}"
extraFlags=""
if [ $type = pv ]; then
extraFlags+=" --root-device-name=/dev/sda1"
extraFlags+=" --root-device-name /dev/sda1"
else
extraFlags+=" --root-device-name /dev/sda1"
extraFlags+=" --sriov-net-support simple"
extraFlags+=" --ena-support"
fi
extraFlags+=" -b /dev/sdb=ephemeral0 -b /dev/sdc=ephemeral1 -b /dev/sdd=ephemeral2 -b /dev/sde=ephemeral3"
blockDeviceMappings+=" DeviceName=/dev/sdb,VirtualName=ephemeral0"
blockDeviceMappings+=" DeviceName=/dev/sdc,VirtualName=ephemeral1"
blockDeviceMappings+=" DeviceName=/dev/sdd,VirtualName=ephemeral2"
blockDeviceMappings+=" DeviceName=/dev/sde,VirtualName=ephemeral3"
fi
if [ $type = hvm ]; then
extraFlags+=" --sriov-net-support simple"
extraFlags+=" --ena-support"
fi
# Register the AMI.
if [ $type = pv ]; then
kernel=$(ec2-describe-images -o amazon --filter "manifest-location=*pv-grub-hd0_1.04-$arch*" --region "$region" | cut -f 2)
[ -n "$kernel" ]
kernel=$(aws ec2 describe-images --owner amazon --filters "Name=name,Values=pv-grub-hd0_1.04-$arch.gz" | jq -r .Images[0].ImageId)
if [ "$kernel" = null ]; then break; fi
echo "using PV-GRUB kernel $kernel"
extraFlags+=" --virtualization-type paravirtual --kernel $kernel"
else
extraFlags+=" --virtualization-type hvm"
fi
ami=$(ec2-register \
-n "$name" \
-d "$description" \
ami=$(aws ec2 register-image \
--name "$name" \
--description "$description" \
--region "$region" \
--architecture "$arch" \
$extraFlags | cut -f 2)
--block-device-mappings $blockDeviceMappings \
$extraFlags | jq -r .ImageId)
if [ "$ami" = null ]; then break; fi
fi
echo -n "$ami" > $amiFile
@ -204,23 +227,45 @@ for type in hvm pv; do
ami=$(cat $amiFile)
fi
if [ -z "$NO_WAIT" -o -z "$prevAmi" ]; then
echo "waiting for AMI..."
while true; do
status=$(ec2-describe-images "$ami" --region "$region" | head -n1 | cut -f 5)
if [ "$status" = available ]; then break; fi
sleep 10
done
ec2-modify-image-attribute \
--region "$region" "$ami" -l -a all
fi
echo "region = $region, type = $type, store = $store, ami = $ami"
if [ -z "$prevAmi" ]; then
prevAmi="$ami"
prevRegion="$region"
fi
done
done
done
for type in $types; do
link=$stateDir/$type
system=x86_64-linux
arch=x86_64
for store in $stores; do
for region in $regions; do
name=nixos-$version-$arch-$type-$store
amiFile=$stateDir/$region.$type.$store.ami-id
ami=$(cat $amiFile)
echo "region = $region, type = $type, store = $store, ami = $ami"
echo -n "waiting for AMI..."
while true; do
status=$(aws ec2 describe-images --image-ids "$ami" --region "$region" | jq -r .Images[0].State)
if [ "$status" = available ]; then break; fi
sleep 10
echo -n '.'
done
echo
# Make the image public.
aws ec2 modify-image-attribute \
--image-id "$ami" --region "$region" --launch-permission 'Add={Group=all}'
echo " \"$major\".$region.$type-$store = \"$ami\";" >> ec2-amis.nix
done

View File

@ -3,6 +3,84 @@
with lib;
let fcBool = x: if x then "<bool>true</bool>" else "<bool>false</bool>";
cfg = config.fonts.fontconfig.ultimate;
fontconfigUltimateConf = pkgs.writeText "ultimate-conf" ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
${optionalString (!cfg.allowBitmaps) ''
<!-- Reject bitmap fonts -->
<selectfont>
<rejectfont>
<pattern>
<patelt name="scalable"><bool>false</bool></patelt>
</pattern>
</rejectfont>
</selectfont>
''}
${optionalString cfg.allowType1 ''
<!-- Reject Type 1 fonts -->
<selectfont>
<rejectfont>
<pattern>
<patelt name="fontformat">
<string>Type 1</string>
</patelt>
</pattern>
</rejectfont>
</selectfont>
''}
<!-- Use embedded bitmaps in fonts like Calibri? -->
<match target="font">
<edit name="embeddedbitmap" mode="assign">
${fcBool cfg.useEmbeddedBitmaps}
</edit>
</match>
<!-- Force autohint always -->
<match target="font">
<edit name="force_autohint" mode="assign">
${fcBool cfg.forceAutohint}
</edit>
</match>
<!-- Render some monospace TTF fonts as bitmaps -->
<match target="pattern">
<edit name="bitmap_monospace" mode="assign">
${fcBool cfg.renderMonoTTFAsBitmap}
</edit>
</match>
</fontconfig>
'';
confPkg =
let version = pkgs.fontconfig.configVersion;
in pkgs.runCommand "font-ultimate-conf" {} ''
mkdir -p $out/etc/fonts/{,${version}/}conf.d/
cp ${fontconfigUltimateConf} \
$out/etc/fonts/conf.d/52-fontconfig-ultimate.conf
cp ${fontconfigUltimateConf} \
$out/etc/fonts/${version}/conf.d/52-fontconfig-ultimate.conf
${optionalString (cfg.substitutions != "none") ''
cp ${pkgs.fontconfig-ultimate.confd}/etc/fonts/presets/${cfg.substitutions}/*.conf \
$out/etc/fonts/conf.d/
cp ${pkgs.fontconfig-ultimate.confd}/etc/fonts/presets/${cfg.substitutions}/*.conf \
$out/etc/fonts/${version}/conf.d/
''}
ln -s ${pkgs.fontconfig-ultimate.confd}/etc/fonts/conf.d/*.conf \
$out/etc/fonts/conf.d/
ln -s ${pkgs.fontconfig-ultimate.confd}/etc/fonts/conf.d/*.conf \
$out/etc/fonts/${version}/conf.d/
'';
in
{
@ -115,78 +193,11 @@ in
};
config =
let ultimate = config.fonts.fontconfig.ultimate;
fontconfigUltimateConf = ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
config = mkIf (config.fonts.fontconfig.enable && cfg.enable) {
${optionalString (!ultimate.allowBitmaps) ''
<!-- Reject bitmap fonts -->
<selectfont>
<rejectfont>
<pattern>
<patelt name="scalable"><bool>false</bool></patelt>
</pattern>
</rejectfont>
</selectfont>
''}
${optionalString ultimate.allowType1 ''
<!-- Reject Type 1 fonts -->
<selectfont>
<rejectfont>
<pattern>
<patelt name="fontformat">
<string>Type 1</string>
</patelt>
</pattern>
</rejectfont>
</selectfont>
''}
<!-- Use embedded bitmaps in fonts like Calibri? -->
<match target="font">
<edit name="embeddedbitmap" mode="assign">
${fcBool ultimate.useEmbeddedBitmaps}
</edit>
</match>
<!-- Force autohint always -->
<match target="font">
<edit name="force_autohint" mode="assign">
${fcBool ultimate.forceAutohint}
</edit>
</match>
<!-- Render some monospace TTF fonts as bitmaps -->
<match target="pattern">
<edit name="bitmap_monospace" mode="assign">
${fcBool ultimate.renderMonoTTFAsBitmap}
</edit>
</match>
${optionalString (ultimate.substitutions != "none") ''
<!-- Type 1 font substitutions -->
<include ignore_missing="yes">${pkgs.fontconfig-ultimate.confd}/etc/fonts/presets/${ultimate.substitutions}</include>
''}
<include ignore_missing="yes">${pkgs.fontconfig-ultimate.confd}/etc/fonts/conf.d</include>
</fontconfig>
'';
in mkIf (config.fonts.fontconfig.enable && ultimate.enable) {
environment.etc."fonts/conf.d/52-fontconfig-ultimate.conf" = {
text = fontconfigUltimateConf;
};
environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/52-fontconfig-ultimate.conf" = {
text = fontconfigUltimateConf;
};
environment.variables = ultimate.rendering;
fonts.fontconfig.confPkgs = [ confPkg ];
environment.variables = cfg.rendering;
};

View File

@ -2,6 +2,121 @@
with lib;
let cfg = config.fonts.fontconfig;
fcBool = x: "<bool>" + (if x then "true" else "false") + "</bool>";
renderConf = pkgs.writeText "render-conf" ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Default rendering settings -->
<match target="font">
<edit mode="assign" name="hinting">
${fcBool cfg.hinting.enable}
</edit>
<edit mode="assign" name="autohint">
${fcBool cfg.hinting.autohint}
</edit>
<edit mode="assign" name="hintstyle">
<const>hint${cfg.hinting.style}</const>
</edit>
<edit mode="assign" name="antialias">
${fcBool cfg.antialias}
</edit>
<edit mode="assign" name="rgba">
<const>${cfg.subpixel.rgba}</const>
</edit>
<edit mode="assign" name="lcdfilter">
<const>lcd${cfg.subpixel.lcdfilter}</const>
</edit>
</match>
${optionalString (cfg.dpi != 0) ''
<match target="pattern">
<edit name="dpi" mode="assign">
<double>${toString cfg.dpi}</double>
</edit>
</match>
''}
</fontconfig>
'';
genericAliasConf =
let genDefault = fonts: name:
optionalString (fonts != []) ''
<alias>
<family>${name}</family>
<prefer>
${concatStringsSep ""
(map (font: ''
<family>${font}</family>
'') fonts)}
</prefer>
</alias>
'';
in
pkgs.writeText "generic-alias-conf" ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Default fonts -->
${genDefault cfg.defaultFonts.sansSerif "sans-serif"}
${genDefault cfg.defaultFonts.serif "serif"}
${genDefault cfg.defaultFonts.monospace "monospace"}
</fontconfig>
'';
cacheConf = let
cache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
in
pkgs.writeText "cache-conf" ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Font directories -->
${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
<!-- Pre-generated font caches -->
<cachedir>${cache pkgs.fontconfig}</cachedir>
${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) ''
<cachedir>${cache pkgs.pkgsi686Linux.fontconfig}</cachedir>
''}
</fontconfig>
'';
userConf = pkgs.writeText "user-conf" ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
<include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
</fontconfig>
'';
fontsConf = pkgs.makeFontsConf { fontconfig = pkgs.fontconfig_210; fontDirectories = config.fonts.fonts; };
confPkg =
let version = pkgs.fontconfig.configVersion;
in pkgs.runCommand "fontconfig-conf" {} ''
mkdir -p $out/etc/fonts/{,${version}/}conf.d
ln -s ${fontsConf} $out/etc/fonts/fonts.conf
ln -s ${pkgs.fontconfig.out}/etc/fonts/fonts.conf $out/etc/fonts/${version}/fonts.conf
ln -s ${pkgs.fontconfig.out}/etc/fonts/conf.d/* $out/etc/fonts/${version}/conf.d/
ln -s ${renderConf} $out/etc/fonts/conf.d/10-nixos-rendering.conf
ln -s ${genericAliasConf} $out/etc/fonts/conf.d/60-nixos-generic-alias.conf
ln -s ${cacheConf} $out/etc/fonts/${version}/conf.d/00-nixos.conf
ln -s ${renderConf} $out/etc/fonts/${version}/conf.d/10-nixos-rendering.conf
ln -s ${genericAliasConf} $out/etc/fonts/${version}/conf.d/30-nixos-generic-alias.conf
${optionalString cfg.includeUserConf
"ln -s ${userConf} $out/etc/fonts/${version}/conf.d/99-user.conf"}
'';
in
{
options = {
@ -21,6 +136,15 @@ with lib;
'';
};
confPkgs = mkOption {
internal = true;
type = with types; listOf path;
default = [ ];
description = ''
Fontconfig configuration packages.
'';
};
antialias = mkOption {
type = types.bool;
default = true;
@ -143,135 +267,17 @@ with lib;
};
config =
let fontconfig = config.fonts.fontconfig;
fcBool = x: "<bool>" + (if x then "true" else "false") + "</bool>";
renderConf = ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
config = mkIf cfg.enable {
fonts.fontconfig.confPkgs = [ confPkg ];
<!-- Default rendering settings -->
<match target="font">
<edit mode="assign" name="hinting">
${fcBool fontconfig.hinting.enable}
</edit>
<edit mode="assign" name="autohint">
${fcBool fontconfig.hinting.autohint}
</edit>
<edit mode="assign" name="hintstyle">
<const>hint${fontconfig.hinting.style}</const>
</edit>
<edit mode="assign" name="antialias">
${fcBool fontconfig.antialias}
</edit>
<edit mode="assign" name="rgba">
<const>${fontconfig.subpixel.rgba}</const>
</edit>
<edit mode="assign" name="lcdfilter">
<const>lcd${fontconfig.subpixel.lcdfilter}</const>
</edit>
</match>
environment.etc.fonts.source =
let fontConf = pkgs.symlinkJoin {
name = "fontconfig-etc";
paths = cfg.confPkgs;
};
in "${fontConf}/etc/fonts/";
${optionalString (fontconfig.dpi != 0) ''
<match target="pattern">
<edit name="dpi" mode="assign">
<double>${toString fontconfig.dpi}</double>
</edit>
</match>
''}
</fontconfig>
'';
genericAliasConf = ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Default fonts -->
${optionalString (fontconfig.defaultFonts.sansSerif != []) ''
<alias>
<family>sans-serif</family>
<prefer>
${concatStringsSep "\n"
(map (font: "<family>${font}</family>")
fontconfig.defaultFonts.sansSerif)}
</prefer>
</alias>
''}
${optionalString (fontconfig.defaultFonts.serif != []) ''
<alias>
<family>serif</family>
<prefer>
${concatStringsSep "\n"
(map (font: "<family>${font}</family>")
fontconfig.defaultFonts.serif)}
</prefer>
</alias>
''}
${optionalString (fontconfig.defaultFonts.monospace != []) ''
<alias>
<family>monospace</family>
<prefer>
${concatStringsSep "\n"
(map (font: "<family>${font}</family>")
fontconfig.defaultFonts.monospace)}
</prefer>
</alias>
''}
</fontconfig>
'';
in mkIf fontconfig.enable {
# Fontconfig 2.10 backward compatibility
# Bring in the default (upstream) fontconfig configuration, only for fontconfig 2.10
environment.etc."fonts/fonts.conf".source =
pkgs.makeFontsConf { fontconfig = pkgs.fontconfig_210; fontDirectories = config.fonts.fonts; };
environment.etc."fonts/conf.d/10-nixos-rendering.conf".text = renderConf;
environment.etc."fonts/conf.d/60-nixos-generic-alias.conf".text = genericAliasConf;
# Versioned fontconfig > 2.10. Take shared fonts.conf from fontconfig.
# Otherwise specify only font directories.
environment.etc."fonts/${pkgs.fontconfig.configVersion}/fonts.conf".source =
"${pkgs.fontconfig.out}/etc/fonts/fonts.conf";
environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/00-nixos.conf".text =
let
cache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
in ''
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<!-- Font directories -->
${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
<!-- Pre-generated font caches -->
<cachedir>${cache pkgs.fontconfig}</cachedir>
${optionalString (pkgs.stdenv.isx86_64 && config.fonts.fontconfig.cache32Bit) ''
<cachedir>${cache pkgs.pkgsi686Linux.fontconfig}</cachedir>
''}
</fontconfig>
'';
environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/10-nixos-rendering.conf".text = renderConf;
environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/60-nixos-generic-alias.conf".text = genericAliasConf;
environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/99-user.conf" = {
enable = fontconfig.includeUserConf;
text = ''
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
<include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
</fontconfig>
'';
};
environment.systemPackages = [ pkgs.fontconfig ];
};
environment.systemPackages = [ pkgs.fontconfig ];
};
}

View File

@ -41,6 +41,15 @@ in
'';
};
consolePackages = mkOption {
type = types.listOf types.package;
default = with pkgs.kbdKeymaps; [ dvp neo ];
description = ''
List of additional packages that provide console fonts, keymaps and
other resources.
'';
};
consoleFont = mkOption {
type = types.str;
default = "Lat2-Terminus16";

View File

@ -1,7 +1,7 @@
# This module defines a global environment configuration and
# a common configuration for all shells.
{ config, lib, pkgs, ... }:
{ config, lib, utils, pkgs, ... }:
with lib;
@ -135,13 +135,13 @@ in
environment.shells = mkOption {
default = [];
example = [ "/run/current-system/sw/bin/zsh" ];
example = literalExample "[ pkgs.bashInteractive pkgs.zsh ]";
description = ''
A list of permissible login shells for user accounts.
No need to mention <literal>/bin/sh</literal>
here, it is placed into this list implicitly.
'';
type = types.listOf types.path;
type = types.listOf (types.either types.shellPackage types.path);
};
};
@ -158,7 +158,7 @@ in
environment.etc."shells".text =
''
${concatStringsSep "\n" cfg.shells}
${concatStringsSep "\n" (map utils.toShellPath cfg.shells)}
/bin/sh
'';

View File

@ -30,8 +30,7 @@ let
description = ''
If this option is set, device is interpreted as the
path of a swapfile that will be created automatically
with the indicated size (in megabytes) if it doesn't
exist.
with the indicated size (in megabytes).
'';
};
@ -132,9 +131,13 @@ in
script =
''
${optionalString (sw.size != null) ''
if [ ! -e "${sw.device}" ]; then
currentSize=$(( $(stat -c "%s" "${sw.device}" 2>/dev/null || echo 0) / 1024 / 1024 ))
if [ "${toString sw.size}" != "$currentSize" ]; then
fallocate -l ${toString sw.size}M "${sw.device}" ||
dd if=/dev/zero of="${sw.device}" bs=1M count=${toString sw.size}
if [ "${toString sw.size}" -lt "$currentSize" ]; then
truncate --size "${toString sw.size}M" "${sw.device}"
fi
chmod 0600 ${sw.device}
${optionalString (!sw.randomEncryption) "mkswap ${sw.realDevice}"}
fi

View File

@ -103,7 +103,7 @@ foreach my $g (@{$spec->{groups}}) {
if (defined $existing) {
$g->{gid} = $existing->{gid} if !defined $g->{gid};
if ($g->{gid} != $existing->{gid}) {
warn "warning: not applying GID change of group $name\n";
warn "warning: not applying GID change of group $name ($existing->{gid} -> $g->{gid})\n";
$g->{gid} = $existing->{gid};
}
$g->{password} = $existing->{password}; # do we want this?
@ -163,7 +163,7 @@ foreach my $u (@{$spec->{users}}) {
if (defined $existing) {
$u->{uid} = $existing->{uid} if !defined $u->{uid};
if ($u->{uid} != $existing->{uid}) {
warn "warning: not applying UID change of user $name\n";
warn "warning: not applying UID change of user $name ($existing->{uid} -> $u->{uid})\n";
$u->{uid} = $existing->{uid};
}
} else {

View File

@ -1,9 +1,8 @@
{ config, lib, pkgs, ... }:
{ config, lib, utils, pkgs, ... }:
with lib;
let
ids = config.ids;
cfg = config.users;
@ -103,7 +102,7 @@ let
};
home = mkOption {
type = types.str;
type = types.path;
default = "/var/empty";
description = "The user's home directory.";
};
@ -118,9 +117,17 @@ let
};
shell = mkOption {
type = types.str;
default = "/run/current-system/sw/bin/nologin";
description = "The path to the user's shell.";
type = types.either types.shellPackage types.path;
default = pkgs.nologin;
defaultText = "pkgs.nologin";
example = literalExample "pkgs.bashInteractive";
description = ''
The path to the user's shell. Can use shell derivations,
like <literal>pkgs.bashInteractive</literal>. Dont
forget to enable your shell in
<literal>programs</literal> if necessary,
like <code>programs.zsh.enable = true;</code>.
'';
};
subUidRanges = mkOption {
@ -359,11 +366,12 @@ let
spec = pkgs.writeText "users-groups.json" (builtins.toJSON {
inherit (cfg) mutableUsers;
users = mapAttrsToList (n: u:
users = mapAttrsToList (_: u:
{ inherit (u)
name uid group description home shell createHome isSystemUser
name uid group description home createHome isSystemUser
password passwordFile hashedPassword
initialPassword initialHashedPassword;
shell = utils.toShellPath u.shell;
}) cfg.users;
groups = mapAttrsToList (n: g:
{ inherit (g) name gid;
@ -373,6 +381,12 @@ let
}) cfg.groups;
});
systemShells =
let
shells = mapAttrsToList (_: u: u.shell) cfg.users;
in
filter types.shellPackage.check shells;
in {
###### interface
@ -468,7 +482,6 @@ in {
home = "/root";
shell = mkDefault cfg.defaultUserShell;
group = "root";
extraGroups = [ "grsecurity" ];
initialHashedPassword = mkDefault config.security.initialRootPassword;
};
nobody = {
@ -478,6 +491,9 @@ in {
};
};
# Install all the user shells
environment.systemPackages = systemShells;
users.groups = {
root.gid = ids.gids.root;
wheel.gid = ids.gids.wheel;
@ -497,7 +513,6 @@ in {
nixbld.gid = ids.gids.nixbld;
utmp.gid = ids.gids.utmp;
adm.gid = ids.gids.adm;
grsecurity.gid = ids.gids.grsecurity;
input.gid = ids.gids.input;
};

View File

@ -4,7 +4,7 @@ with lib;
let
cfg = config.i18n.inputMethod.fcitx;
fcitxPackage = pkgs.fcitx-with-plugins.override { plugins = cfg.engines; };
fcitxPackage = pkgs.fcitx.override { plugins = cfg.engines; };
fcitxEngine = types.package // {
name = "fcitx-engine";
check = x: (lib.types.package.check x) && (attrByPath ["meta" "isFcitxEngine"] false x);

View File

@ -19,18 +19,37 @@ in
"it cannot be cross compiled";
};
# Needed by RPi firmware
nixpkgs.config.allowUnfree = true;
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.kernelParams = ["console=ttyS0,115200n8" "console=ttymxc0,115200n8" "console=ttyAMA0,115200n8" "console=tty0"];
boot.kernelParams = ["console=ttyS0,115200n8" "console=ttymxc0,115200n8" "console=ttyAMA0,115200n8" "console=ttyO0,115200n8" "console=tty0"];
boot.consoleLogLevel = 7;
# FIXME: this probably should be in installation-device.nix
users.extraUsers.root.initialHashedPassword = "";
sdImage = {
populateBootCommands = ''
populateBootCommands = let
configTxt = pkgs.writeText "config.txt" ''
[pi2]
kernel=u-boot-rpi2.bin
[pi3]
kernel=u-boot-rpi3.bin
enable_uart=1
'';
in ''
for f in bootcode.bin fixup.dat start.elf; do
cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/$f boot/
done
cp ${pkgs.ubootRaspberryPi2}/u-boot.bin boot/u-boot-rpi2.bin
cp ${pkgs.ubootRaspberryPi3}/u-boot.bin boot/u-boot-rpi3.bin
cp ${configTxt} boot/config.txt
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
'';
'';
};
}

View File

@ -26,6 +26,7 @@ in
boot.loader.generic-extlinux-compatible.enable = true;
boot.kernelPackages = pkgs.linuxPackages_rpi;
boot.consoleLogLevel = 7;
# FIXME: this probably should be in installation-device.nix
users.extraUsers.root.initialHashedPassword = "";

View File

@ -91,12 +91,10 @@ ln -s /run $mountPoint/var/run
rm -f $mountPoint/etc/{resolv.conf,hosts}
cp -Lf /etc/resolv.conf /etc/hosts $mountPoint/etc/
if [ -e "$SSL_CERT_FILE" ]; then
cp -Lf "$SSL_CERT_FILE" "$mountPoint/tmp/ca-cert.crt"
export SSL_CERT_FILE=/tmp/ca-cert.crt
# For Nix 1.7
export CURL_CA_BUNDLE=/tmp/ca-cert.crt
fi
cp -Lf "@cacert@" "$mountPoint/tmp/ca-cert.crt"
export SSL_CERT_FILE=/tmp/ca-cert.crt
# For Nix 1.7
export CURL_CA_BUNDLE=/tmp/ca-cert.crt
if [ -n "$runChroot" ]; then
if ! [ -L $mountPoint/nix/var/nix/profiles/system ]; then

View File

@ -1,6 +1,10 @@
#! @shell@
case "$1" in
-h|--help)
exec man nixos-version
exit 1
;;
--hash|--revision)
echo "@nixosRevision@"
;;

View File

@ -23,6 +23,7 @@ let
inherit (pkgs) perl pathsFromGraph;
nix = config.nix.package.out;
cacert = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
nixClosure = pkgs.runCommand "closure"
{ exportReferencesGraph = ["refs" config.nix.package.out]; }

View File

@ -147,7 +147,6 @@
foundationdb = 118;
newrelic = 119;
starbound = 120;
#grsecurity = 121; # unused
hydra = 122;
spiped = 123;
teamspeak = 124;
@ -269,6 +268,8 @@
nzbget = 245;
mosquitto = 246;
toxvpn = 247;
squeezelite = 248;
turnserver = 249;
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
@ -369,7 +370,7 @@
quassel = 89;
amule = 90;
minidlna = 91;
#elasticsearch = 92; # unused
elasticsearch = 92;
#tcpcryptd = 93; # unused
connman = 94;
firebird = 95;
@ -396,7 +397,6 @@
foundationdb = 118;
newrelic = 119;
starbound = 120;
grsecurity = 121;
hydra = 122;
spiped = 123;
teamspeak = 124;
@ -508,6 +508,8 @@
nzbget = 245;
mosquitto = 246;
#toxvpn = 247; # unused
#squeezelite = 248; #unused
turnserver = 249;
# When adding a gid, make sure it doesn't match an existing
# uid. Users and groups with the same name should have equal

View File

@ -76,6 +76,7 @@
./programs/screen.nix
./programs/shadow.nix
./programs/shell.nix
./programs/spacefm.nix
./programs/ssh.nix
./programs/ssmtp.nix
./programs/tmux.nix
@ -110,6 +111,7 @@
./services/audio/liquidsoap.nix
./services/audio/mpd.nix
./services/audio/mopidy.nix
./services/audio/squeezelite.nix
./services/backup/almir.nix
./services/backup/bacula.nix
./services/backup/crashplan.nix
@ -125,10 +127,11 @@
./services/computing/torque/server.nix
./services/computing/torque/mom.nix
./services/computing/slurm/slurm.nix
./services/continuous-integration/jenkins/default.nix
./services/continuous-integration/jenkins/slave.nix
./services/continuous-integration/jenkins/job-builder.nix
./services/continuous-integration/buildkite-agent.nix
./services/continuous-integration/hydra/default.nix
./services/continuous-integration/jenkins/default.nix
./services/continuous-integration/jenkins/job-builder.nix
./services/continuous-integration/jenkins/slave.nix
./services/databases/4store-endpoint.nix
./services/databases/4store.nix
./services/databases/couchdb.nix
@ -162,6 +165,7 @@
./services/desktops/profile-sync-daemon.nix
./services/desktops/telepathy.nix
./services/development/hoogle.nix
./services/editors/emacs.nix
./services/games/factorio.nix
./services/games/ghost-one.nix
./services/games/minecraft-server.nix
@ -218,6 +222,7 @@
./services/misc/confd.nix
./services/misc/devmon.nix
./services/misc/dictd.nix
./services/misc/dysnomia.nix
./services/misc/disnix.nix
./services/misc/docker-registry.nix
./services/misc/emby.nix
@ -314,6 +319,7 @@
./services/networking/cntlm.nix
./services/networking/connman.nix
./services/networking/consul.nix
./services/networking/coturn.nix
./services/networking/ddclient.nix
./services/networking/dhcpcd.nix
./services/networking/dhcpd.nix
@ -362,6 +368,7 @@
./services/networking/ntopng.nix
./services/networking/ntpd.nix
./services/networking/nylon.nix
./services/networking/offlineimap.nix
./services/networking/oidentd.nix
./services/networking/openfire.nix
./services/networking/openntpd.nix
@ -369,6 +376,7 @@
./services/networking/ostinato.nix
./services/networking/pdnsd.nix
./services/networking/polipo.nix
./services/networking/pptpd.nix
./services/networking/prayer.nix
./services/networking/privoxy.nix
./services/networking/prosody.nix
@ -409,6 +417,7 @@
./services/networking/wicd.nix
./services/networking/wpa_supplicant.nix
./services/networking/xinetd.nix
./services/networking/xl2tpd.nix
./services/networking/zerobin.nix
./services/networking/zerotierone.nix
./services/networking/znc.nix
@ -455,6 +464,7 @@
./services/web-servers/lighttpd/cgit.nix
./services/web-servers/lighttpd/default.nix
./services/web-servers/lighttpd/gitweb.nix
./services/web-servers/lighttpd/inginious.nix
./services/web-servers/nginx/default.nix
./services/web-servers/phpfpm.nix
./services/web-servers/shellinabox.nix
@ -490,6 +500,7 @@
./services/x11/window-managers/windowlab.nix
./services/x11/window-managers/wmii.nix
./services/x11/window-managers/xmonad.nix
./services/x11/xbanish.nix
./services/x11/xfs.nix
./services/x11/xserver.nix
./system/activation/activation-script.nix
@ -513,6 +524,7 @@
./system/boot/luksroot.nix
./system/boot/modprobe.nix
./system/boot/networkd.nix
./system/boot/plymouth.nix
./system/boot/resolved.nix
./system/boot/shutdown.nix
./system/boot/stage-1.nix

View File

@ -42,7 +42,7 @@ with lib;
The "root" account has an empty password. ${
optionalString config.services.xserver.enable
"Type `start display-manager' to\nstart the graphical user interface."}
"Type `systemctl start display-manager' to\nstart the graphical user interface."}
'';
# Allow sshd to be started manually through "start sshd".

View File

@ -200,7 +200,7 @@ in
# Configuration for readline in bash.
environment.etc."inputrc".source = ./inputrc;
users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash";
users.defaultUserShell = mkDefault pkgs.bashInteractive;
environment.pathsToLink = optionals cfg.enableCompletion [
"/etc/bash_completion.d"

View File

@ -6,6 +6,7 @@ set meta-flag on
set input-meta on
set convert-meta off
set output-meta on
set colored-stats on
#set mark-symlinked-directories on

View File

@ -1,6 +1,6 @@
# Configuration for the pwdutils suite of tools: passwd, useradd, etc.
{ config, lib, pkgs, ... }:
{ config, lib, utils, pkgs, ... }:
with lib;
@ -43,13 +43,13 @@ in
users.defaultUserShell = lib.mkOption {
description = ''
This option defines the default shell assigned to user
accounts. This must not be a store path, since the path is
accounts. This can be either a full system path or a shell package.
This must not be a store path, since the path is
used outside the store (in particular in /etc/passwd).
Rather, it should be the path of a symlink that points to the
actual shell in the Nix store.
'';
example = "/run/current-system/sw/bin/zsh";
type = types.path;
example = literalExample "pkgs.zsh";
type = types.either types.path types.shellPackage;
};
};
@ -60,7 +60,9 @@ in
config = {
environment.systemPackages =
lib.optional config.users.mutableUsers pkgs.shadow;
lib.optional config.users.mutableUsers pkgs.shadow ++
lib.optional (types.shellPackage.check config.users.defaultUserShell)
config.users.defaultUserShell;
environment.etc =
[ { # /etc/login.defs: global configuration for pwdutils. You
@ -74,7 +76,7 @@ in
''
GROUP=100
HOME=/home
SHELL=${config.users.defaultUserShell}
SHELL=${utils.toShellPath config.users.defaultUserShell}
'';
target = "default/useradd";
}

View File

@ -0,0 +1,55 @@
# Global configuration for spacefm.
{ config, lib, pkgs, ... }:
with lib;
let cfg = config.programs.spacefm;
in
{
###### interface
options = {
programs.spacefm = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to install SpaceFM and create <filename>/etc/spacefm/spacefm.conf</filename>.
'';
};
settings = mkOption {
type = types.attrs;
default = {
tmp_dir = "/tmp";
terminal_su = "${pkgs.sudo}/bin/sudo";
graphical_su = "${pkgs.gksu}/bin/gksu";
};
example = literalExample ''{
tmp_dir = "/tmp";
terminal_su = "''${pkgs.sudo}/bin/sudo";
graphical_su = "''${pkgs.gksu}/bin/gksu";
}'';
description = ''
The system-wide spacefm configuration.
Parameters to be written to <filename>/etc/spacefm/spacefm.conf</filename>.
Refer to the <link xlink:href="https://ignorantguru.github.io/spacefm/spacefm-manual-en.html#programfiles-etc">relevant entry</link> in the SpaceFM manual.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.spaceFM ];
environment.etc."spacefm/spacefm.conf".text =
concatStrings (mapAttrsToList (n: v: "${n}=${toString v}\n") cfg.settings);
};
}

View File

@ -114,6 +114,26 @@ with lib;
(mkRenamedOptionModule [ "services" "iodined" "extraConfig" ] [ "services" "iodine" "server" "extraConfig" ])
(mkRemovedOptionModule [ "services" "iodined" "client" ])
# Grsecurity
(mkRemovedOptionModule [ "security" "grsecurity" "kernelPatch" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "mode" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "priority" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "system" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "virtualisationConfig" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "hardwareVirtualisation" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "virtualisationSoftware" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "sysctl" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "denyChrootChmod" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "denyChrootCaps" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "denyUSB" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "restrictProc" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "restrictProcWithGroup" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "unrestrictProcGid" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "disableRBAC" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "disableSimultConnect" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "verboseVersion" ])
(mkRemovedOptionModule [ "security" "grsecurity" "config" "kernelExtraConfig" ])
# Options that are obsolete and have no replacement.
(mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ])
(mkRemovedOptionModule [ "programs" "bash" "enable" ])

View File

@ -187,7 +187,7 @@ in
script = ''
cd '${cpath}'
set +e
simp_le ${concatMapStringsSep " " (arg: escapeShellArg (toString arg)) cmdline}
simp_le ${escapeShellArgs cmdline}
EXITCODE=$?
set -e
echo "$EXITCODE" > /tmp/lastExitCode

View File

@ -1,312 +1,122 @@
{ config, lib, pkgs, ... }:
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.security.grsecurity;
grsecLockPath = "/proc/sys/kernel/grsecurity/grsec_lock";
customGrsecPkg =
(import ../../../pkgs/build-support/grsecurity {
grsecOptions = cfg;
inherit pkgs lib;
}).grsecPackage;
# Ascertain whether ZFS is required for booting the system; grsecurity is
# currently incompatible with ZFS, rendering the system unbootable.
zfsNeededForBoot = filter
(fs: (fs.neededForBoot
|| elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ])
&& fs.fsType == "zfs")
(attrValues config.fileSystems) != [];
in
{
options = {
security.grsecurity = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable grsecurity support. This enables advanced exploit
hardening for the Linux kernel, and adds support for
administrative Role-Based Acess Control (RBAC) via
<literal>gradm</literal>. It also includes traditional
utilities for PaX.
'';
};
options.security.grsecurity = {
kernelPatch = mkOption {
type = types.attrs;
example = lib.literalExample "pkgs.kernelPatches.grsecurity_4_1";
description = ''
Grsecurity patch to use.
'';
};
enable = mkEnableOption "Grsecurity/PaX";
config = {
mode = mkOption {
type = types.enum [ "auto" "custom" ];
default = "auto";
description = ''
grsecurity configuration mode. This specifies whether
grsecurity is auto-configured or otherwise completely
manually configured.
'';
};
priority = mkOption {
type = types.enum [ "security" "performance" ];
default = "security";
description = ''
grsecurity configuration priority. This specifies whether
the kernel configuration should emphasize speed or
security.
'';
};
system = mkOption {
type = types.enum [ "desktop" "server" ];
default = "desktop";
description = ''
grsecurity system configuration.
'';
};
virtualisationConfig = mkOption {
type = types.nullOr (types.enum [ "host" "guest" ]);
default = null;
description = ''
grsecurity virtualisation configuration. This specifies
the virtualisation role of the machine - that is, whether
it will be a virtual machine guest, a virtual machine
host, or neither.
'';
};
hardwareVirtualisation = mkOption {
type = types.nullOr types.bool;
default = null;
example = true;
description = ''
grsecurity hardware virtualisation configuration. Set to
<literal>true</literal> if your machine supports hardware
accelerated virtualisation.
'';
};
virtualisationSoftware = mkOption {
type = types.nullOr (types.enum [ "kvm" "xen" "vmware" "virtualbox" ]);
default = null;
description = ''
Configure grsecurity for use with this virtualisation software.
'';
};
sysctl = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_SYSCTL y</literal>. If
enabled then grsecurity can be controlled using sysctl
(and turned off). You are advised to *never* enable this,
but if you do, make sure to always set the sysctl
<literal>kernel.grsecurity.grsec_lock</literal> to
non-zero as soon as all sysctl options are set. *THIS IS
EXTREMELY IMPORTANT*!
'';
};
denyChrootChmod = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_CHROOT_CHMOD
y</literal>. If enabled, this denies processes inside a
chroot from setting the suid or sgid bits using
<literal>chmod</literal> or <literal>fchmod</literal>.
By default this protection is disabled - it makes it
impossible to use Nix to build software on your system,
which is what most users want.
If you are using NixOps to deploy your software to a
remote machine, you're encouraged to enable this as you
won't need to compile code.
'';
};
denyChrootCaps = mkOption {
type = types.bool;
default = false;
description = ''
Whether to lower capabilities of all processes within a chroot,
preventing commands that require <literal>CAP_SYS_ADMIN</literal>.
This protection is disabled by default because it breaks
<literal>nixos-rebuild</literal>. Whenever possible, it is
highly recommended to enable this protection.
'';
};
denyUSB = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERNSEC_DENYUSB y</literal>.
This enables a sysctl with name
<literal>kernel.grsecurity.deny_new_usb</literal>. Setting
its value to <literal>1</literal> will prevent any new USB
devices from being recognized by the OS. Any attempted
USB device insertion will be logged.
This option is intended to be used against custom USB
devices designed to exploit vulnerabilities in various USB
device drivers.
'';
};
restrictProc = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_PROC_USER
y</literal>. This restricts non-root users to only viewing
their own processes and restricts network-related
information, kernel symbols, and module information.
'';
};
restrictProcWithGroup = mkOption {
type = types.bool;
default = true;
description = ''
If true, then set <literal>GRKERN_PROC_USERGROUP
y</literal>. This is similar to
<literal>restrictProc</literal> except it allows a special
group (specified by <literal>unrestrictProcGid</literal>)
to still access otherwise classified information in
<literal>/proc</literal>.
'';
};
unrestrictProcGid = mkOption {
type = types.int;
default = config.ids.gids.grsecurity;
description = ''
If set, specifies a GID which is exempt from
<literal>/proc</literal> restrictions (set by
<literal>GRKERN_PROC_USERGROUP</literal>). By default,
this is set to the GID for <literal>grsecurity</literal>,
a predefined NixOS group, which the
<literal>root</literal> account is a member of. You may
conveniently add other users to this group if you need
access to <literal>/proc</literal>
'';
};
disableRBAC = mkOption {
type = types.bool;
default = false;
description = ''
If true, then set <literal>GRKERN_NO_RBAC
y</literal>. This disables the
<literal>/dev/grsec</literal> device, which in turn
disables the RBAC system (and <literal>gradm</literal>).
'';
};
disableSimultConnect = mkOption {
type = types.bool;
default = false;
description = ''
Disable TCP simultaneous connect. The TCP simultaneous connect
feature allows two clients to connect without either of them
entering the listening state. This feature of the TCP specification
is claimed to enable an attacker to deny the target access to a given
server by guessing the source port the target would use to make the
connection.
This option is OFF by default because TCP simultaneous connect has
some legitimate uses. Enable this option if you know what this TCP
feature is for and know that you do not need it.
'';
};
verboseVersion = mkOption {
type = types.bool;
default = false;
description = "Use verbose version in kernel localversion.";
};
kernelExtraConfig = mkOption {
type = types.str;
default = "";
description = "Extra kernel configuration parameters.";
};
};
};
};
config = mkIf cfg.enable {
assertions =
[
{ assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) ||
(cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc);
message = "You cannot enable both restrictProc and restrictProcWithGroup";
}
{ assertion = config.boot.kernelPackages.kernel.features ? grsecurity
&& config.boot.kernelPackages.kernel.features.grsecurity;
message = "grsecurity enabled, but kernel doesn't have grsec support";
}
{ assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) ->
cfg.config.hardwareVirtualisation != null;
message = "when using auto grsec mode with virtualisation, you must specify if your hardware has virtualisation extensions";
}
{ assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) ->
cfg.config.virtualisationSoftware != null;
message = "grsecurity configured for virtualisation but no virtualisation software specified";
}
];
security.grsecurity.kernelPatch = lib.mkDefault pkgs.kernelPatches.grsecurity_latest;
systemd.services.grsec-lock = mkIf cfg.config.sysctl {
description = "grsecurity sysctl-lock Service";
wants = [ "systemd-sysctl.service" ];
after = [ "systemd-sysctl.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = "yes";
unitConfig.ConditionPathIsReadWrite = "/proc/sys/kernel/grsecurity/grsec_lock";
script = ''
locked=`cat /proc/sys/kernel/grsecurity/grsec_lock`
if [ "$locked" == "0" ]; then
echo 1 > /proc/sys/kernel/grsecurity/grsec_lock
echo grsecurity sysctl lock - enabled
else
echo grsecurity sysctl lock already enabled - doing nothing
fi
lockTunables = mkOption {
type = types.bool;
example = false;
default = true;
description = ''
Whether to automatically lock grsecurity tunables
(<option>boot.kernel.sysctl."kernel.grsecurity.*"</option>). Disable
this to allow configuration of grsecurity features while the system is
running. The lock can be manually engaged by activating the
<literal>grsec-lock</literal> service unit.
'';
};
# systemd.services.grsec-learn = {
# description = "grsecurity learning Service";
# wantedBy = [ "local-fs.target" ];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = "yes";
# ExecStart = "${pkgs.gradm}/sbin/gradm -VFL /etc/grsec/learning.logs";
# ExecStop = "${pkgs.gradm}/sbin/gradm -D";
# };
# };
};
system.activationScripts = lib.optionalAttrs (!cfg.config.disableRBAC) { grsec = ''
mkdir -p /etc/grsec
if [ ! -f /etc/grsec/learn_config ]; then
cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec
fi
if [ ! -f /etc/grsec/policy ]; then
cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec
fi
chmod -R 0600 /etc/grsec
''; };
config = mkIf cfg.enable {
# Allow the user to select a different package set, subject to the stated
# required kernel config
boot.kernelPackages = mkDefault pkgs.linuxPackages_grsec_nixos;
system.requiredKernelConfig = with config.lib.kernelConfig;
[ (isEnabled "GRKERNSEC")
(isEnabled "PAX")
(isYES "GRKERNSEC_SYSCTL")
(isYES "GRKERNSEC_SYSCTL_DISTRO")
];
# Crashing on an overflow in kernel land is user unfriendly and may prevent
# the system from booting, which is too severe for our use case.
boot.kernelParams = [ "pax_size_overflow_report_only" ];
# Install PaX related utillities into the system profile. Eventually, we
# also want to include gradm here.
environment.systemPackages = with pkgs; [ paxctl pax-utils ];
# Install rules for the grsec device node
services.udev.packages = [ pkgs.gradm ];
# This service unit is responsible for locking the Grsecurity tunables. The
# unit is always defined, but only activated on bootup if lockTunables is
# toggled. When lockTunables is toggled, failure to activate the unit will
# enter emergency mode. The intent is to make it difficult to silently
# enter multi-user mode without having locked the tunables. Some effort is
# made to ensure that starting the unit is an idempotent operation.
systemd.services.grsec-lock = {
description = "Lock grsecurity tunables";
wantedBy = optional cfg.lockTunables "multi-user.target";
wants = [ "local-fs.target" "systemd-sysctl.service" ];
after = [ "local-fs.target" "systemd-sysctl.service" ];
conflicts = [ "shutdown.target" ];
restartIfChanged = false;
script = ''
if ${pkgs.gnugrep}/bin/grep -Fq 0 ${grsecLockPath} ; then
echo -n 1 > ${grsecLockPath}
fi
'';
unitConfig = {
ConditionPathIsReadWrite = grsecLockPath;
DefaultDependencies = false;
} // optionalAttrs cfg.lockTunables {
OnFailure = "emergency.target";
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
};
# Configure system tunables
boot.kernel.sysctl = {
# Removed under grsecurity
"kernel.kptr_restrict" = mkForce null;
} // optionalAttrs config.nix.useSandbox {
# chroot(2) restrictions that conflict with sandboxed Nix builds
"kernel.grsecurity.chroot_caps" = mkForce 0;
"kernel.grsecurity.chroot_deny_chroot" = mkForce 0;
"kernel.grsecurity.chroot_deny_mount" = mkForce 0;
"kernel.grsecurity.chroot_deny_pivot" = mkForce 0;
} // optionalAttrs config.boot.enableContainers {
# chroot(2) restrictions that conflict with NixOS lightweight containers
"kernel.grsecurity.chroot_deny_chmod" = mkForce 0;
"kernel.grsecurity.chroot_deny_mount" = mkForce 0;
"kernel.grsecurity.chroot_restrict_nice" = mkForce 0;
};
assertions = [
{ assertion = !zfsNeededForBoot;
message = "grsecurity is currently incompatible with ZFS";
}
];
# Enable AppArmor, gradm udev rules, and utilities
security.apparmor.enable = true;
boot.kernelPackages = customGrsecPkg;
services.udev.packages = lib.optional (!cfg.config.disableRBAC) pkgs.gradm;
environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils ] ++ lib.optional (!cfg.config.disableRBAC) pkgs.gradm;
};
}

View File

@ -0,0 +1,67 @@
{ config, lib, pkgs, ... }:
with lib;
let
uid = config.ids.uids.squeezelite;
cfg = config.services.squeezelite;
in {
###### interface
options = {
services.squeezelite= {
enable = mkEnableOption "Squeezelite, a software Squeezebox emulator";
dataDir = mkOption {
default = "/var/lib/squeezelite";
type = types.str;
description = ''
The directory where Squeezelite stores its name file.
'';
};
extraArguments = mkOption {
default = "";
type = types.str;
description = ''
Additional command line arguments to pass to Squeezelite.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
systemd.services.squeezelite= {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "sound.target" ];
description = "Software Squeezebox emulator";
preStart = "mkdir -p ${cfg.dataDir} && chown -R squeezelite ${cfg.dataDir}";
serviceConfig = {
ExecStart = "${pkgs.squeezelite}/bin/squeezelite -N ${cfg.dataDir}/player-name ${cfg.extraArguments}";
User = "squeezelite";
PermissionsStartOnly = true;
};
};
users.extraUsers.squeezelite= {
inherit uid;
group = "nogroup";
extraGroups = [ "audio" ];
description = "Squeezelite user";
home = "${cfg.dataDir}";
};
};
}

View File

@ -0,0 +1,100 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.buildkite-agent;
configFile = pkgs.writeText "buildkite-agent.cfg"
''
token="${cfg.token}"
name="${cfg.name}"
meta-data="${cfg.meta-data}"
hooks-path="${pkgs.buildkite-agent}/share/hooks"
build-path="/var/lib/buildkite-agent/builds"
bootstrap-script="${pkgs.buildkite-agent}/share/bootstrap.sh"
'';
in
{
options = {
services.buildkite-agent = {
enable = mkEnableOption "buildkite-agent";
token = mkOption {
type = types.str;
description = ''
The token from your Buildkite "Agents" page.
'';
};
name = mkOption {
type = types.str;
description = ''
The name of the agent.
'';
};
meta-data = mkOption {
type = types.str;
default = "";
description = ''
Meta data for the agent.
'';
};
openssh =
{ privateKey = mkOption {
type = types.str;
description = ''
Private agent key.
'';
};
publicKey = mkOption {
type = types.str;
description = ''
Public agent key.
'';
};
};
};
};
config = mkIf config.services.buildkite-agent.enable {
users.extraUsers.buildkite-agent =
{ name = "buildkite-agent";
home = "/var/lib/buildkite-agent";
createHome = true;
description = "Buildkite agent user";
};
environment.systemPackages = [ pkgs.buildkite-agent ];
systemd.services.buildkite-agent =
{ description = "Buildkite Agent";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment.HOME = "/var/lib/buildkite-agent";
preStart = ''
${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/lib/buildkite-agent/.ssh
if ! [ -f /var/lib/buildkite-agent/.ssh/id_rsa ]; then
echo "${cfg.openssh.privateKey}" > /var/lib/buildkite-agent/.ssh/id_rsa
${pkgs.coreutils}/bin/chmod 600 /var/lib/buildkite-agent/.ssh/id_rsa
fi
if ! [ -f /var/lib/buildkite-agent/.ssh/id_rsa.pub ]; then
echo "${cfg.openssh.publicKey}" > /var/lib/buildkite-agent/.ssh/id_rsa.pub
${pkgs.coreutils}/bin/chmod 600 /var/lib/buildkite-agent/.ssh/id_rsa.pub
fi
'';
serviceConfig =
{ ExecStart = "${pkgs.buildkite-agent}/bin/buildkite-agent start --config ${configFile}";
User = "buildkite-agent";
RestartSec = 5;
Restart = "on-failure";
TimeoutSec = 10;
};
};
};
}

View File

@ -154,7 +154,7 @@ in {
'';
script = ''
${pkgs.jdk}/bin/java -jar ${pkgs.jenkins} --httpListenAddress=${cfg.listenAddress} \
${pkgs.jdk}/bin/java -jar ${pkgs.jenkins}/lib/jenkins.war --httpListenAddress=${cfg.listenAddress} \
--httpPort=${toString cfg.port} \
--prefix=${cfg.prefix} \
${concatStringsSep " " cfg.extraOptions}

View File

@ -40,6 +40,13 @@ in
description = "Group account under which slapd runs.";
};
urlList = mkOption {
type = types.listOf types.string;
default = [ "ldap:///" ];
description = "URL list slapd should listen on.";
example = [ "ldaps:///" ];
};
dataDir = mkOption {
type = types.string;
default = "/var/db/openldap";
@ -50,7 +57,7 @@ in
type = types.lines;
default = "";
description = "
sldapd.conf configuration
slapd.conf configuration
";
example = literalExample ''
'''
@ -89,7 +96,7 @@ in
mkdir -p ${cfg.dataDir}
chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}
'';
serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -f ${configFile}";
serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -h \"${concatStringsSep " " cfg.urlList}\" -f ${configFile}";
};
users.extraUsers.openldap =

View File

@ -0,0 +1,86 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.emacs;
editorScript = pkgs.writeScriptBin "emacseditor" ''
#!${pkgs.stdenv.shell}
if [ -z "$1" ]; then
exec ${cfg.package}/bin/emacsclient --create-frame --alternate-editor ${cfg.package}/bin/emacs
else
exec ${cfg.package}/bin/emacsclient --alternate-editor ${cfg.package}/bin/emacs "$@"
fi
'';
in {
options.services.emacs = {
enable = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to enable a user service for the Emacs daemon. Use <literal>emacsclient</literal> to connect to the
daemon. If <literal>true</literal>, <varname>services.emacs.install</varname> is
considered <literal>true</literal>, whatever its value.
'';
};
install = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to install a user service for the Emacs daemon. Once
the service is started, use emacsclient to connect to the
daemon.
The service must be manually started for each user with
"systemctl --user start emacs" or globally through
<varname>services.emacs.enable</varname>.
'';
};
package = mkOption {
type = types.package;
default = pkgs.emacs;
defaultText = "pkgs.emacs";
description = ''
emacs derivation to use.
'';
};
defaultEditor = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
When enabled, configures emacsclient to be the default editor
using the EDITOR environment variable.
'';
};
};
config = mkIf (cfg.enable || cfg.install) {
systemd.user.services.emacs = {
description = "Emacs: the extensible, self-documenting text editor";
serviceConfig = {
Type = "forking";
ExecStart = "${pkgs.bash}/bin/bash -c 'source ${config.system.build.setEnvironment}; exec ${cfg.package}/bin/emacs --daemon'";
ExecStop = "${cfg.package}/bin/emacsclient --eval (kill-emacs)";
Restart = "always";
};
} // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
environment.systemPackages = [ cfg.package editorScript ];
environment.variables = if cfg.defaultEditor then {
EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor";
} else {};
};
}

View File

@ -78,7 +78,7 @@ in
test -e ${stateDir}/saves/${cfg.saveName}.zip || \
${pkgs.factorio-headless}/bin/factorio \
--config=${cfg.configFile} \
--create=${cfg.saveName}
--create=${stateDir}/saves/${cfg.saveName}.zip
'';
serviceConfig = {
@ -93,7 +93,7 @@ in
"${pkgs.factorio-headless}/bin/factorio"
"--config=${cfg.configFile}"
"--port=${toString cfg.port}"
"--start-server=${cfg.saveName}"
"--start-server=${stateDir}/saves/${cfg.saveName}.zip"
];
};
};

View File

@ -54,6 +54,9 @@ in
config = mkIf cfg.enable {
powerManagement.scsiLinkPolicy = null;
powerManagement.cpuFreqGovernor = null;
systemd.services = {
tlp = {
description = "TLP system startup/shutdown";
@ -61,6 +64,7 @@ in
after = [ "multi-user.target" ];
wantedBy = [ "multi-user.target" ];
before = [ "shutdown.target" ];
restartTriggers = [ confFile ];
serviceConfig = {
Type = "oneshot";

View File

@ -105,7 +105,7 @@ in
prune {
whitelist_names => [
"type", "@timestamp", "@version",
"MESSAGE", "PRIORITY", "SYSLOG_FACILITY",
"MESSAGE", "PRIORITY", "SYSLOG_FACILITY"
]
}
}

View File

@ -101,7 +101,7 @@ in {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.opendkim}/bin/opendkim ${concatMapStringsSep " " escapeShellArg args}";
ExecStart = "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}";
User = cfg.user;
Group = cfg.group;
RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim";

View File

@ -127,11 +127,11 @@ let
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#submission inet n - n - - smtpd
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
'' + optionalString cfg.enableSubmission ''
submission inet n - n - - smtpd
${concatStringsSep "\n " (mapAttrsToList (x: y: "-o " + x + "=" + y) cfg.submissionOptions)}
''
+ ''
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr
@ -201,6 +201,28 @@ in
default = true;
description = "Whether to enable smtp in master.cf.";
};
enableSubmission = mkOption {
type = types.bool;
default = false;
description = "Whether to enable smtp submission";
};
submissionOptions = mkOption {
type = types.attrs;
default = { "smtpd_tls_security_level" = "encrypt";
"smtpd_sasl_auth_enable" = "yes";
"smtpd_client_restrictions" = "permit_sasl_authenticated,reject";
"milter_macro_daemon_name" = "ORIGINATING";
};
description = "Options for the submission config in master.cf";
example = { "smtpd_tls_security_level" = "encrypt";
"smtpd_sasl_auth_enable" = "yes";
"smtpd_sasl_type" = "dovecot";
"smtpd_client_restrictions" = "permit_sasl_authenticated,reject";
"milter_macro_daemon_name" = "ORIGINATING";
};
};
setSendmail = mkOption {
type = types.bool;

View File

@ -75,7 +75,7 @@ in {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/confd";
ExecStart = "${cfg.package.bin}/bin/confd";
};
};

View File

@ -36,49 +36,32 @@ in
default = false;
description = "Whether to enable the DisnixWebService interface running on Apache Tomcat";
};
publishInfrastructure = {
enable = mkOption {
default = false;
description = "Whether to publish capabilities/properties of this machine in as attributes in the infrastructure option";
};
enableAuthentication = mkOption {
default = false;
description = "Whether to publish authentication credentials through the infrastructure attribute (not recommended in combination with Avahi)";
};
};
infrastructure = mkOption {
default = {};
description = "List of name value pairs containing properties for the infrastructure model";
};
publishAvahi = mkOption {
default = false;
description = "Whether to publish capabilities/properties as a Disnix service through Avahi";
package = mkOption {
type = types.path;
description = "The Disnix package";
default = pkgs.disnix;
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.disnix pkgs.dysnomia ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService;
dysnomia.enable = true;
environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService;
services.dbus.enable = true;
services.dbus.packages = [ pkgs.disnix ];
services.avahi.enable = cfg.publishAvahi;
services.tomcat.enable = cfg.useWebServiceInterface;
services.tomcat.extraGroups = [ "disnix" ];
services.tomcat.javaOpts = "${optionalString cfg.useWebServiceInterface "-Djava.library.path=${pkgs.libmatthew_java}/lib/jni"} ";
services.tomcat.sharedLibs = optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar"
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
users.extraGroups = singleton
@ -86,38 +69,6 @@ in
gid = config.ids.gids.disnix;
};
services.disnix.infrastructure =
optionalAttrs (cfg.publishInfrastructure.enable)
( { hostname = config.networking.hostName;
#targetHost = config.deployment.targetHost;
system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system;
supportedTypes = (import "${pkgs.stdenv.mkDerivation {
name = "supportedtypes";
buildCommand = ''
( echo -n "[ "
cd ${dysnomia}/libexec/dysnomia
for i in *
do
echo -n "\"$i\" "
done
echo -n " ]") > $out
'';
}}");
}
#// optionalAttrs (cfg.useWebServiceInterface) { targetEPR = "http://${config.deployment.targetHost}:8080/DisnixWebService/services/DisnixWebService"; }
// optionalAttrs (config.services.httpd.enable) { documentRoot = config.services.httpd.documentRoot; }
// optionalAttrs (config.services.mysql.enable) { mysqlPort = config.services.mysql.port; }
// optionalAttrs (config.services.tomcat.enable) { tomcatPort = 8080; }
// optionalAttrs (config.services.svnserve.enable) { svnBaseDir = config.services.svnserve.svnBaseDir; }
// optionalAttrs (config.services.ejabberd.enable) { ejabberdUser = config.services.ejabberd.user; }
// optionalAttrs (cfg.publishInfrastructure.enableAuthentication) (
optionalAttrs (config.services.mysql.enable) { mysqlUsername = "root"; mysqlPassword = readFile config.services.mysql.rootPassword; })
)
;
services.disnix.publishInfrastructure.enable = cfg.publishAvahi;
systemd.services = {
disnix = {
description = "Disnix server";
@ -133,46 +84,17 @@ in
restartIfChanged = false;
path = [ pkgs.nix pkgs.disnix dysnomia "/run/current-system/sw" ];
path = [ config.nix.package cfg.package config.dysnomia.package "/run/current-system/sw" ];
environment = {
HOME = "/root";
};
preStart = ''
mkdir -p /etc/systemd-mutable/system
if [ ! -f /etc/systemd-mutable/system/dysnomia.target ]
then
( echo "[Unit]"
echo "Description=Services that are activated and deactivated by Dysnomia"
echo "After=final.target"
) > /etc/systemd-mutable/system/dysnomia.target
fi
'';
script = "disnix-service";
}
// (if config.environment.variables ? DYSNOMIA_CONTAINERS_PATH then { inherit (config.environment.variables) DYSNOMIA_CONTAINERS_PATH; } else {})
// (if config.environment.variables ? DYSNOMIA_MODULES_PATH then { inherit (config.environment.variables) DYSNOMIA_MODULES_PATH; } else {});
serviceConfig.ExecStart = "${cfg.package}/bin/disnix-service";
};
} // optionalAttrs cfg.publishAvahi {
disnixAvahi = {
description = "Disnix Avahi publisher";
wants = [ "avahi-daemon.service" ];
wantedBy = [ "multi-user.target" ];
script = ''
${pkgs.avahi}/bin/avahi-publish-service disnix-${config.networking.hostName} _disnix._tcp 22 \
"mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \
${concatMapStrings (infrastructureAttrName:
let infrastructureAttrValue = getAttr infrastructureAttrName (cfg.infrastructure);
in
if isInt infrastructureAttrValue then
''${infrastructureAttrName}=${toString infrastructureAttrValue} \
''
else
''${infrastructureAttrName}=\"${infrastructureAttrValue}\" \
''
) (attrNames (cfg.infrastructure))}
'';
};
};
};
}

View File

@ -0,0 +1,217 @@
{pkgs, lib, config, ...}:
with lib;
let
cfg = config.dysnomia;
printProperties = properties:
concatMapStrings (propertyName:
let
property = properties."${propertyName}";
in
if isList property then "${propertyName}=(${lib.concatMapStrings (elem: "\"${toString elem}\" ") (properties."${propertyName}")})\n"
else "${propertyName}=\"${toString property}\"\n"
) (builtins.attrNames properties);
properties = pkgs.stdenv.mkDerivation {
name = "dysnomia-properties";
buildCommand = ''
cat > $out << "EOF"
${printProperties cfg.properties}
EOF
'';
};
containersDir = pkgs.stdenv.mkDerivation {
name = "dysnomia-containers";
buildCommand = ''
mkdir -p $out
cd $out
${concatMapStrings (containerName:
let
containerProperties = cfg.containers."${containerName}";
in
''
cat > ${containerName} <<EOF
${printProperties containerProperties}
type=${containerName}
EOF
''
) (builtins.attrNames cfg.containers)}
'';
};
linkMutableComponents = {containerName}:
''
mkdir ${containerName}
${concatMapStrings (componentName:
let
component = cfg.components."${containerName}"."${componentName}";
in
"ln -s ${component} ${containerName}/${componentName}\n"
) (builtins.attrNames (cfg.components."${containerName}" or {}))}
'';
componentsDir = pkgs.stdenv.mkDerivation {
name = "dysnomia-components";
buildCommand = ''
mkdir -p $out
cd $out
${concatMapStrings (containerName:
let
components = cfg.components."${containerName}";
in
linkMutableComponents { inherit containerName; }
) (builtins.attrNames cfg.components)}
'';
};
in
{
options = {
dysnomia = {
enable = mkOption {
type = types.bool;
default = false;
description = "Whether to enable Dysnomia";
};
enableAuthentication = mkOption {
type = types.bool;
default = false;
description = "Whether to publish privacy-sensitive authentication credentials";
};
package = mkOption {
type = types.path;
description = "The Dysnomia package";
};
properties = mkOption {
description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions.";
default = {};
};
containers = mkOption {
description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties";
default = {};
};
components = mkOption {
description = "An atttribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state";
default = {};
};
extraContainerProperties = mkOption {
description = "An attribute set providing additional container settings in addition to the default properties";
default = {};
};
extraContainerPaths = mkOption {
description = "A list of paths containing additional container configurations that are added to the search folders";
default = [];
};
extraModulePaths = mkOption {
description = "A list of paths containing additional modules that are added to the search folders";
default = [];
};
};
};
config = mkIf cfg.enable {
environment.etc = {
"dysnomia/containers" = {
source = containersDir;
};
"dysnomia/components" = {
source = componentsDir;
};
"dysnomia/properties" = {
source = properties;
};
};
environment.variables = {
DYSNOMIA_STATEDIR = "/var/state/dysnomia-nixos";
DYSNOMIA_CONTAINERS_PATH = "${lib.concatMapStrings (containerPath: "${containerPath}:") cfg.extraContainerPaths}/etc/dysnomia/containers";
DYSNOMIA_MODULES_PATH = "${lib.concatMapStrings (modulePath: "${modulePath}:") cfg.extraModulePaths}/etc/dysnomia/modules";
};
environment.systemPackages = [ cfg.package ];
dysnomia.package = pkgs.dysnomia.override (origArgs: {
enableApacheWebApplication = config.services.httpd.enable;
enableAxis2WebService = config.services.tomcat.axis2.enable;
enableEjabberdDump = config.services.ejabberd.enable;
enableMySQLDatabase = config.services.mysql.enable;
enablePostgreSQLDatabase = config.services.postgresql.enable;
enableSubversionRepository = config.services.svnserve.enable;
enableTomcatWebApplication = config.services.tomcat.enable;
enableMongoDatabase = config.services.mongodb.enable;
});
dysnomia.properties = {
hostname = config.networking.hostName;
system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system;
supportedTypes = (import "${pkgs.stdenv.mkDerivation {
name = "supportedtypes";
buildCommand = ''
( echo -n "[ "
cd ${cfg.package}/libexec/dysnomia
for i in *
do
echo -n "\"$i\" "
done
echo -n " ]") > $out
'';
}}");
};
dysnomia.containers = lib.recursiveUpdate ({
process = {};
wrapper = {};
}
// lib.optionalAttrs (config.services.httpd.enable) { apache-webapplication = {
documentRoot = config.services.httpd.documentRoot;
}; }
// lib.optionalAttrs (config.services.tomcat.axis2.enable) { axis2-webservice = {}; }
// lib.optionalAttrs (config.services.ejabberd.enable) { ejabberd-dump = {
ejabberdUser = config.services.ejabberd.user;
}; }
// lib.optionalAttrs (config.services.mysql.enable) { mysql-database = {
mysqlPort = config.services.mysql.port;
} // lib.optionalAttrs cfg.enableAuthentication {
mysqlUsername = "root";
mysqlPassword = builtins.readFile (config.services.mysql.rootPassword);
};
}
// lib.optionalAttrs (config.services.postgresql.enable && cfg.enableAuthentication) { postgresql-database = {
postgresqlUsername = "root";
}; }
// lib.optionalAttrs (config.services.tomcat.enable) { tomcat-webapplication = {
tomcatPort = 8080;
}; }
// lib.optionalAttrs (config.services.mongodb.enable) { mongo-database = {}; }
// lib.optionalAttrs (config.services.svnserve.enable) { subversion-repository = {
svnBaseDir = config.services.svnserve.svnBaseDir;
}; }) cfg.extraContainerProperties;
system.activationScripts.dysnomia = ''
mkdir -p /etc/systemd-mutable/system
if [ ! -f /etc/systemd-mutable/system/dysnomia.target ]
then
( echo "[Unit]"
echo "Description=Services that are activated and deactivated by Dysnomia"
echo "After=final.target"
) > /etc/systemd-mutable/system/dysnomia.target
fi
'';
};
}

View File

@ -115,7 +115,7 @@ in {
serviceConfig = {
Type = "notify";
ExecStart = "${pkgs.etcd}/bin/etcd";
ExecStart = "${pkgs.etcd.bin}/bin/etcd";
User = "etcd";
PermissionsStartOnly = true;
};

View File

@ -5,17 +5,31 @@ with lib;
let
cfg = config.services.matrix-synapse;
logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${if r.compress then "true" else "false"}}'';
mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${if l.tls then "true" else "false"}, x_forwarded: ${if l.x_forwarded then "true" else "false"}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
configFile = pkgs.writeText "homeserver.yaml" ''
tls_certificate_path: "${cfg.tls_certificate_path}"
${optionalString (cfg.tls_private_key_path != null) ''
tls_private_key_path: "${cfg.tls_private_key_path}"
''}
tls_dh_params_path: "${cfg.tls_dh_params_path}"
no_tls: ${if cfg.no_tls then "true" else "false"}
${optionalString (cfg.bind_port != null) ''
bind_port: ${toString cfg.bind_port}
''}
${optionalString (cfg.unsecure_port != null) ''
unsecure_port: ${toString cfg.unsecure_port}
''}
${optionalString (cfg.bind_host != null) ''
bind_host: "${cfg.bind_host}"
''}
server_name: "${cfg.server_name}"
pid_file: "/var/run/matrix-synapse.pid"
web_client: ${if cfg.web_client then "true" else "false"}
${optionalString (cfg.public_baseurl != null) ''
public_baseurl: "${cfg.public_baseurl}"
''}
listeners: [${concatStringsSep "," (map mkListener cfg.listeners)}]
database: {
name: "${cfg.database_type}",
args: {
@ -24,21 +38,41 @@ database: {
)}
}
}
event_cache_size: "${cfg.event_cache_size}"
verbose: ${cfg.verbose}
log_file: "/var/log/matrix-synapse/homeserver.log"
log_config: "${logConfigFile}"
rc_messages_per_second: ${cfg.rc_messages_per_second}
rc_message_burst_count: ${cfg.rc_message_burst_count}
federation_rc_window_size: ${cfg.federation_rc_window_size}
federation_rc_sleep_limit: ${cfg.federation_rc_sleep_limit}
federation_rc_sleep_delay: ${cfg.federation_rc_sleep_delay}
federation_rc_reject_limit: ${cfg.federation_rc_reject_limit}
federation_rc_concurrent: ${cfg.federation_rc_concurrent}
media_store_path: "/var/lib/matrix-synapse/media"
uploads_path: "/var/lib/matrix-synapse/uploads"
max_upload_size: "${cfg.max_upload_size}"
max_image_pixels: "${cfg.max_image_pixels}"
dynamic_thumbnails: ${if cfg.dynamic_thumbnails then "true" else "false"}
url_preview_enabled: False
recaptcha_private_key: "${cfg.recaptcha_private_key}"
recaptcha_public_key: "${cfg.recaptcha_public_key}"
enable_registration_captcha: ${if cfg.enable_registration_captcha then "true" else "false"}
turn_uris: ${if (length cfg.turn_uris) == 0 then "[]" else ("\n" + (concatStringsSep "\n" (map (s: "- " + s) cfg.turn_uris)))}
turn_uris: ${builtins.toJSON cfg.turn_uris}
turn_shared_secret: "${cfg.turn_shared_secret}"
enable_registration: ${if cfg.enable_registration then "true" else "false"}
${optionalString (cfg.registration_shared_secret != "") ''
${optionalString (cfg.registration_shared_secret != null) ''
registration_shared_secret: "${cfg.registration_shared_secret}"
''}
recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
turn_user_lifetime: "${cfg.turn_user_lifetime}"
user_creation_max_duration: ${cfg.user_creation_max_duration}
bcrypt_rounds: ${cfg.bcrypt_rounds}
allow_guest_access: {if cfg.allow_guest_access then "true" else "false"}
enable_metrics: ${if cfg.enable_metrics then "true" else "false"}
report_stats: ${if cfg.report_stats then "true" else "false"}
signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key"
key_refresh_interval: "${cfg.key_refresh_interval}"
perspectives:
servers: {
${concatStringsSep "},\n" (mapAttrsToList (n: v: ''
@ -52,6 +86,8 @@ perspectives:
'') cfg.servers)}
}
}
app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
${cfg.extraConfig}
'';
in {
@ -73,53 +109,65 @@ in {
Don't bind to the https port
'';
};
tls_certificate_path = mkOption {
type = types.path;
default = "/var/lib/matrix-synapse/homeserver.tls.crt";
description = ''
PEM encoded X509 certificate for TLS
'';
};
tls_private_key_path = mkOption {
type = types.path;
default = "/var/lib/matrix-synapse/homeserver.tls.key";
description = ''
PEM encoded private key for TLS
'';
};
tls_dh_params_path = mkOption {
type = types.path;
default = "/var/lib/matrix-synapse/homeserver.tls.dh";
description = ''
PEM dh parameters for ephemeral keys
'';
};
bind_port = mkOption {
type = types.int;
default = 8448;
type = types.nullOr types.int;
default = null;
example = 8448;
description = ''
DEPRECATED: Use listeners instead.
The port to listen for HTTPS requests on.
For when matrix traffic is sent directly to synapse.
'';
};
unsecure_port = mkOption {
type = types.int;
default = 8008;
type = types.nullOr types.int;
default = null;
example = 8008;
description = ''
DEPRECATED: Use listeners instead.
The port to listen for HTTP requests on.
For when matrix traffic passes through loadbalancer that unwraps TLS.
'';
};
bind_host = mkOption {
type = types.str;
default = "";
type = types.nullOr types.str;
default = null;
description = ''
DEPRECATED: Use listeners instead.
Local interface to listen on.
The empty string will cause synapse to listen on all interfaces.
'';
};
tls_certificate_path = mkOption {
type = types.str;
default = "/var/lib/matrix-synapse/homeserver.tls.crt";
description = ''
PEM encoded X509 certificate for TLS.
You can replace the self-signed certificate that synapse
autogenerates on launch with your own SSL certificate + key pair
if you like. Any required intermediary certificates can be
appended after the primary certificate in hierarchical order.
'';
};
tls_private_key_path = mkOption {
type = types.nullOr types.str;
default = "/var/lib/matrix-synapse/homeserver.tls.key";
example = null;
description = ''
PEM encoded private key for TLS. Specify null if synapse is not
speaking TLS directly.
'';
};
tls_dh_params_path = mkOption {
type = types.str;
default = "/var/lib/matrix-synapse/homeserver.tls.dh";
description = ''
PEM dh parameters for ephemeral keys
'';
};
server_name = mkOption {
type = types.str;
example = "example.com";
description = ''
The domain name of the server, with optional explicit port.
This is used by remote servers to connect to this server,
@ -134,6 +182,145 @@ in {
Whether to serve a web client from the HTTP/HTTPS root resource.
'';
};
public_baseurl = mkOption {
type = types.nullOr types.str;
default = null;
example = "https://example.com:8448/";
description = ''
The public-facing base URL for the client API (not including _matrix/...)
'';
};
listeners = mkOption {
type = types.listOf (types.submodule {
options = {
port = mkOption {
type = types.int;
example = 8448;
description = ''
The port to listen for HTTP(S) requests on.
'';
};
bind_address = mkOption {
type = types.str;
default = "";
example = "203.0.113.42";
description = ''
Local interface to listen on.
The empty string will cause synapse to listen on all interfaces.
'';
};
type = mkOption {
type = types.str;
default = "http";
description = ''
Type of listener.
'';
};
tls = mkOption {
type = types.bool;
default = true;
description = ''
Whether to listen for HTTPS connections rather than HTTP.
'';
};
x_forwarded = mkOption {
type = types.bool;
default = false;
description = ''
Use the X-Forwarded-For (XFF) header as the client IP and not the
actual client IP.
'';
};
resources = mkOption {
type = types.listOf (types.submodule {
options = {
names = mkOption {
type = types.listOf types.str;
description = ''
List of resources to host on this listener.
'';
example = ["client" "webclient" "federation"];
};
compress = mkOption {
type = types.bool;
description = ''
Should synapse compress HTTP responses to clients that support it?
This should be disabled if running synapse behind a load balancer
that can do automatic compression.
'';
};
};
});
description = ''
List of HTTP resources to serve on this listener.
'';
};
};
});
default = [{
port = 8448;
bind_address = "";
type = "http";
tls = true;
x_forwarded = false;
resources = [
{ names = ["client" "webclient"]; compress = true; }
{ names = ["federation"]; compress = false; }
];
}];
description = ''
List of ports that Synapse should listen on, their purpose and their configuration.
'';
};
verbose = mkOption {
type = types.str;
default = "0";
description = "Logging verbosity level.";
};
rc_messages_per_second = mkOption {
type = types.str;
default = "0.2";
description = "Number of messages a client can send per second";
};
rc_message_burst_count = mkOption {
type = types.str;
default = "10.0";
description = "Number of message a client can send before being throttled";
};
federation_rc_window_size = mkOption {
type = types.str;
default = "1000";
description = "The federation window size in milliseconds";
};
federation_rc_sleep_limit = mkOption {
type = types.str;
default = "10";
description = ''
The number of federation requests from a single server in a window
before the server will delay processing the request.
'';
};
federation_rc_sleep_delay = mkOption {
type = types.str;
default = "500";
description = ''
The duration in milliseconds to delay processing events from
remote servers by if they go over the sleep limit.
'';
};
federation_rc_reject_limit = mkOption {
type = types.str;
default = "50";
description = ''
The maximum number of concurrent federation requests allowed
from a single server
'';
};
federation_rc_concurrent = mkOption {
type = types.str;
default = "3";
description = "The number of federation requests to concurrently process from a single server";
};
database_type = mkOption {
type = types.enum [ "sqlite3" "psycopg2" ];
default = "sqlite3";
@ -150,6 +337,11 @@ in {
Arguments to pass to the engine.
'';
};
event_cache_size = mkOption {
type = types.str;
default = "10K";
description = "Number of events to cache in memory.";
};
recaptcha_private_key = mkOption {
type = types.str;
default = "";
@ -187,6 +379,11 @@ in {
The shared secret used to compute passwords for the TURN server
'';
};
turn_user_lifetime = mkOption {
type = types.str;
default = "1h";
description = "How long generated TURN credentials last";
};
enable_registration = mkOption {
type = types.bool;
default = false;
@ -195,8 +392,8 @@ in {
'';
};
registration_shared_secret = mkOption {
type = types.str;
default = "";
type = types.nullOr types.str;
default = null;
description = ''
If set, allows registration by anyone who also has the shared
secret, even if registration is otherwise disabled.
@ -216,7 +413,7 @@ in {
'';
};
servers = mkOption {
type = types.attrs;
type = types.attrsOf (types.attrsOf types.str);
default = {
"matrix.org" = {
"ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
@ -226,6 +423,69 @@ in {
The trusted servers to download signing keys from.
'';
};
max_upload_size = mkOption {
type = types.str;
default = "10M";
description = "The largest allowed upload size in bytes";
};
max_image_pixels = mkOption {
type = types.str;
default = "32M";
description = "Maximum number of pixels that will be thumbnailed";
};
dynamic_thumbnails = mkOption {
type = types.bool;
default = false;
description = ''
Whether to generate new thumbnails on the fly to precisely match
the resolution requested by the client. If true then whenever
a new resolution is requested by the client the server will
generate a new thumbnail. If false the server will pick a thumbnail
from a precalculated list.
'';
};
user_creation_max_duration = mkOption {
type = types.str;
default = "1209600000";
description = ''
Sets the expiry for the short term user creation in
milliseconds. The default value is two weeks.
'';
};
bcrypt_rounds = mkOption {
type = types.str;
default = "12";
description = ''
Set the number of bcrypt rounds used to generate password hash.
Larger numbers increase the work factor needed to generate the hash.
'';
};
allow_guest_access = mkOption {
type = types.bool;
default = false;
description = ''
Allows users to register as guests without a password/email/etc, and
participate in rooms hosted on this server which have been made
accessible to anonymous users.
'';
};
key_refresh_interval = mkOption {
type = types.str;
default = "1d";
description = ''
How long key response published by this server is valid for.
Used to set the valid_until_ts in /key/v2 APIs.
Determines how quickly servers will query to check which keys
are still valid.
'';
};
app_service_config_files = mkOption {
type = types.listOf types.path;
default = [ ];
description = ''
A list of application service config file to use
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
@ -265,7 +525,7 @@ in {
mkdir -p /var/lib/matrix-synapse
chmod 700 /var/lib/matrix-synapse
chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse
${cfg.package}/bin/homeserver --config-path ${configFile} --generate-keys
${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys
'';
serviceConfig = {
Type = "simple";

View File

@ -91,7 +91,7 @@ in
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.nodePackages_0_10.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
};
};

View File

@ -152,8 +152,6 @@ let
};
};
mkShellStr = val: "'${replaceStrings ["'"] ["'\\''"] val}'";
certtool = "${pkgs.gnutls.bin}/bin/certtool";
nixos-taskserver = pkgs.buildPythonPackage {

View File

@ -148,7 +148,7 @@ in {
User = cfg.user;
Group = cfg.group;
ExecStart = ''
${cfg.package}/bin/bosun -c ${configFile}
${cfg.package.bin}/bin/bosun -c ${configFile}
'';
};
};

View File

@ -228,7 +228,7 @@ in {
after = ["networking.target"];
environment = mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions;
serviceConfig = {
ExecStart = "${cfg.package}/bin/grafana-server -homepath ${cfg.dataDir}";
ExecStart = "${cfg.package.bin}/bin/grafana-server -homepath ${cfg.dataDir}";
WorkingDirectory = cfg.dataDir;
User = "grafana";
};

View File

@ -119,7 +119,7 @@ in {
PermissionsStartOnly = true;
User = cfg.user;
Group = cfg.group;
ExecStart = "${cfg.package}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}";
ExecStart = "${cfg.package.bin}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}";
};
};

View File

@ -24,6 +24,7 @@ let
use-ipv4=${if ipv4 then "yes" else "no"}
use-ipv6=${if ipv6 then "yes" else "no"}
${optionalString (interfaces!=null) "allow-interfaces=${concatStringsSep "," interfaces}"}
${optionalString (domainName!=null) "domain-name=${domainName}"}
[wide-area]
enable-wide-area=${if wideArea then "yes" else "no"}
@ -65,6 +66,14 @@ in
'';
};
domainName = mkOption {
type = types.str;
default = "local";
description = ''
Domain name for all advertisements.
'';
};
browseDomains = mkOption {
default = [ "0pointer.de" "zeroconf.org" ];
description = ''

View File

@ -178,14 +178,14 @@ in
(filterAttrs (n: _: hasPrefix "consul.d/" n) config.environment.etc);
serviceConfig = {
ExecStart = "@${cfg.package}/bin/consul consul agent -config-dir /etc/consul.d"
ExecStart = "@${cfg.package.bin}/bin/consul consul agent -config-dir /etc/consul.d"
+ concatMapStrings (n: " -config-file ${n}") configFiles;
ExecReload = "${cfg.package}/bin/consul reload";
ExecReload = "${cfg.package.bin}/bin/consul reload";
PermissionsStartOnly = true;
User = if cfg.dropPrivileges then "consul" else null;
TimeoutStartSec = "0";
} // (optionalAttrs (cfg.leaveOnStop) {
ExecStop = "${cfg.package}/bin/consul leave";
ExecStop = "${cfg.package.bin}/bin/consul leave";
});
path = with pkgs; [ iproute gnugrep gawk consul ];
@ -236,7 +236,7 @@ in
serviceConfig = {
ExecStart = ''
${cfg.alerts.package}/bin/consul-alerts start \
${cfg.alerts.package.bin}/bin/consul-alerts start \
--alert-addr=${cfg.alerts.listenAddr} \
--consul-addr=${cfg.alerts.consulAddr} \
${optionalString cfg.alerts.watchChecks "--watch-checks"} \

View File

@ -0,0 +1,327 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.coturn;
pidfile = "/run/turnserver/turnserver.pid";
configFile = pkgs.writeText "turnserver.conf" ''
listening-port=${toString cfg.listening-port}
tls-listening-port=${toString cfg.tls-listening-port}
alt-listening-port=${toString cfg.alt-listening-port}
alt-tls-listening-port=${toString cfg.alt-tls-listening-port}
${concatStringsSep "\n" (map (x: "listening-ip=${x}") cfg.listening-ips)}
${concatStringsSep "\n" (map (x: "relay-ip=${x}") cfg.relay-ips)}
min-port=${toString cfg.min-port}
max-port=${toString cfg.max-port}
${lib.optionalString cfg.lt-cred-mech "lt-cred-mech"}
${lib.optionalString cfg.no-auth "no-auth"}
${lib.optionalString cfg.use-auth-secret "use-auth-secret"}
${lib.optionalString (cfg.static-auth-secret != null) ("static-auth-secret=${cfg.static-auth-secret}")}
realm=${cfg.realm}
${lib.optionalString cfg.no-udp "no-udp"}
${lib.optionalString cfg.no-tcp "no-tcp"}
${lib.optionalString cfg.no-tls "no-tls"}
${lib.optionalString cfg.no-dtls "no-dtls"}
${lib.optionalString cfg.no-udp-relay "no-udp-relay"}
${lib.optionalString cfg.no-tcp-relay "no-tcp-relay"}
${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"}
${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"}
${lib.optionalString (cfg.dh-file != null) ("dh-file=${cfg.dh-file}")}
no-stdout-log
syslog
pidfile=${pidfile}
${lib.optionalString cfg.secure-stun "secure-stun"}
${lib.optionalString cfg.no-cli "no-cli"}
cli-ip=${cfg.cli-ip}
cli-port=${toString cfg.cli-port}
${lib.optionalString (cfg.cli-password != null) ("cli-password=${cfg.cli-password}")}
${cfg.extraConfig}
'';
in {
options = {
services.coturn = {
enable = mkEnableOption "coturn TURN server";
listening-port = mkOption {
type = types.int;
default = 3478;
description = ''
TURN listener port for UDP and TCP.
Note: actually, TLS and DTLS sessions can connect to the
"plain" TCP and UDP port(s), too - if allowed by configuration.
'';
};
tls-listening-port = mkOption {
type = types.int;
default = 5349;
description = ''
TURN listener port for TLS.
Note: actually, "plain" TCP and UDP sessions can connect to the TLS and
DTLS port(s), too - if allowed by configuration. The TURN server
"automatically" recognizes the type of traffic. Actually, two listening
endpoints (the "plain" one and the "tls" one) are equivalent in terms of
functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
For secure TCP connections, we currently support SSL version 3 and
TLS version 1.0, 1.1 and 1.2.
For secure UDP connections, we support DTLS version 1.
'';
};
alt-listening-port = mkOption {
type = types.int;
default = cfg.listening-port + 1;
defaultText = "listening-port + 1";
description = ''
Alternative listening port for UDP and TCP listeners;
default (or zero) value means "listening port plus one".
This is needed for RFC 5780 support
(STUN extension specs, NAT behavior discovery). The TURN Server
supports RFC 5780 only if it is started with more than one
listening IP address of the same family (IPv4 or IPv6).
RFC 5780 is supported only by UDP protocol, other protocols
are listening to that endpoint only for "symmetry".
'';
};
alt-tls-listening-port = mkOption {
type = types.int;
default = cfg.tls-listening-port + 1;
defaultText = "tls-listening-port + 1";
description = ''
Alternative listening port for TLS and DTLS protocols.
'';
};
listening-ips = mkOption {
type = types.listOf types.str;
default = [];
example = [ "203.0.113.42" "2001:DB8::42" ];
description = ''
Listener IP addresses of relay server.
If no IP(s) specified in the config file or in the command line options,
then all IPv4 and IPv6 system IPs will be used for listening.
'';
};
relay-ips = mkOption {
type = types.listOf types.str;
default = [];
example = [ "203.0.113.42" "2001:DB8::42" ];
description = ''
Relay address (the local IP address that will be used to relay the
packets to the peer).
Multiple relay addresses may be used.
The same IP(s) can be used as both listening IP(s) and relay IP(s).
If no relay IP(s) specified, then the turnserver will apply the default
policy: it will decide itself which relay addresses to be used, and it
will always be using the client socket IP address as the relay IP address
of the TURN session (if the requested relay address family is the same
as the family of the client socket).
'';
};
min-port = mkOption {
type = types.int;
default = 49152;
description = ''
Lower bound of UDP relay endpoints
'';
};
max-port = mkOption {
type = types.int;
default = 65535;
description = ''
Upper bound of UDP relay endpoints
'';
};
lt-cred-mech = mkOption {
type = types.bool;
default = false;
description = ''
Use long-term credential mechanism.
'';
};
no-auth = mkOption {
type = types.bool;
default = false;
description = ''
This option is opposite to lt-cred-mech.
(TURN Server with no-auth option allows anonymous access).
If neither option is defined, and no users are defined,
then no-auth is default. If at least one user is defined,
in this file or in command line or in usersdb file, then
lt-cred-mech is default.
'';
};
use-auth-secret = mkOption {
type = types.bool;
default = false;
description = ''
TURN REST API flag.
Flag that sets a special authorization option that is based upon authentication secret.
This feature can be used with the long-term authentication mechanism, only.
This feature purpose is to support "TURN Server REST API", see
"TURN REST API" link in the project's page
https://github.com/coturn/coturn/
This option is used with timestamp:
usercombo -> "timestamp:userid"
turn user -> usercombo
turn password -> base64(hmac(secret key, usercombo))
This allows TURN credentials to be accounted for a specific user id.
If you don't have a suitable id, the timestamp alone can be used.
This option is just turning on secret-based authentication.
The actual value of the secret is defined either by option static-auth-secret,
or can be found in the turn_secret table in the database.
'';
};
static-auth-secret = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
'Static' authentication secret value (a string) for TURN REST API only.
If not set, then the turn server
will try to use the 'dynamic' value in turn_secret table
in user database (if present). The database-stored value can be changed on-the-fly
by a separate program, so this is why that other mode is 'dynamic'.
'';
};
realm = mkOption {
type = types.str;
default = config.networking.hostName;
example = "example.com";
description = ''
The default realm to be used for the users when no explicit
origin/realm relationship was found in the database, or if the TURN
server is not using any database (just the commands-line settings
and the userdb file). Must be used with long-term credentials
mechanism or with TURN REST API.
'';
};
cert = mkOption {
type = types.nullOr types.str;
default = null;
example = "/var/lib/acme/example.com/fullchain.pem";
description = ''
Certificate file in PEM format.
'';
};
pkey = mkOption {
type = types.nullOr types.str;
default = null;
example = "/var/lib/acme/example.com/key.pem";
description = ''
Private key file in PEM format.
'';
};
dh-file = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Use custom DH TLS key, stored in PEM format in the file.
'';
};
secure-stun = mkOption {
type = types.bool;
default = false;
description = ''
Require authentication of the STUN Binding request.
By default, the clients are allowed anonymous access to the STUN Binding functionality.
'';
};
no-cli = mkOption {
type = types.bool;
default = false;
description = ''
Turn OFF the CLI support.
'';
};
cli-ip = mkOption {
type = types.str;
default = "127.0.0.1";
description = ''
Local system IP address to be used for CLI server endpoint.
'';
};
cli-port = mkOption {
type = types.int;
default = 5766;
description = ''
CLI server port.
'';
};
cli-password = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
CLI access password.
For the security reasons, it is recommended to use the encrypted
for of the password (see the -P command in the turnadmin utility).
'';
};
no-udp = mkOption {
type = types.bool;
default = false;
description = "Disable UDP client listener";
};
no-tcp = mkOption {
type = types.bool;
default = false;
description = "Disable TCP client listener";
};
no-tls = mkOption {
type = types.bool;
default = false;
description = "Disable TLS client listener";
};
no-dtls = mkOption {
type = types.bool;
default = false;
description = "Disable DTLS client listener";
};
no-udp-relay = mkOption {
type = types.bool;
default = false;
description = "Disable UDP relay endpoints";
};
no-tcp-relay = mkOption {
type = types.bool;
default = false;
description = "Disable TCP relay endpoints";
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = "Additional configuration options";
};
};
};
config = mkIf cfg.enable {
users.extraUsers = [
{ name = "turnserver";
uid = config.ids.uids.turnserver;
description = "coturn TURN server user";
} ];
users.extraGroups = [
{ name = "turnserver";
gid = config.ids.gids.turnserver;
members = [ "turnserver" ];
} ];
systemd.services.coturn = {
description = "coturn TURN server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
unitConfig = {
Documentation = "man:coturn(1) man:turnadmin(1) man:turnserver(1)";
};
serviceConfig = {
Type = "simple";
ExecStart = "${pkgs.coturn}/bin/turnserver -c ${configFile}";
RuntimeDirectory = "turnserver";
User = "turnserver";
Group = "turnserver";
Restart = "on-abort";
};
};
};
}

View File

@ -7,22 +7,8 @@ let
stateDir = "/var/spool/ddclient";
ddclientUser = "ddclient";
ddclientFlags = "-foreground -verbose -noquiet -file ${ddclientCfg}";
ddclientFlags = "-foreground -verbose -noquiet -file /etc/ddclient.conf";
ddclientPIDFile = "${stateDir}/ddclient.pid";
ddclientCfg = pkgs.writeText "ddclient.conf" ''
daemon=600
cache=${stateDir}/ddclient.cache
pid=${ddclientPIDFile}
use=${config.services.ddclient.use}
login=${config.services.ddclient.username}
password=${config.services.ddclient.password}
protocol=${config.services.ddclient.protocol}
server=${config.services.ddclient.server}
ssl=${if config.services.ddclient.ssl then "yes" else "no"}
wildcard=YES
${config.services.ddclient.domain}
${config.services.ddclient.extraConfig}
'';
in
@ -122,10 +108,30 @@ in
home = stateDir;
};
environment.etc."ddclient.conf" = {
uid = config.ids.uids.ddclient;
mode = "0600";
text = ''
daemon=600
cache=${stateDir}/ddclient.cache
pid=${ddclientPIDFile}
use=${config.services.ddclient.use}
login=${config.services.ddclient.username}
password=${config.services.ddclient.password}
protocol=${config.services.ddclient.protocol}
server=${config.services.ddclient.server}
ssl=${if config.services.ddclient.ssl then "yes" else "no"}
wildcard=YES
${config.services.ddclient.domain}
${config.services.ddclient.extraConfig}
'';
};
systemd.services.ddclient = {
description = "Dynamic DNS Client";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."ddclient.conf".source ];
serviceConfig = {
# Uncomment this if too many problems occur:

View File

@ -13,7 +13,7 @@ let
ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"'';
dumps = lib.concatMapStringsSep " " lib.escapeShellArg cfg.loadDumps;
dumps = lib.escapeShellArgs cfg.loadDumps;
in {

View File

@ -231,11 +231,6 @@ in {
users.extraUsers = [{
name = "nm-openvpn";
uid = config.ids.uids.nm-openvpn;
}
{
# to enable link-local connections
name = "avahi-autoipd";
uid = config.ids.uids.avahi-autoipd;
}];
systemd.packages = cfg.packages;

View File

@ -0,0 +1,73 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.offlineimap;
in {
options.services.offlineimap = {
enable = mkEnableOption "Offlineimap, a software to dispose your mailbox(es) as a local Maildir(s).";
install = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether to install a user service for Offlineimap. Once
the service is started, emails will be fetched automatically.
The service must be manually started for each user with
"systemctl --user start offlineimap" or globally through
<varname>services.offlineimap.enable</varname>.
'';
};
package = mkOption {
type = types.package;
default = pkgs.offlineimap;
defaultText = "pkgs.offlineimap";
description = "Offlineimap derivation to use.";
};
path = mkOption {
type = types.listOf types.path;
default = [];
example = literalExample "[ pkgs.pass pkgs.bash pkgs.notmuch ]";
description = "List of derivations to put in Offlineimap's path.";
};
onCalendar = mkOption {
type = types.str;
default = "*:0/3"; # every 3 minutes
description = "How often is offlineimap started. Default is '*:0/3' meaning every 3 minutes. See systemd.time(7) for more information about the format.";
};
timeoutStartSec = mkOption {
type = types.str;
default = "120sec"; # Kill if still alive after 2 minutes
description = "How long waiting for offlineimap before killing it. Default is '120sec' meaning every 2 minutes. See systemd.time(7) for more information about the format.";
};
};
config = mkIf (cfg.enable || cfg.install) {
systemd.user.services.offlineimap = {
description = "Offlineimap: a software to dispose your mailbox(es) as a local Maildir(s)";
serviceConfig = {
Type = "oneshot";
ExecStart = "${cfg.package}/bin/offlineimap -u basic -o -1";
TimeoutStartSec = cfg.timeoutStartSec;
};
path = cfg.path;
};
environment.systemPackages = [ "${cfg.package}" ];
systemd.user.timers.offlineimap = {
description = "offlineimap timer";
timerConfig = {
Unit = "offlineimap.service";
OnCalendar = cfg.onCalendar;
# start immediately after computer is started:
Persistent = "true";
};
} // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
};
}

View File

@ -0,0 +1,124 @@
{ config, stdenv, pkgs, lib, ... }:
with lib;
{
options = {
services.pptpd = {
enable = mkEnableOption "Whether pptpd should be run on startup.";
serverIp = mkOption {
type = types.string;
description = "The server-side IP address.";
default = "10.124.124.1";
};
clientIpRange = mkOption {
type = types.string;
description = "The range from which client IPs are drawn.";
default = "10.124.124.2-11";
};
maxClients = mkOption {
type = types.int;
description = "The maximum number of simultaneous connections.";
default = 10;
};
extraPptpdOptions = mkOption {
type = types.lines;
description = "Adds extra lines to the pptpd configuration file.";
default = "";
};
extraPppdOptions = mkOption {
type = types.lines;
description = "Adds extra lines to the pppd options file.";
default = "";
example = ''
ms-dns 8.8.8.8
ms-dns 8.8.4.4
'';
};
};
};
config = mkIf config.services.pptpd.enable {
systemd.services.pptpd = let
cfg = config.services.pptpd;
pptpd-conf = pkgs.writeText "pptpd.conf" ''
# Inspired from pptpd-1.4.0/samples/pptpd.conf
ppp ${ppp-pptpd-wrapped}/bin/pppd
option ${pppd-options}
pidfile /run/pptpd.pid
localip ${cfg.serverIp}
remoteip ${cfg.clientIpRange}
connections ${toString cfg.maxClients} # (Will get harmless warning if inconsistent with IP range)
# Extra
${cfg.extraPptpdOptions}
'';
pppd-options = pkgs.writeText "ppp-options-pptpd.conf" ''
# From: cat pptpd-1.4.0/samples/options.pptpd | grep -v ^# | grep -v ^$
name pptpd
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
require-mppe-128
proxyarp
lock
nobsdcomp
novj
novjccomp
nologfd
# Extra:
${cfg.extraPppdOptions}
'';
ppp-pptpd-wrapped = pkgs.stdenv.mkDerivation {
name = "ppp-pptpd-wrapped";
phases = [ "installPhase" ];
buildInputs = with pkgs; [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
makeWrapper ${pkgs.ppp}/bin/pppd $out/bin/pppd \
--set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/etc/ppp=/etc/ppp-pptpd"
'';
};
in {
description = "pptpd server";
requires = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
mkdir -p -m 700 /etc/ppp-pptpd
secrets="/etc/ppp-pptpd/chap-secrets"
[ -f "$secrets" ] || cat > "$secrets" << EOF
# From: pptpd-1.4.0/samples/chap-secrets
# Secrets for authentication using CHAP
# client server secret IP addresses
#username pptpd password *
EOF
chown root.root "$secrets"
chmod 600 "$secrets"
'';
serviceConfig = {
ExecStart = "${pkgs.pptpd}/bin/pptpd --conf ${pptpd-conf}";
KillMode = "process";
Restart = "on-success";
Type = "forking";
PIDFile = "/run/pptpd.pid";
};
};
};
}

View File

@ -52,6 +52,8 @@ in
config = mkIf config.services.shairport-sync.enable {
services.avahi.enable = true;
services.avahi.publish.enable = true;
services.avahi.publish.userServices = true;
users.extraUsers = singleton
{ name = cfg.user;

View File

@ -83,7 +83,7 @@ in {
SKYDNS_NAMESERVERS = concatStringsSep "," cfg.nameservers;
};
serviceConfig = {
ExecStart = "${cfg.package}/bin/skydns";
ExecStart = "${cfg.package.bin}/bin/skydns";
};
};

View File

@ -129,7 +129,7 @@ in {
in {
description = "WPA Supplicant";
after = [ "network-interfaces.target" ];
after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces;
requires = lib.concatMap deviceUnit ifaces;
wantedBy = [ "network.target" ];

View File

@ -0,0 +1,143 @@
{ config, stdenv, pkgs, lib, ... }:
with lib;
{
options = {
services.xl2tpd = {
enable = mkEnableOption "Whether xl2tpd should be run on startup.";
serverIp = mkOption {
type = types.string;
description = "The server-side IP address.";
default = "10.125.125.1";
};
clientIpRange = mkOption {
type = types.string;
description = "The range from which client IPs are drawn.";
default = "10.125.125.2-11";
};
extraXl2tpOptions = mkOption {
type = types.lines;
description = "Adds extra lines to the xl2tpd configuration file.";
default = "";
};
extraPppdOptions = mkOption {
type = types.lines;
description = "Adds extra lines to the pppd options file.";
default = "";
example = ''
ms-dns 8.8.8.8
ms-dns 8.8.4.4
'';
};
};
};
config = mkIf config.services.xl2tpd.enable {
systemd.services.xl2tpd = let
cfg = config.services.xl2tpd;
# Config files from https://help.ubuntu.com/community/L2TPServer
xl2tpd-conf = pkgs.writeText "xl2tpd.conf" ''
[global]
ipsec saref = no
[lns default]
local ip = ${cfg.serverIp}
ip range = ${cfg.clientIpRange}
pppoptfile = ${pppd-options}
length bit = yes
; Extra
${cfg.extraXl2tpOptions}
'';
pppd-options = pkgs.writeText "ppp-options-xl2tpd.conf" ''
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
# require-mppe-128
asyncmap 0
auth
crtscts
idle 1800
mtu 1200
mru 1200
lock
hide-password
local
# debug
name xl2tpd
# proxyarp
lcp-echo-interval 30
lcp-echo-failure 4
# Extra:
${cfg.extraPppdOptions}
'';
xl2tpd-ppp-wrapped = pkgs.stdenv.mkDerivation {
name = "xl2tpd-ppp-wrapped";
phases = [ "installPhase" ];
buildInputs = with pkgs; [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
makeWrapper ${pkgs.ppp}/sbin/pppd $out/bin/pppd \
--set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "/etc/ppp=/etc/xl2tpd/ppp"
makeWrapper ${pkgs.xl2tpd}/bin/xl2tpd $out/bin/xl2tpd \
--set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \
--set NIX_REDIRECTS "${pkgs.ppp}/sbin/pppd=$out/bin/pppd"
'';
};
in {
description = "xl2tpd server";
requires = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
mkdir -p -m 700 /etc/xl2tpd
pushd /etc/xl2tpd > /dev/null
mkdir -p -m 700 ppp
[ -f ppp/chap-secrets ] || cat > ppp/chap-secrets << EOF
# Secrets for authentication using CHAP
# client server secret IP addresses
#username xl2tpd password *
EOF
chown root.root ppp/chap-secrets
chmod 600 ppp/chap-secrets
# The documentation says this file should be present but doesn't explain why and things work even if not there:
[ -f l2tp-secrets ] || (echo -n "* * "; ${pkgs.apg}/bin/apg -n 1 -m 32 -x 32 -a 1 -M LCN) > l2tp-secrets
chown root.root l2tp-secrets
chmod 600 l2tp-secrets
popd > /dev/null
mkdir -p /run/xl2tpd
chown root.root /run/xl2tpd
chmod 700 /run/xl2tpd
'';
serviceConfig = {
ExecStart = "${xl2tpd-ppp-wrapped}/bin/xl2tpd -D -c ${xl2tpd-conf} -s /etc/xl2tpd/l2tp-secrets -p /run/xl2tpd/pid -C /run/xl2tpd/control";
KillMode = "process";
Restart = "on-success";
Type = "simple";
PIDFile = "/run/xl2tpd/pid";
};
};
};
}

View File

@ -157,11 +157,14 @@ in {
environment.systemPackages = [ cfg.package ];
users.extraUsers = singleton {
name = "elasticsearch";
uid = config.ids.uids.elasticsearch;
description = "Elasticsearch daemon user";
home = cfg.dataDir;
users = {
groups.elasticsearch.gid = config.ids.gids.elasticsearch;
users.elasticsearch = {
uid = config.ids.uids.elasticsearch;
description = "Elasticsearch daemon user";
home = cfg.dataDir;
group = "elasticsearch";
};
};
};
}

View File

@ -95,7 +95,7 @@ in {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.hologram}/bin/hologram-server --debug --conf ${cfgFile}";
ExecStart = "${pkgs.hologram.bin}/bin/hologram-server --debug --conf ${cfgFile}";
};
};
};

View File

@ -515,7 +515,7 @@ in
serviceConfig = {
User = "oauth2_proxy";
Restart = "always";
ExecStart = "${cfg.package}/bin/oauth2_proxy ${mkCommandLine cfg}";
ExecStart = "${cfg.package.bin}/bin/oauth2_proxy ${mkCommandLine cfg}";
};
};

View File

@ -65,10 +65,13 @@ in
default = [ ];
description = ''
Packages whose D-Bus configuration files should be included in
the configuration of the D-Bus system-wide message bus.
Specifically, every file in
the configuration of the D-Bus system-wide or session-wide
message bus. Specifically, files in the following directories
will be included into their respective DBus configuration paths:
<filename><replaceable>pkg</replaceable>/etc/dbus-1/system.d</filename>
is included.
<filename><replaceable>pkg</replaceable>/share/dbus-1/system-services</filename>
<filename><replaceable>pkg</replaceable>/etc/dbus-1/session.d</filename>
<filename><replaceable>pkg</replaceable>/share/dbus-1/services</filename>
'';
};

View File

@ -12,7 +12,9 @@ let
httpdConf = mainCfg.configFile;
php = pkgs.php.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ };
php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ };
phpMajorVersion = head (splitString "." php.version);
getPort = cfg: if cfg.port != 0 then cfg.port else if cfg.enableSSL then 443 else 80;
@ -337,7 +339,8 @@ let
allModules =
concatMap (svc: svc.extraModulesPre) allSubservices
++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules
++ optional enablePHP { name = "php5"; path = "${php}/modules/libphp5.so"; }
++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; }
++ optional enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; }
++ concatMap (svc: svc.extraModules) allSubservices
++ extraForeignModules;
in concatMapStrings load allModules
@ -541,12 +544,27 @@ in
'';
};
enableMellon = mkOption {
type = types.bool;
default = false;
description = "Whether to enable the mod_auth_mellon module.";
};
enablePHP = mkOption {
type = types.bool;
default = false;
description = "Whether to enable the PHP module.";
};
phpPackage = mkOption {
type = types.package;
default = pkgs.php;
defaultText = "pkgs.php";
description = ''
Overridable attribute of the PHP package to use.
'';
};
phpOptions = mkOption {
type = types.lines;
default = "";
@ -650,6 +668,7 @@ in
environment =
optionalAttrs enablePHP { PHPRC = phpIni; }
// optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; }
// (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices));
preStart =

View File

@ -33,7 +33,7 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.caddy}/bin/caddy -conf=${configFile} -email=${cfg.email}";
ExecStart = "${pkgs.caddy.bin}/bin/caddy -conf=${configFile} -email=${cfg.email}";
Type = "simple";
User = "caddy";
Group = "caddy";

View File

@ -0,0 +1,262 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.lighttpd.inginious;
inginious = pkgs.inginious;
execName = "inginious-${if cfg.useLTI then "lti" else "webapp"}";
inginiousConfigFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "inginious.yaml" ''
# Backend; can be:
# - "local" (run containers on the same machine)
# - "remote" (connect to distant docker daemon and auto start agents) (choose this if you use boot2docker)
# - "remote_manual" (connect to distant and manually installed agents)
backend: "${cfg.backendType}"
## TODO (maybe): Add an option for the "remote" backend in this NixOS module.
# List of remote docker daemon to which the backend will try
# to connect (backend: remote only)
#docker_daemons:
# - # Host of the docker daemon *from the webapp*
# remote_host: "some.remote.server"
# # Port of the distant docker daemon *from the webapp*
# remote_docker_port: "2375"
# # A mandatory port used by the backend and the agent that will be automatically started.
# # Needs to be available on the remote host, and to be open in the firewall.
# remote_agent_port: "63456"
# # Does the remote docker requires tls? Defaults to false.
# # Parameter can be set to true or path to the certificates
# #use_tls: false
# # Link to the docker daemon *from the host that runs the docker daemon*. Defaults to:
# #local_location: "unix:///var/run/docker.sock"
# # Path to the cgroups "mount" *from the host that runs the docker daemon*. Defaults to:
# #cgroups_location: "/sys/fs/cgroup"
# # Name that will be used to reference the agent
# #"agent_name": "inginious-agent"
# List of remote agents to which the backend will try
# to connect (backend: remote_manual only)
# Example:
#agents:
# - host: "192.168.59.103"
# port: 5001
agents:
${lib.concatMapStrings (agent:
" - host: \"${agent.host}\"\n" +
" port: ${agent.port}\n"
) cfg.remoteAgents}
# Location of the task directory
tasks_directory: "${cfg.tasksDirectory}"
# Super admins: list of user names that can do everything in the backend
superadmins:
${lib.concatMapStrings (x: " - \"${x}\"\n") cfg.superadmins}
# Aliases for containers
# Only containers listed here can be used by tasks
containers:
${lib.concatStrings (lib.mapAttrsToList (name: fullname:
" ${name}: \"${fullname}\"\n"
) cfg.containers)}
# Use single minified javascript file (production) or multiple files (dev) ?
use_minified_js: true
## TODO (maybe): Add NixOS options for these parameters.
# MongoDB options
#mongo_opt:
# host: localhost
# database: INGInious
# Disable INGInious?
#maintenance: false
#smtp:
# sendername: 'INGInious <no-reply@inginious.org>'
# host: 'smtp.gmail.com'
# port: 587
# username: 'configme@gmail.com'
# password: 'secret'
# starttls: True
## NixOS extra config
${cfg.extraConfig}
'';
in
{
options.services.lighttpd.inginious = {
enable = mkEnableOption "INGInious, an automated code testing and grading system.";
configFile = mkOption {
type = types.nullOr types.path;
default = null;
example = literalExample ''pkgs.writeText "configuration.yaml" "# custom config options ...";'';
description = ''The path to an INGInious configuration file.'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
# Load the dummy auth plugin.
plugins:
- plugin_module: inginious.frontend.webapp.plugins.auth.demo_auth
users:
# register the user "test" with the password "someverycomplexpassword"
test: someverycomplexpassword
'';
description = ''Extra option in YaML format, to be appended to the config file.'';
};
tasksDirectory = mkOption {
type = types.path;
default = "${inginious}/lib/python2.7/site-packages/inginious/tasks";
example = "/var/lib/INGInious/tasks";
description = ''
Path to the tasks folder.
Defaults to the provided test tasks folder (readonly).
'';
};
useLTI = mkOption {
type = types.bool;
default = false;
description = ''Whether to start the LTI frontend in place of the webapp.'';
};
superadmins = mkOption {
type = types.uniq (types.listOf types.str);
default = [ "admin" ];
example = [ "john" "pepe" "emilia" ];
description = ''List of user logins allowed to administrate the whole server.'';
};
containers = mkOption {
type = types.attrsOf types.str;
default = {
default = "ingi/inginious-c-default";
};
example = {
default = "ingi/inginious-c-default";
sekexe = "ingi/inginious-c-sekexe";
java = "ingi/inginious-c-java";
oz = "ingi/inginious-c-oz";
pythia1compat = "ingi/inginious-c-pythia1compat";
};
description = ''
An attrset describing the required containers
These containers will be available in INGInious using their short name (key)
and will be automatically downloaded before INGInious starts.
'';
};
hostPattern = mkOption {
type = types.str;
default = "^inginious.";
example = "^inginious.mydomain.xyz$";
description = ''
The domain that serves INGInious.
INGInious uses absolute paths which makes it difficult to relocate in its own subdir.
The default configuration will serve INGInious when the server is accessed with a hostname starting with "inginious.".
If left blank, INGInious will take the precedence over all the other lighttpd sites, which is probably not what you want.
'';
};
backendType = mkOption {
type = types.enum [ "local" "remote_manual" ]; # TODO: support backend "remote"
default = "local";
description = ''
Select how INGINious accesses to grading containers.
The default "local" option ensures that Docker is started and provisioned.
Fore more information, see http://inginious.readthedocs.io/en/latest/install_doc/config_reference.html
Not all backends are supported. Use services.inginious.configFile for full flexibility.
'';
};
remoteAgents = mkOption {
type = types.listOf (types.attrsOf types.str);
default = [];
example = [ { host = "192.0.2.25"; port = "1345"; } ];
description = ''A list of remote agents, used only when services.inginious.backendType is "remote_manual".'';
};
};
config = mkIf cfg.enable (
mkMerge [
# For a local install, we need docker.
(mkIf (cfg.backendType == "local") {
virtualisation.docker = {
enable = true;
# We need docker to listen on port 2375.
extraOptions = "-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock";
storageDriver = mkDefault "overlay";
socketActivation = false;
};
users.extraUsers."lighttpd".extraGroups = [ "docker" ];
# Ensure that docker has pulled the required images.
systemd.services.inginious-prefetch = {
script = let
images = lib.unique (
[ "centos" "ingi/inginious-agent" ]
++ lib.mapAttrsToList (_: image: image) cfg.containers
);
in lib.concatMapStrings (image: ''
${pkgs.docker}/bin/docker pull ${image}
'') images;
serviceConfig.Type = "oneshot";
wants = [ "docker.service" ];
after = [ "docker.service" ];
wantedBy = [ "lighttpd.service" ];
before = [ "lighttpd.service" ];
};
})
# Common
{
# To access inginous tools (like inginious-test-task)
environment.systemPackages = [ inginious ];
services.mongodb.enable = true;
services.lighttpd.enable = true;
services.lighttpd.enableModules = [ "mod_access" "mod_alias" "mod_fastcgi" "mod_redirect" "mod_rewrite" ];
services.lighttpd.extraConfig = ''
$HTTP["host"] =~ "${cfg.hostPattern}" {
fastcgi.server = ( "/${execName}" =>
((
"socket" => "/run/lighttpd/inginious-fastcgi.socket",
"bin-path" => "${inginious}/bin/${execName} --config=${inginiousConfigFile}",
"max-procs" => 1,
"bin-environment" => ( "REAL_SCRIPT_NAME" => "" ),
"check-local" => "disable"
))
)
url.rewrite-once = (
"^/.well-known/.*" => "$0",
"^/static/.*" => "$0",
"^/.*$" => "/${execName}$0",
"^/favicon.ico$" => "/static/common/favicon.ico",
)
alias.url += (
"/static/webapp/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/webapp/static/",
"/static/common/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/common/static/"
)
}
'';
systemd.services.lighttpd.preStart = ''
mkdir -p /run/lighttpd
chown lighttpd.lighttpd /run/lighttpd
'';
systemd.services.lighttpd.wants = [ "mongodb.service" "docker.service" ];
systemd.services.lighttpd.after = [ "mongodb.service" "docker.service" ];
}
]);
}

View File

@ -78,6 +78,8 @@ in {
type = types.listOf types.path;
description = "List of packages for which gsettings are overridden.";
};
debug = mkEnableOption "gnome-session debug messages";
};
environment.gnome3.packageSet = mkOption {
@ -117,7 +119,10 @@ in {
services.telepathy.enable = mkDefault true;
networking.networkmanager.enable = mkDefault true;
services.upower.enable = config.powerManagement.enable;
services.dbus.packages = mkIf config.services.printing.enable [ pkgs.system-config-printer ];
services.colord.enable = mkDefault true;
hardware.bluetooth.enable = mkDefault true;
services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
@ -159,7 +164,7 @@ in {
# Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
${gnome3.gnome_session}/bin/gnome-session&
${gnome3.gnome_session}/bin/gnome-session ${optionalString cfg.debug "--debug"} &
waitPID=$!
'';
};

View File

@ -33,6 +33,14 @@ in
default = false;
description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon).";
};
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before XFCE is started.
'';
};
};
};
@ -45,6 +53,8 @@ in
bgSupport = true;
start =
''
${cfg.extraSessionCommands}
# Set GTK_PATH so that GTK+ can find the theme engines.
export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"

View File

@ -3,37 +3,52 @@
with lib;
let
cfg = config.services.xserver.windowManager.i3;
wmCfg = config.services.xserver.windowManager;
i3option = name: {
enable = mkEnableOption name;
configFile = mkOption {
default = null;
type = types.nullOr types.path;
description = ''
Path to the i3 configuration file.
If left at the default value, $HOME/.i3/config will be used.
'';
};
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before i3 is started.
'';
};
};
i3config = name: pkg: cfg: {
services.xserver.windowManager.session = [{
inherit name;
start = ''
${cfg.extraSessionCommands}
${pkg}/bin/i3 ${optionalString (cfg.configFile != null)
"-c \"${cfg.configFile}\""
} &
waitPID=$!
'';
}];
environment.systemPackages = [ pkg ];
};
in
{
options = {
services.xserver.windowManager.i3 = {
enable = mkEnableOption "i3";
configFile = mkOption {
default = null;
type = types.nullOr types.path;
description = ''
Path to the i3 configuration file.
If left at the default value, $HOME/.i3/config will be used.
'';
};
};
options.services.xserver.windowManager = {
i3 = i3option "i3";
i3-gaps = i3option "i3-gaps";
};
config = mkIf cfg.enable {
services.xserver.windowManager = {
session = [{
name = "i3";
start = ''
${pkgs.i3}/bin/i3 ${optionalString (cfg.configFile != null)
"-c \"${cfg.configFile}\""
} &
waitPID=$!
'';
}];
};
environment.systemPackages = with pkgs; [ i3 ];
};
config = mkMerge [
(mkIf wmCfg.i3.enable (i3config "i3" pkgs.i3 wmCfg.i3))
(mkIf wmCfg.i3-gaps.enable (i3config "i3-gaps" pkgs.i3-gaps wmCfg.i3-gaps))
];
}

View File

@ -0,0 +1,30 @@
{ config, lib, pkgs, ... }:
with lib;
let cfg = config.services.xbanish;
in {
options.services.xbanish = {
enable = mkEnableOption "xbanish";
arguments = mkOption {
description = "Arguments to pass to xbanish command";
default = "";
example = "-d -i shift";
type = types.str;
};
};
config = mkIf cfg.enable {
systemd.user.services.xbanish = {
description = "xbanish hides the mouse pointer";
wantedBy = [ "default.target" ];
serviceConfig.ExecStart = ''
${pkgs.xbanish}/bin/xbanish ${cfg.arguments}
'';
serviceConfig.Restart = "always";
};
};
}

View File

@ -261,7 +261,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
sub pathToUnitName {
my ($path) = @_;
open my $cmd, "-|", "systemd-escape", "--suffix=mount", "-p", $path
open my $cmd, "-|", "@systemd@/bin/systemd-escape", "--suffix=mount", "-p", $path
or die "Unable to escape $path!\n";
my $escaped = join "", <$cmd>;
chomp $escaped;

View File

@ -36,6 +36,8 @@ with lib;
config = mkMerge [
(mkIf config.systemd.coredump.enable {
systemd.additionalUpstreamSystemUnits = [ "systemd-coredump.socket" "systemd-coredump@.service" ];
environment.etc."systemd/coredump.conf".text =
''
[Coredump]
@ -45,7 +47,7 @@ with lib;
# Have the kernel pass core dumps to systemd's coredump helper binary.
# From systemd's 50-coredump.conf file. See:
# <https://github.com/systemd/systemd/blob/v218/sysctl.d/50-coredump.conf.in>
boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %p %u %g %s %t %e";
boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %P %u %g %s %t %c %e";
})
(mkIf (!config.systemd.coredump.enable) {

View File

@ -100,9 +100,6 @@ in
'';
boot.initrd.network.postCommands = ''
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo '${cfg.shell}' > /etc/shells
echo 'root:x:0:0:root:/root:${cfg.shell}' > /etc/passwd
echo 'passwd: files' > /etc/nsswitch.conf

View File

@ -5,5 +5,4 @@ pkgs.substituteAll {
isExecutable = true;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
inherit (pkgs) bash;
kernelDTB = pkgs.stdenv.platform.kernelDTB or false;
}

View File

@ -75,9 +75,10 @@ addEntry() {
copyToKernelsDir "$path/kernel"; kernel=$result
copyToKernelsDir "$path/initrd"; initrd=$result
if [ -n "@kernelDTB@" ]; then
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
dtbDir=$(readlink -m "$path/kernel/../dtbs")
if [ -d "$dtbDir" ]; then
copyToKernelsDir "$dtbDir"; dtbs=$result
fi
timestampEpoch=$(stat -L -c '%Z' $path)
@ -95,7 +96,7 @@ addEntry() {
fi
echo " LINUX ../nixos/$(basename $kernel)"
echo " INITRD ../nixos/$(basename $initrd)"
if [ -n "@kernelDTB@" ]; then
if [ -d "$dtbDir" ]; then
echo " FDTDIR ../nixos/$(basename $dtbs)"
fi
echo " APPEND systemConfig=$path init=$path/init $extraParams"

View File

@ -501,7 +501,7 @@ sub getEfiTarget {
my @deviceTargets = getDeviceTargets();
my $efiTarget = getEfiTarget();
my $prevGrubState = readGrubState();
my @prevDeviceTargets = split/:/, $prevGrubState->devices;
my @prevDeviceTargets = split/,/, $prevGrubState->devices;
my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference());
my $nameDiffer = get("fullName") ne $prevGrubState->name;
@ -549,7 +549,7 @@ if ($requireNewInstall != 0) {
print FILE get("fullName"), "\n" or die;
print FILE get("fullVersion"), "\n" or die;
print FILE $efiTarget, "\n" or die;
print FILE join( ":", @deviceTargets ), "\n" or die;
print FILE join( ",", @deviceTargets ), "\n" or die;
print FILE $efiSysMountPoint, "\n" or die;
close FILE or die;
}

View File

@ -36,7 +36,7 @@ let
${optionalString (header != null) "--header=${header}"} \
${optionalString (keyFile != null) "--key-file=${keyFile} ${optionalString (keyFileSize != null) "--keyfile-size=${toString keyFileSize}"}"} \
> /.luksopen_args
cryptsetup-askpass
get_password "Enter LUKS Passphrase" cryptsetup-askpass
rm /.luksopen_args
}
@ -78,9 +78,7 @@ let
for try in $(seq 3); do
${optionalString yubikey.twoFactor ''
echo -n "Enter two-factor passphrase: "
read -s k_user
echo
k_user="$(get_password "Enter two-factor passphrase" cat)"
''}
if [ ! -z "$k_user" ]; then
@ -463,6 +461,26 @@ in
''}
'';
boot.initrd.preDeviceCommands = ''
get_password() {
local ret
local reply
local tty_stat
tty_stat="$(stty -g)"
stty -echo
for i in `seq 1 3`; do
echo -n "$1: "
read reply
echo "$reply" | "$2"
if [ "$?" = "0" ]; then
break
fi
done
stty "$tty_stat"
}
'';
boot.initrd.preLVMCommands = concatStrings (mapAttrsToList openCommand preLVM);
boot.initrd.postDeviceCommands = concatStrings (mapAttrsToList openCommand postLVM);

View File

@ -0,0 +1,129 @@
{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs) plymouth;
cfg = config.boot.plymouth;
themesEnv = pkgs.buildEnv {
name = "plymouth-themes";
paths = [ plymouth ] ++ cfg.themePackages;
};
configFile = pkgs.writeText "plymouthd.conf" ''
[Daemon]
ShowDelay=0
Theme=${cfg.theme}
'';
in
{
options = {
boot.plymouth = {
enable = mkEnableOption "Plymouth boot splash screen";
themePackages = mkOption {
default = [];
type = types.listOf types.package;
description = ''
Extra theme packages for plymouth.
'';
};
theme = mkOption {
default = "fade-in";
type = types.str;
description = ''
Splash screen theme.
'';
};
logo = mkOption {
type = types.path;
default = pkgs.fetchurl {
url = "https://nixos.org/logo/nixos-hires.png";
sha256 = "1ivzgd7iz0i06y36p8m5w48fd8pjqwxhdaavc0pxs7w1g7mcy5si";
};
description = ''
Logo which is displayed on the splash screen.
'';
};
};
};
config = mkIf cfg.enable {
boot.kernelParams = [ "splash" ];
# To be discoverable by systemd.
environment.systemPackages = [ plymouth ];
environment.etc."plymouth/plymouthd.conf".source = configFile;
environment.etc."plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouth.defaults";
environment.etc."plymouth/logo.png".source = cfg.logo;
environment.etc."plymouth/themes".source = "${themesEnv}/share/plymouth/themes";
# XXX: Needed because we supply a different set of plugins in initrd.
environment.etc."plymouth/plugins".source = "${plymouth}/lib/plymouth";
systemd.packages = [ plymouth ];
systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ];
systemd.services.plymouth-halt.wantedBy = [ "halt.target" ];
systemd.services.plymouth-quit = {
wantedBy = [ "multi-user.target" ];
after = [ "display-manager.service" "multi-user.target" ];
};
systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ];
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${pkgs.plymouth}/bin/plymouthd
copy_bin_and_libs ${pkgs.plymouth}/bin/plymouth
moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)"
mkdir -p $out/lib/plymouth/renderers
cp ${plymouth}/lib/plymouth/{text,details,$moduleName}.so $out/lib/plymouth
cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/lib/plymouth/renderers
mkdir -p $out/share/plymouth/themes
cp ${plymouth}/share/plymouth/plymouthd.defaults $out/share/plymouth
cp -r ${themesEnv}/share/plymouth/themes/{text,details,${cfg.theme}} $out/share/plymouth/themes
cp ${cfg.logo} $out/share/plymouth/logo.png
'';
boot.initrd.extraUtilsCommandsTest = ''
$out/bin/plymouthd --help >/dev/null
$out/bin/plymouth --help >/dev/null
'';
boot.initrd.extraUdevRulesCommands = ''
cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out
sed -i '/loginctl/d' $out/71-seat.rules
'';
boot.initrd.preLVMCommands = mkAfter ''
mkdir -p /etc/plymouth
ln -s ${configFile} /etc/plymouth/plymouthd.conf
ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults
ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png
ln -s $extraUtils/share/plymouth/themes /etc/plymouth/themes
ln -s $extraUtils/lib/plymouth /etc/plymouth/plugins
plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session
plymouth --show-splash
'';
};
}

View File

@ -1,7 +1,9 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.resolved;
in
{
options = {
@ -14,9 +16,60 @@ with lib;
'';
};
services.resolved.fallbackDns = mkOption {
default = [ ];
example = [ "8.8.8.8" "2001:4860:4860::8844" ];
type = types.listOf types.str;
description = ''
A list of IPv4 and IPv6 addresses to use as the fallback DNS servers.
If this option is empty, a compiled-in list of DNS servers is used instead.
'';
};
services.resolved.domains = mkOption {
default = config.networking.search;
example = [ "example.com" ];
type = types.listOf types.str;
description = ''
A list of domains. These domains are used as search suffixes when resolving single-label host names (domain names which contain no dot), in order to qualify them into fully-qualified domain names (FQDNs).
For compatibility reasons, if this setting is not specified, the search domains listed in /etc/resolv.conf are used instead, if that file exists and any domains are configured in it.
'';
};
services.resolved.llmnr = mkOption {
default = "true";
example = "false";
type = types.enum [ "true" "resolve" "false" ];
description = ''
Controls Link-Local Multicast Name Resolution support (RFC 4794) on the local host.
If true, enables full LLMNR responder and resolver support.
If false, disables both.
If set to "resolve", only resolution support is enabled, but responding is disabled.
'';
};
services.resolved.dnssec = mkOption {
default = "allow-downgrade";
example = "true";
type = types.enum [ "true" "allow-downgrade" "false" ];
description = ''
If true all DNS lookups are DNSSEC-validated locally (excluding LLMNR and Multicast DNS). Note that this mode requires a DNS server that supports DNSSEC. If the DNS server does not properly support DNSSEC all validations will fail.
If set to "allow-downgrade" DNSSEC validation is attempted, but if the server does not support DNSSEC properly, DNSSEC mode is automatically disabled. Note that this mode makes DNSSEC validation vulnerable to "downgrade" attacks, where an attacker might be able to trigger a downgrade to non-DNSSEC mode by synthesizing a DNS response that suggests DNSSEC was not supported.
If set to false, DNS lookups are not DNSSEC validated.
'';
};
services.resolved.extraConfig = mkOption {
default = "";
type = types.lines;
description = ''
Extra config to append to resolved.conf.
'';
};
};
config = mkIf config.services.resolved.enable {
config = mkIf cfg.enable {
systemd.additionalUpstreamSystemUnits = [ "systemd-resolved.service" ];
@ -27,7 +80,15 @@ with lib;
environment.etc."systemd/resolved.conf".text = ''
[Resolve]
DNS=${concatStringsSep " " config.networking.nameservers}
${optionalString (config.networking.nameservers != [])
"DNS=${concatStringsSep " " config.networking.nameservers}"}
${optionalString (cfg.fallbackDns != [])
"FallbackDNS=${concatStringsSep " " cfg.fallbackDns}"}
${optionalString (cfg.domains != [])
"Domains=${concatStringsSep " " cfg.domains}"}
LLMNR=${cfg.llmnr}
DNSSEC=${cfg.dnssec}
${config.services.resolved.extraConfig}
'';
};

Some files were not shown because too many files have changed in this diff Show More