Merge branch 'master' into improved-make-overridable

This commit is contained in:
Will Fancher 2017-08-26 11:39:13 -04:00
commit 4d860389d8
3457 changed files with 64462 additions and 45322 deletions

23
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,23 @@
# CODEOWNERS file
#
# This file is used to describe who owns what in this repository. This file does not
# replace `meta.maintainers` but is instead used for other things than derivations
# and modules, like documentation, package sets, and other assets.
#
# For documentation on this file, see https://help.github.com/articles/about-codeowners/
# Mentioned users will get code review requests.
# Python-related code and docs
pkgs/top-level/python-packages.nix @FRidh
pkgs/development/interpreters/python/* @FRidh
pkgs/development/python-modules/* @FRidh
doc/languages-frameworks/python.md @FRidh
# Boostraping and core infra
pkgs/stdenv/ @Ericson2314
pkgs/build-support/cc-wrapper/ @Ericson2314
# Darwin-related
pkgs/stdenv/darwin/* @copumpkin @LnL7
pkgs/os-specific/darwin/* @LnL7
pkgs/os-specific/darwin/apple-source-releases/* @copumpkin

View File

@ -15,7 +15,7 @@ under the terms of [COPYING](../COPYING), which is an MIT-like license.
* Format the commits in the following way:
```
(pkg-name | service-name): (from -> to | init at version | refactor | etc)
(pkg-name | nixos/<module>): (from -> to | init at version | refactor | etc)
(Motivation for change. Additional information.)
```
@ -24,10 +24,10 @@ under the terms of [COPYING](../COPYING), which is an MIT-like license.
* nginx: init at 2.0.1
* firefox: 3.0 -> 3.1.1
* hydra service: add bazBaz option
* nixos/hydra: add bazBaz option
Dual baz behavior is needed to do foo.
* nginx service: refactor config generation
* nixos/nginx: refactor config generation
The old config generation system used impure shell scripts and could break in specific circumstances (see #1234).

View File

@ -3,6 +3,8 @@
###### Things done
<!-- Please check what applies. Note that these are not hard requirements but merely serve as information for reviewers. -->
- [ ] 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)

View File

@ -1,14 +0,0 @@
{
"userBlacklist": [
"civodul",
"jhasse",
"shlevy",
"bbenoist"
],
"alwaysNotifyForPaths": [
{ "name": "FRidh", "files": ["pkgs/top-level/python-packages.nix", "pkgs/development/interpreters/python/*", "pkgs/development/python-modules/*" ] },
{ "name": "LnL7", "files": ["pkgs/stdenv/darwin/*", "pkgs/os-specific/darwin/*"] },
{ "name": "copumpkin", "files": ["pkgs/stdenv/darwin/*", "pkgs/os-specific/darwin/apple-source-releases/*"] }
],
"fileBlacklist": ["pkgs/top-level/all-packages.nix"]
}

View File

@ -12,15 +12,21 @@ matrix:
script:
- ./maintainers/scripts/travis-nox-review-pr.sh nixpkgs-verify nixpkgs-manual nixpkgs-tarball nixpkgs-unstable
- ./maintainers/scripts/travis-nox-review-pr.sh nixos-options nixos-manual
env:
- BUILD_TYPE="Test Nixpkgs evaluation & NixOS manual build"
- os: linux
sudo: required
dist: trusty
before_script:
- sudo mount -o remount,exec,size=2G,mode=755 /run/user
script: ./maintainers/scripts/travis-nox-review-pr.sh nox pr
env:
- BUILD_TYPE="Build affected packages (Linux)"
- os: osx
osx_image: xcode7.3
script: ./maintainers/scripts/travis-nox-review-pr.sh nox pr
env:
- BUILD_TYPE="Build affected packages (macOS)"
env:
global:
- GITHUB_TOKEN=5edaaf1017f691ed34e7f80878f8f5fbd071603f

View File

@ -38,5 +38,5 @@ For pull-requests, please rebase onto nixpkgs `master`.
Communication:
* [Mailing list](http://lists.science.uu.nl/mailman/listinfo/nix-dev)
* [Mailing list](https://groups.google.com/forum/#!forum/nix-devel)
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)

View File

@ -243,5 +243,218 @@ set of packages.
</section>
<section xml:id="sec-declarative-package-management">
<title>Declarative Package Management</title>
<section xml:id="sec-building-environment">
<title>Build an environment</title>
<para>
Using <literal>packageOverrides</literal>, it is possible to manage
packages declaratively. This means that we can list all of our desired
packages within a declarative Nix expression. For example, to have
<literal>aspell</literal>, <literal>bc</literal>,
<literal>ffmpeg</literal>, <literal>coreutils</literal>,
<literal>gdb</literal>, <literal>nixUnstable</literal>,
<literal>emscripten</literal>, <literal>jq</literal>,
<literal>nox</literal>, and <literal>silver-searcher</literal>, we could
use the following in <filename>~/.config/nixpkgs/config.nix</filename>:
</para>
<screen>
{
packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv {
name = "my-packages";
paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ];
};
};
}
</screen>
<para>
To install it into our environment, you can just run <literal>nix-env -iA
nixpkgs.myPackages</literal>. If you want to load the packages to be built
from a working copy of <literal>nixpkgs</literal> you just run
<literal>nix-env -f. -iA myPackages</literal>. To explore what's been
installed, just look through <filename>~/.nix-profile/</filename>. You can
see that a lot of stuff has been installed. Some of this stuff is useful
some of it isn't. Let's tell Nixpkgs to only link the stuff that we want:
</para>
<screen>
{
packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv {
name = "my-packages";
paths = [ aspell bc coreutils gdb ffmpeg nixUnstable emscripten jq nox silver-searcher ];
pathsToLink = [ "/share" "/bin" ];
};
};
}
</screen>
<para>
<literal>pathsToLink</literal> tells Nixpkgs to only link the paths listed
which gets rid of the extra stuff in the profile.
<filename>/bin</filename> and <filename>/share</filename> are good
defaults for a user environment, getting rid of the clutter. If you are
running on Nix on MacOS, you may want to add another path as well,
<filename>/Applications</filename>, that makes GUI apps available.
</para>
</section>
<section xml:id="sec-getting-documentation">
<title>Getting documentation</title>
<para>
After building that new environment, look through
<filename>~/.nix-profile</filename> to make sure everything is there that
we wanted. Discerning readers will note that some files are missing. Look
inside <filename>~/.nix-profile/share/man/man1/</filename> to verify this.
There are no man pages for any of the Nix tools! This is because some
packages like Nix have multiple outputs for things like documentation (see
section 4). Let's make Nix install those as well.
</para>
<screen>
{
packageOverrides = pkgs: with pkgs; {
myPackages = pkgs.buildEnv {
name = "my-packages";
paths = [ aspell bc coreutils ffmpeg nixUnstable emscripten jq nox silver-searcher ];
pathsToLink = [ "/share/man" "/share/doc" /bin" ];
extraOutputsToInstall = [ "man" "doc" ];
};
};
}
</screen>
<para>
This provides us with some useful documentation for using our packages.
However, if we actually want those manpages to be detected by man, we need
to set up our environment. This can also be managed within Nix
expressions.
</para>
<screen>
{
packageOverrides = pkgs: with pkgs; rec {
myProfile = writeText "my-profile" ''
export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
'';
myPackages = pkgs.buildEnv {
name = "my-packages";
paths = [
(runCommand "profile" {} ''
mkdir -p $out/etc/profile.d
cp ${myProfile} $out/etc/profile.d/my-profile.sh
'')
aspell
bc
coreutils
ffmpeg
man
nixUnstable
emscripten
jq
nox
silver-searcher
];
pathsToLink = [ "/share/man" "/share/doc" /bin" "/etc" ];
extraOutputsToInstall = [ "man" "doc" ];
};
};
}
</screen>
<para>
For this to work fully, you must also have this script sourced when you
are logged in. Try adding something like this to your
<filename>~/.profile</filename> file:
</para>
<screen>
#!/bin/sh
if [ -d $HOME/.nix-profile/etc/profile.d ]; then
for i in $HOME/.nix-profile/etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
fi
</screen>
<para>
Now just run <literal>source $HOME/.profile</literal> and you can starting
loading man pages from your environent.
</para>
</section>
<section xml:id="sec-gnu-info-setup">
<title>GNU info setup</title>
<para>
Configuring GNU info is a little bit trickier than man pages. To work
correctly, info needs a database to be generated. This can be done with
some small modifications to our environment scripts.
</para>
<screen>
{
packageOverrides = pkgs: with pkgs; rec {
myProfile = writeText "my-profile" ''
export PATH=$HOME/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/sbin:/bin:/usr/sbin:/usr/bin
export MANPATH=$HOME/.nix-profile/share/man:/nix/var/nix/profiles/default/share/man:/usr/share/man
export INFOPATH=$HOME/.nix-profile/share/info:/nix/var/nix/profiles/default/share/info:/usr/share/info
'';
myPackages = pkgs.buildEnv {
name = "my-packages";
paths = [
(runCommand "profile" {} ''
mkdir -p $out/etc/profile.d
cp ${myProfile} $out/etc/profile.d/my-profile.sh
'')
aspell
bc
coreutils
ffmpeg
man
nixUnstable
emscripten
jq
nox
silver-searcher
texinfoInteractive
];
pathsToLink = [ "/share/man" "/share/doc" "/share/info" "/bin" "/etc" ];
extraOutputsToInstall = [ "man" "doc" "info" ];
postBuild = ''
if [ -x $out/bin/install-info -a -w $out/share/info ]; then
shopt -s nullglob
for i in $out/share/info/*.info $out/share/info/*.info.gz; do
$out/bin/install-info $i $out/share/info/dir
done
fi
'';
};
};
}
</screen>
<para>
<literal>postBuild</literal> tells Nixpkgs to run a command after building
the environment. In this case, <literal>install-info</literal> adds the
installed info pages to <literal>dir</literal> which is GNU info's default
root node. Note that <literal>texinfoInteractive</literal> is added to the
environment to give the <literal>install-info</literal> command.
</para>
</section>
</section>
</chapter>

View File

@ -358,8 +358,8 @@
<para>
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
manipulating Docker images according to the
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#docker-image-specification-v100">
Docker Image Specification v1.0.0
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#docker-image-specification-v120">
Docker Image Specification v1.2.0
</link>. Docker itself is not used to perform any of the operations done by these
functions.
</para>
@ -493,8 +493,8 @@
<varname>config</varname> is used to specify the configuration of the
containers that will be started off the built image in Docker.
The available options are listed in the
<link xlink:href="https://github.com/docker/docker/blob/master/image/spec/v1.md#container-runconfig-field-descriptions">
Docker Image Specification v1.0.0
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0
</link>.
</para>
</callout>

View File

@ -698,33 +698,6 @@ rm /nix/var/nix/manifests/*
rm /nix/var/nix/channel-cache/*
```
### How to use the Haste Haskell-to-Javascript transpiler
Open a shell with `haste-compiler` and `haste-cabal-install` (you don't actually need
`node`, but it can be useful to test stuff):
```shell
nix-shell \
-p "haskellPackages.ghcWithPackages (self: with self; [haste-cabal-install haste-compiler])" \
-p nodejs
```
You may not need the following step but if `haste-boot` fails to compile all the
packages it needs, this might do the trick
```shell
haste-cabal update
```
`haste-boot` builds a set of core libraries so that they can be used from Javascript
transpiled programs:
```shell
haste-boot
```
Transpile and run a "Hello world" program:
```
$ echo 'module Main where main = putStrLn "Hello world"' > hello-world.hs
$ hastec --onexec hello-world.hs
$ node hello-world.js
Hello world
```
### Builds on Darwin fail with `math.h` not found
Users of GHC on Darwin have occasionally reported that builds fail, because the
@ -854,7 +827,7 @@ the work to be licensed" under the terms of the LGPL (including for free).
The LGPL licensing for GMP is a problem for the overall licensing of binary
programs compiled with GHC because most distributions (and builds) of GHC use
static libraries. (Dynamic libraries are currently distributed only for OS X.)
static libraries. (Dynamic libraries are currently distributed only for macOS.)
The LGPL licensing situation may be worse: even though
[The Glasgow Haskell Compiler License](https://www.haskell.org/ghc/license)
is essentially a "free software" license (BSD3), according to
@ -912,14 +885,14 @@ nix-build -A haskell.packages.integer-simple.ghc802.scientific
- The *Journey into the Haskell NG infrastructure* series of postings
describe the new Haskell infrastructure in great detail:
- [Part 1](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015591.html)
- [Part 1](https://nixos.org/nix-dev/2015-January/015591.html)
explains the differences between the old and the new code and gives
instructions how to migrate to the new setup.
- [Part 2](http://lists.science.uu.nl/pipermail/nix-dev/2015-January/015608.html)
- [Part 2](https://nixos.org/nix-dev/2015-January/015608.html)
looks in-depth at how to tweak and configure your setup by means of
overrides.
- [Part 3](http://lists.science.uu.nl/pipermail/nix-dev/2015-April/016912.html)
- [Part 3](https://nixos.org/nix-dev/2015-April/016912.html)
describes the infrastructure that keeps the Haskell package set in Nixpkgs
up-to-date.

View File

@ -2,115 +2,204 @@
## User Guide
Several versions of Python are available on Nix as well as a high amount of
packages. The default interpreter is CPython 2.7.
### Using Python
#### Overview
Several versions of the Python interpreter are available on Nix, as well as a
high amount of packages. The attribute `python` refers to the default
interpreter, which is currently CPython 2.7. It is also possible to refer to
specific versions, e.g. `python35` refers to CPython 3.5, and `pypy` refers to
the default PyPy interpreter.
Python is used a lot, and in different ways. This affects also how it is
packaged. In the case of Python on Nix, an important distinction is made between
whether the package is considered primarily an application, or whether it should
be used as a library, i.e., of primary interest are the modules in
`site-packages` that should be importable.
In the Nixpkgs tree Python applications can be found throughout, depending on
what they do, and are called from the main package set. Python libraries,
however, are in separate sets, with one set per interpreter version.
The interpreters have several common attributes. One of these attributes is
`pkgs`, which is a package set of Python libraries for this specific
interpreter. E.g., the `toolz` package corresponding to the default interpreter
is `python.pkgs.toolz`, and the CPython 3.5 version is `python35.pkgs.toolz`.
The main package set contains aliases to these package sets, e.g.
`pythonPackages` refers to `python.pkgs` and `python35Packages` to
`python35.pkgs`.
#### Installing Python and packages
It is important to make a distinction between Python packages that are
used as libraries, and applications that are written in Python.
The Nix and NixOS manuals explain how packages are generally installed. In the
case of Python and Nix, it is important to make a distinction between whether the
package is considered an application or a library.
Applications on Nix are installed typically into your user
Applications on Nix are typically installed into your user
profile imperatively using `nix-env -i`, and on NixOS declaratively by adding the
package name to `environment.systemPackages` in `/etc/nixos/configuration.nix`.
Dependencies such as libraries are automatically installed and should not be
installed explicitly.
The same goes for Python applications and libraries. Python applications can be
installed in your profile, but Python libraries you would like to use to develop
cannot. If you do install libraries in your profile, then you will end up with
import errors.
installed in your profile. But Python libraries you would like to use for
development cannot be installed, at least not individually, because they won't
be able to find each other resulting in import errors. Instead, it is possible
to create an environment with `python.buildEnv` or `python.withPackages` where
the interpreter and other executables are able to find each other and all of the
modules.
#### Python environments using `nix-shell`
In the following examples we create an environment with Python 3.5, `numpy` and
`toolz`. As you may imagine, there is one limitation here, and that's that
you can install only one environment at a time. You will notice the complaints
about collisions when you try to install a second environment.
The recommended method for creating Python environments for development is with
`nix-shell`. Executing
##### Environment defined in separate `.nix` file
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> {};
python35.withPackages (ps: with ps; [ numpy toolz ])
```
and install it in your profile with
```shell
nix-env -if build.nix
```
Now you can use the Python interpreter, as well as the extra packages (`numpy`,
`toolz`) that you added to the environment.
##### Environment defined in `~/.config/nixpkgs/config.nix`
If you prefer to, you could also add the environment as a package override to the Nixpkgs set, e.g.
using `config.nix`,
```nix
{ # ...
packageOverrides = pkgs: with pkgs; {
myEnv = python35.withPackages (ps: with ps; [ numpy toolz ]);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myEnv
```
The environment is is installed by referring to the attribute, and considering
the `nixpkgs` channel was used.
##### 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; [
(python35.withPackages(ps: with ps; [ numpy toolz ]))
];
}
```
opens a Nix shell which has available the requested packages and dependencies.
Now you can launch the Python interpreter (which is itself a dependency)
#### Temporary Python environment with `nix-shell`
The examples in the previous section showed how to install a Python environment
into a profile. For development you may need to use multiple environments.
`nix-shell` gives the possibility to temporarily load another environment, akin
to `virtualenv`.
There are two methods for loading a shell with Python packages. The first and recommended method
is to create an environment with `python.buildEnv` or `python.withPackages` and load that. E.g.
```sh
$ nix-shell -p 'python35.withPackages(ps: with ps; [ numpy toolz ])'
```
opens a shell from which you can launch the interpreter
```sh
[nix-shell:~] python3
```
The other method, which is not recommended, does not create an environment and requires you to list the packages directly,
If the packages were not available yet in the Nix store, Nix would download or
build them automatically. A convenient option with `nix-shell` is the `--run`
option, with which you can execute a command in the `nix-shell`. Let's say we
want the above environment and directly run the Python interpreter
```sh
$ nix-shell -p python35.pkgs.numpy python35.pkgs.toolz
```
Again, it is possible to launch the interpreter from the shell.
The Python interpreter has the attribute `pkgs` which contains all Python libraries for that specific interpreter.
##### Load environment from `.nix` expression
As explained in the Nix manual, `nix-shell` can also load an
expression from a `.nix` file. Say we want to have Python 3.5, `numpy`
and `toolz`, like before, in an environment. Consider a `shell.nix` file
with
```nix
with import <nixpkgs> {};
python35.withPackages (ps: [ps.numpy ps.toolz])
```
Executing `nix-shell` gives you again a Nix shell from which you can run Python.
What's happening here?
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` imports the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. These attributes form the main package set.
2. Then we create a Python 3.5 environment with the `withPackages` function.
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all python packages and returns a list of packages to include in the environment. Here, we select the packages `numpy` and `toolz` from the package set.
##### Execute command with `--run`
A convenient option with `nix-shell` is the `--run`
option, with which you can execute a command in the `nix-shell`. We can
e.g. directly open a Python shell
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3"
```
This way you can use the `--run` option also to directly run a script
or run a script
```sh
$ nix-shell -p python35Packages.numpy python35Packages.toolz --run "python3 myscript.py"
```
In fact, for this specific use case there is a more convenient method. You can
##### `nix-shell` as shebang
In fact, for the second use case, there is a more convenient method. You can
add a [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) to your script
specifying which dependencies Nix shell needs. With the following shebang, you
can use `nix-shell myscript.py` and it will make available all dependencies and
specifying which dependencies `nix-shell` needs. With the following shebang, you
can just execute `./myscript.py`, and it will make available all dependencies and
run the script in the `python3` shell.
```py
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.numpy
#! nix-shell -i 'python3.withPackages(ps: [ps.numpy])'
import numpy
print(numpy.__version__)
```
Likely you do not want to type your dependencies each and every time. What you
can do is write a simple Nix expression which sets up an environment for you,
requiring you only to type `nix-shell`. Say we want to have Python 3.5, `numpy`
and `toolz`, like before, in an environment. With a `shell.nix` file
containing
```nix
with import <nixpkgs> {};
(pkgs.python35.withPackages (ps: [ps.numpy ps.toolz])).env
```
executing `nix-shell` gives you again a Nix shell from which you can run Python.
What's happening here?
1. We begin with importing the Nix Packages collections. `import <nixpkgs>` import the `<nixpkgs>` function, `{}` calls it and the `with` statement brings all attributes of `nixpkgs` in the local scope. Therefore we can now use `pkgs`.
2. Then we create a Python 3.5 environment with the `withPackages` function.
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all python packages and returns a list of packages to include in the environment. Here, we select the packages `numpy` and `toolz` from the package set.
4. And finally, for in interactive use we return the environment by using the `env` attribute.
### Developing with Python
Now that you know how to get a working Python environment with Nix, it is time
to go forward and start actually developing with Python. We will first have a
look at how Python packages are packaged on Nix. Then, we will look at how you
can use development mode with your code.
Now that you know how to get a working Python environment on Nix, it is time to go forward and start actually developing with Python.
We will first have a look at how Python packages are packaged on Nix. Then, we will look how you can use development mode with your code.
#### Packaging a library
#### Python packaging on Nix
On Nix all packages are built by functions. The main function in Nix for building Python packages is [`buildPythonPackage`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/interpreters/python/build-python-package.nix).
Let's see how we would build the `toolz` package. According to [`python-packages.nix`](https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/top-level/python-packages.nix) `toolz` is build using
With Nix all packages are built by functions. The main function in Nix for
building Python libraries is `buildPythonPackage`. Let's see how we can build the
`toolz` package.
```nix
{ # ...
toolz = buildPythonPackage rec {
name = "toolz-${version}";
pname = "toolz";
version = "0.7.4";
name = "${pname}-${version}";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
src = fetchPypi {
inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
doCheck = false;
meta = {
homepage = "http://github.com/pytoolz/toolz/";
description = "List processing tools and functional utilities";
@ -122,63 +211,37 @@ Let's see how we would build the `toolz` package. According to [`python-packages
```
What happens here? The function `buildPythonPackage` is called and as argument
it accepts a set. In this case the set is a recursive set ([`rec`](http://nixos.org/nix/manual/#sec-constructs)).
One of the arguments is the name of the package, which consists of a basename
(generally following the name on PyPi) and a version. Another argument, `src`
specifies the source, which in this case is fetched from an url. `fetchurl` not
only downloads the target file, but also validates its hash. Furthermore, we
specify some (optional) [meta information](http://nixos.org/nixpkgs/manual/#chap-meta).
The output of the function is a derivation, which is an attribute with the name
`toolz` of the set `pythonPackages`. Actually, sets are created for all interpreter versions,
so e.g. `python27Packages`, `python35Packages` and `pypyPackages`.
it accepts a set. In this case the set is a recursive set, `rec`. One of the
arguments is the name of the package, which consists of a basename (generally
following the name on PyPi) and a version. Another argument, `src` specifies the
source, which in this case is fetched from PyPI using the helper function
`fetchPypi`. The argument `doCheck` is used to set whether tests should be run
when building the package. Furthermore, we specify some (optional) meta
information. The output of the function is a derivation.
An expression for `toolz` can be found in the Nixpkgs repository. As explained
in the introduction of this Python section, a derivation of `toolz` is available
for each interpreter version, e.g. `python35.pkgs.toolz` refers to the `toolz`
derivation corresponding to the CPython 3.5 interpreter.
The above example works when you're directly working on
`pkgs/top-level/python-packages.nix` in the Nixpkgs repository. Often though,
you will want to test a Nix expression outside of the Nixpkgs tree. If you
create a `shell.nix` file with the following contents
you will want to test a Nix expression outside of the Nixpkgs tree.
```nix
with import <nixpkgs> {};
pkgs.python35Packages.buildPythonPackage rec {
name = "toolz-${version}";
version = "0.8.0";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
};
doCheck = false;
meta = {
homepage = "http://github.com/pytoolz/toolz/";
description = "List processing tools and functional utilities";
license = licenses.bsd3;
maintainers = with maintainers; [ fridh ];
};
}
```
and then execute `nix-shell` will result in an environment in which you can use
Python 3.5 and the `toolz` package. As you can see we had to explicitly mention
for which Python version we want to build a package.
The above example considered only a single package. Generally you will want to use multiple packages.
If we create a `shell.nix` file with the following contents
The following expression creates a derivation for the `toolz` package,
and adds it along with a `numpy` package to a Python environment.
```nix
with import <nixpkgs> {};
( let
toolz = pkgs.python35Packages.buildPythonPackage rec {
name = "toolz-${version}";
version = "0.8.0";
my_toolz = python35.pkgs.buildPythonPackage rec {
pname = "toolz";
version = "0.7.4";
name = "${pname}-${version}";
src = pkgs.fetchurl {
url = "mirror://pypi/t/toolz/toolz-${version}.tar.gz";
sha256 = "e8451af61face57b7c5d09e71c0d27b8005f001ead56e9fdf470417e5cc6d479";
src = python35.pkgs.fetchPypi {
inherit pname version;
sha256 = "43c2c9e5e7a16b6c88ba3088a9bfc82f7db8e13378be7c78d6c14a5f8ed05afd";
};
doCheck = false;
@ -189,24 +252,24 @@ with import <nixpkgs> {};
};
};
in pkgs.python35.withPackages (ps: [ps.numpy toolz])
in python35.withPackages (ps: [ps.numpy my_toolz])
).env
```
Executing `nix-shell` will result in an environment in which you can use
Python 3.5 and the `toolz` package. As you can see we had to explicitly mention
for which Python version we want to build a package.
and again execute `nix-shell`, then we get a Python 3.5 environment with our
locally defined package as well as `numpy` which is build according to the
definition in Nixpkgs. What did we do here? Well, we took the Nix expression
that we used earlier to build a Python environment, and said that we wanted to
include our own version of `toolz`. To introduce our own package in the scope of
`withPackages` we used a
[`let`](http://nixos.org/nix/manual/#sec-constructs) expression.
You can see that we used `ps.numpy` to select numpy from the nixpkgs package set (`ps`).
But we do not take `toolz` from the nixpkgs package set this time.
Instead, `toolz` will resolve to our local definition that we introduced with `let`.
So, what did we do here? Well, we took the Nix expression that we used earlier
to build a Python environment, and said that we wanted to include our own
version of `toolz`, named `my_toolz`. To introduce our own package in the scope
of `withPackages` we used a `let` expression. You can see that we used
`ps.numpy` to select numpy from the nixpkgs package set (`ps`). We did not take
`toolz` from the Nixpkgs package set this time, but instead took our own version
that we introduced with the `let` expression.
### Handling dependencies
#### Handling dependencies
Our example, `toolz`, doesn't have any dependencies on other Python
Our example, `toolz`, does not have any dependencies on other Python
packages or system libraries. According to the manual, `buildPythonPackage`
uses the arguments `buildInputs` and `propagatedBuildInputs` to specify dependencies. If something is
exclusively a build-time dependency, then the dependency should be included as a
@ -340,7 +403,7 @@ other packages we like to have in the environment, all specified with `propagate
Indeed, we can just add any package we like to have in our environment to `propagatedBuildInputs`.
```nix
with import <nixpkgs>;
with import <nixpkgs> {};
with pkgs.python35Packages;
buildPythonPackage rec {
@ -423,7 +486,7 @@ and in this case the `python35` interpreter is automatically used.
### Interpreters
Versions 2.7, 3.3, 3.4, 3.5 and 3.6 of the CPython interpreter are available as
respectively `python27`, `python33`, `python34`, `python35` and `python36`. The PyPy interpreter
respectively `python27`, `python34`, `python35` and `python36`. The PyPy interpreter
is available as `pypy`. The aliases `python2` and `python3` correspond to respectively `python27` and
`python35`. The default interpreter, `python`, maps to `python2`.
The Nix expressions for the interpreters can be found in
@ -469,7 +532,6 @@ sets are
* `pkgs.python26Packages`
* `pkgs.python27Packages`
* `pkgs.python33Packages`
* `pkgs.python34Packages`
* `pkgs.python35Packages`
* `pkgs.python36Packages`
@ -546,6 +608,35 @@ All parameters from `mkDerivation` function are still supported.
* `catchConflicts` If `true`, abort package build if a package name appears more than once in dependency tree. Default is `true`.
* `checkInputs` Dependencies needed for running the `checkPhase`. These are added to `buildInputs` when `doCheck = true`.
##### Overriding Python packages
The `buildPythonPackage` function has a `overridePythonAttrs` method that
can be used to override the package. In the following example we create an
environment where we have the `blaze` package using an older version of `pandas`.
We override first the Python interpreter and pass
`packageOverrides` which contains the overrides for packages in the package set.
```nix
with import <nixpkgs> {};
(let
python = let
packageOverrides = self: super: {
pandas = super.pandas.overridePythonAttrs(old: rec {
version = "0.19.1";
name = "pandas-${version}";
src = super.fetchPypi {
pname = "pandas";
inherit version;
sha256 = "08blshqj9zj1wyjhhw3kl2vas75vhhicvv72flvf1z3jvapgw295";
};
});
};
in pkgs.python3.override {inherit packageOverrides;};
in python.withPackages(ps: [ps.blaze])).env
```
#### `buildPythonApplication` function
The `buildPythonApplication` function is practically the same as `buildPythonPackage`.
@ -622,7 +713,7 @@ attribute. The `shell.nix` file from the previous section can thus be also writt
```nix
with import <nixpkgs> {};
(python33.withPackages (ps: [ps.numpy ps.requests])).env
(python36.withPackages (ps: [ps.numpy ps.requests])).env
```
In contrast to `python.buildEnv`, `python.withPackages` does not support the more advanced options
@ -685,63 +776,6 @@ Both are also exported in `nix-shell`.
## 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> {};
pkgs.python35.withPackages (ps: with ps; [ numpy ipython ])
```
and install it in your profile with
```shell
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 `~/.config/nixpkgs/config.nix`
If you prefer to, you could also add the environment as a package override to the Nixpkgs set.
```nix
{ # ...
packageOverrides = pkgs: with pkgs; {
myEnv = python35.withPackages (ps: with ps; [ numpy ipython ]);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myEnv
```
We're installing using the attribute path and assume the channels is named `nixpkgs`.
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; [
(python35.withPackages(ps: with ps; [ numpy ipython ]))
];
}
```
### How to solve circular dependencies?
Consider the packages `A` and `B` that depend on each other. When packaging `B`,
@ -755,17 +789,17 @@ In the following example we rename the `pandas` package and build it.
```nix
with import <nixpkgs> {};
let
(let
python = let
packageOverrides = self: super: {
pandas = super.pandas.override {name="foo";};
pandas = super.pandas.overridePythonAttrs(old: {name="foo";});
};
in pkgs.python35.override {inherit packageOverrides;};
in python.pkgs.pandas
in python.withPackages(ps: [ps.pandas])).env
```
Using `nix-build` on this expression will build the package `pandas`
but with the new name `foo`.
Using `nix-build` on this expression will build an environment that contains the
package `pandas` but with the new name `foo`.
All packages in the package set will use the renamed package.
A typical use case is to switch to another version of a certain package.

View File

@ -4,10 +4,14 @@
<title>Ruby</title>
<para>There currently is support to bundle applications that are packaged as Ruby gems. The utility "bundix" allows you to write a <filename>Gemfile</filename>, let bundler create a <filename>Gemfile.lock</filename>, and then convert
this into a nix expression that contains all Gem dependencies automatically.</para>
<para>There currently is support to bundle applications that are packaged as
Ruby gems. The utility "bundix" allows you to write a
<filename>Gemfile</filename>, let bundler create a
<filename>Gemfile.lock</filename>, and then convert this into a nix
expression that contains all Gem dependencies automatically.
</para>
<para>For example, to package sensu, we did:</para>
<para>For example, to package sensu, we did:</para>
<screen>
<![CDATA[$ cd pkgs/servers/monitoring
@ -16,7 +20,7 @@ $ cd sensu
$ cat > Gemfile
source 'https://rubygems.org'
gem 'sensu'
$ $(nix-build '<nixpkgs>' -A bundix)/bin/bundix --magic
$ $(nix-build '<nixpkgs>' -A bundix --no-out-link)/bin/bundix --magic
$ cat > default.nix
{ lib, bundlerEnv, ruby }:
@ -38,15 +42,61 @@ bundlerEnv rec {
}]]>
</screen>
<para>Please check in the <filename>Gemfile</filename>, <filename>Gemfile.lock</filename> and the <filename>gemset.nix</filename> so future updates can be run easily.
<para>Please check in the <filename>Gemfile</filename>,
<filename>Gemfile.lock</filename> and the
<filename>gemset.nix</filename> so future updates can be run easily.
</para>
<para>Resulting derivations also have two helpful items, <literal>env</literal> and <literal>wrapper</literal>. The first one allows one to quickly drop into
<command>nix-shell</command> with the specified environment present. E.g. <command>nix-shell -A sensu.env</command> would give you an environment with Ruby preset
so it has all the libraries necessary for <literal>sensu</literal> in its paths. The second one can be used to make derivations from custom Ruby scripts which have
<filename>Gemfile</filename>s with their dependencies specified. It is a derivation with <command>ruby</command> wrapped so it can find all the needed dependencies.
For example, to make a derivation <literal>my-script</literal> for a <filename>my-script.rb</filename> (which should be placed in <filename>bin</filename>) you should
run <command>bundix</command> as specified above and then use <literal>bundlerEnv</literal> like this:</para>
<para>For tools written in Ruby - i.e. where the desire is to install
a package and then execute e.g. <command>rake</command> at the command
line, there is an alternative builder called <literal>bundlerApp</literal>.
Set up the <filename>gemset.nix</filename> the same way, and then, for
example:
</para>
<screen>
<![CDATA[{ lib, bundlerApp }:
bundlerApp {
pname = "corundum";
gemdir = ./.;
exes = [ "corundum-skel" ];
meta = with lib; {
description = "Tool and libraries for maintaining Ruby gems.";
homepage = https://github.com/nyarly/corundum;
license = licenses.mit;
maintainers = [ maintainers.nyarly ];
platforms = platforms.unix;
};
}]]>
</screen>
<para>The chief advantage of <literal>bundlerApp</literal> over
<literal>bundlerEnv</literal> is the executables introduced in the
environment are precisely those selected in the <literal>exes</literal>
list, as opposed to <literal>bundlerEnv</literal> which adds all the
executables made available by gems in the gemset, which can mean e.g.
<command>rspec</command> or <command>rake</command> in unpredictable
versions available from various packages.
</para>
<para>Resulting derivations for both builders also have two helpful
attributes, <literal>env</literal> and <literal>wrappedRuby</literal>.
The first one allows one to quickly drop into
<command>nix-shell</command> with the specified environment present.
E.g. <command>nix-shell -A sensu.env</command> would give you an
environment with Ruby preset so it has all the libraries necessary
for <literal>sensu</literal> in its paths. The second one can be
used to make derivations from custom Ruby scripts which have
<filename>Gemfile</filename>s with their dependencies specified. It is
a derivation with <command>ruby</command> wrapped so it can find all
the needed dependencies. For example, to make a derivation
<literal>my-script</literal> for a <filename>my-script.rb</filename>
(which should be placed in <filename>bin</filename>) you should run
<command>bundix</command> as specified above and then use
<literal>bundlerEnv</literal> like this:
</para>
<programlisting>
<![CDATA[let env = bundlerEnv {
@ -60,13 +110,9 @@ run <command>bundix</command> as specified above and then use <literal>bundlerEn
in stdenv.mkDerivation {
name = "my-script";
buildInputs = [ env.wrapper ];
buildInputs = [ env.wrappedRuby ];
script = ./my-script.rb;
buildCommand = ''
mkdir -p $out/bin
install -D -m755 $script $out/bin/my-script
patchShebangs $out/bin/my-script
'';
@ -74,4 +120,3 @@ in stdenv.mkDerivation {
</programlisting>
</section>

View File

@ -73,7 +73,7 @@
<varlistentry><term><varname>
$outputMan</varname></term><listitem><para>
is for man pages (except for section 3). They go to <varname>man</varname> or <varname>doc</varname> or <varname>$outputBin</varname> by default.
is for man pages (except for section 3). They go to <varname>man</varname> or <varname>$outputBin</varname> by default.
</para></listitem></varlistentry>
<varlistentry><term><varname>
@ -83,7 +83,7 @@
<varlistentry><term><varname>
$outputInfo</varname></term><listitem><para>
is for info pages. They go to <varname>info</varname> or <varname>doc</varname> or <varname>$outputMan</varname> by default.
is for info pages. They go to <varname>info</varname> or <varname>$outputBin</varname> by default.
</para></listitem></varlistentry>
</variablelist>

View File

@ -8,59 +8,88 @@
overlays. Overlays are used to add layers in the fix-point used by Nixpkgs
to compose the set of all packages.</para>
<para>Nixpkgs can be configured with a list of overlays, which are
applied in order. This means that the order of the overlays can be significant
if multiple layers override the same package.</para>
<!--============================================================-->
<section xml:id="sec-overlays-install">
<title>Installing Overlays</title>
<title>Installing overlays</title>
<para>The set of overlays is looked for in the following places. The
first one present is considered, and all the rest are ignored:
<para>The list of overlays is determined as follows.</para>
<para>If the <varname>overlays</varname> argument is not provided explicitly, we look for overlays in a path. The path
is determined as follows:
<orderedlist>
<listitem>
<para>First, if an <varname>overlays</varname> argument to the nixpkgs function itself is given,
then that is used.</para>
<para>As an argument of the imported attribute set. When importing Nixpkgs,
the <varname>overlays</varname> attribute argument can be set to a list of
functions, which is described in <xref linkend="sec-overlays-layout"/>.</para>
<para>This can be passed explicitly when importing nipxkgs, for example
<literal>import &lt;nixpkgs> { overlays = [ overlay1 overlay2 ]; }</literal>.</para>
</listitem>
<listitem>
<para>Otherwise, if the Nix path entry <literal>&lt;nixpkgs-overlays></literal> exists, we look for overlays
at that path, as described below.</para>
<para>In the directory pointed to by the Nix search path entry
<literal>&lt;nixpkgs-overlays></literal>.</para>
<para>See the section on <literal>NIX_PATH</literal> in the Nix manual for more details on how to
set a value for <literal>&lt;nixpkgs-overlays>.</literal></para>
</listitem>
<listitem>
<para>In the directory <filename>~/.config/nixpkgs/overlays/</filename>.</para>
<para>If one of <filename>~/.config/nixpkgs/overlays.nix</filename> and
<filename>~/.config/nixpkgs/overlays/</filename> exists, then we look for overlays at that path, as
described below. It is an error if both exist.</para>
</listitem>
</orderedlist>
</para>
<para>For the second and third options, the directory should contain Nix expressions defining the
overlays. Each overlay can be a file, a directory containing a
<filename>default.nix</filename>, or a symlink to one of those. The expressions should follow
the syntax described in <xref linkend="sec-overlays-layout"/>.</para>
<para>If we are looking for overlays at a path, then there are two cases:
<itemizedlist>
<listitem>
<para>If the path is a file, then the file is imported as a Nix expression and used as the list of
overlays.</para>
</listitem>
<para>The order of the overlay layers can influence the recipe of packages if multiple layers override
the same recipe. In the case where overlays are loaded from a directory, they are loaded in
alphabetical order.</para>
<listitem>
<para>If the path is a directory, then we take the content of the directory, order it
lexicographically, and attempt to interpret each as an overlay by:
<itemizedlist>
<listitem>
<para>Importing the file, if it is a <literal>.nix</literal> file.</para>
</listitem>
<listitem>
<para>Importing a top-level <filename>default.nix</filename> file, if it is a directory.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para>To install an overlay using the last option, you can clone the overlay's repository and add
a symbolic link to it in <filename>~/.config/nixpkgs/overlays/</filename> directory.</para>
<para>On a NixOS system the value of the <literal>nixpkgs.overlays</literal> option, if present,
is passed to the system Nixpkgs directly as an argument. Note that this does not affect the overlays for
non-NixOS operations (e.g. <literal>nix-env</literal>), which are looked up independently.</para>
<para>The <filename>overlays.nix</filename> option therefore provides a convenient way to use the same
overlays for a NixOS system configuration and user configuration: the same file can be used
as <filename>overlays.nix</filename> and imported as the value of <literal>nixpkgs.overlays</literal>.</para>
</section>
<!--============================================================-->
<section xml:id="sec-overlays-layout">
<title>Overlays Layout</title>
<section xml:id="sec-overlays-definition">
<title>Defining overlays</title>
<para>Overlays are expressed as Nix functions which accept 2 arguments and return a set of
packages.</para>
<para>Overlays are Nix functions which accept two arguments,
conventionally called <varname>self</varname> and <varname>super</varname>,
and return a set of packages. For example, the following is a valid overlay.</para>
<programlisting>
self: super:
@ -75,25 +104,31 @@ self: super:
}
</programlisting>
<para>The first argument, usually named <varname>self</varname>, corresponds to the final package
<para>The first argument (<varname>self</varname>) corresponds to the final package
set. You should use this set for the dependencies of all packages specified in your
overlay. For example, all the dependencies of <varname>rr</varname> in the example above come
from <varname>self</varname>, as well as the overridden dependencies used in the
<varname>boost</varname> override.</para>
<para>The second argument, usually named <varname>super</varname>,
<para>The second argument (<varname>super</varname>)
corresponds to the result of the evaluation of the previous stages of
Nixpkgs. It does not contain any of the packages added by the current
overlay nor any of the following overlays. This set should be used either
overlay, nor any of the following overlays. This set should be used either
to refer to packages you wish to override, or to access functions defined
in Nixpkgs. For example, the original recipe of <varname>boost</varname>
in the above example, comes from <varname>super</varname>, as well as the
<varname>callPackage</varname> function.</para>
<para>The value returned by this function should be a set similar to
<filename>pkgs/top-level/all-packages.nix</filename>, which contains
<filename>pkgs/top-level/all-packages.nix</filename>, containing
overridden and/or new packages.</para>
<para>Overlays are similar to other methods for customizing Nixpkgs, in particular
the <literal>packageOverrides</literal> attribute described in <xref linkend="sec-modify-via-packageOverrides"/>.
Indeed, <literal>packageOverrides</literal> acts as an overlay with only the
<varname>super</varname> argument. It is therefore appropriate for basic use,
but overlays are more powerful and easier to distribute.</para>
</section>
</chapter>

View File

@ -366,15 +366,33 @@ it. Place the resulting <filename>package.nix</filename> file into
</section>
<section xml:id="sec-autojump">
<section xml:id="sec-shell-helpers">
<title>Autojump</title>
<title>Interactive shell helpers</title>
<para>
autojump needs the shell integration to be useful but unlike other systems,
nix doesn't have a standard share directory location. This is why a
<command>autojump-share</command> script is shipped that prints the location
of the shared folder. This can then be used in the .bashrc like this:
Some packages provide the shell integration to be more useful. But
unlike other systems, nix doesn't have a standard share directory
location. This is why a bunch <command>PACKAGE-share</command>
scripts are shipped that print the location of the corresponding
shared folder.
Current list of such packages is as following:
<itemizedlist>
<listitem>
<para>
<literal>autojump</literal>: <command>autojump-share</command>
</para>
</listitem>
<listitem>
<para>
<literal>fzf</literal>: <command>fzf-share</command>
</para>
</listitem>
</itemizedlist>
E.g. <literal>autojump</literal> can then used in the .bashrc like this:
<screen>
source "$(autojump-share)/autojump.bash"
</screen>

View File

@ -212,7 +212,7 @@ $ nix-env -f . -iA libfoo</screen>
<listitem>
<para>Optionally commit the new package and open a pull request, or send a patch to
<literal>nix-dev@cs.uu.nl</literal>.</para>
<literal>https://groups.google.com/forum/#!forum/nix-devel</literal>.</para>
</listitem>

View File

@ -1,3 +1,4 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-stdenv">
@ -1153,7 +1154,7 @@ makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello
</listitem>
</varlistentry>
<varlistentry xml:id='fun-substitute'>
<term><function>substitute</function>
@ -1312,7 +1313,7 @@ someVar=$(stripHash $name)
</para></listitem>
</varlistentry>
<varlistentry xml:id='fun-wrapProgram'>
<term><function>wrapProgram</function>
@ -1342,12 +1343,34 @@ someVar=$(stripHash $name)
<variablelist>
<varlistentry>
<term>GCC wrapper</term>
<listitem><para>Adds the <filename>include</filename> subdirectory
of each build input to the <envar>NIX_CFLAGS_COMPILE</envar>
environment variable, and the <filename>lib</filename> and
<filename>lib64</filename> subdirectories to
<envar>NIX_LDFLAGS</envar>.</para></listitem>
<term>CC Wrapper</term>
<listitem>
<para>
CC Wrapper wraps a C toolchain for a bunch of miscellaneous purposes.
Specifically, a C compiler (GCC or Clang), Binutils (or the CCTools + binutils mashup when targetting Darwin), and a C standard library (glibc or Darwin's libSystem) are all fed in, and dependency finding, hardening (see below), and purity checks for each are handled by CC Wrapper.
Packages typically depend on only CC Wrapper, instead of those 3 inputs directly.
</para>
<para>
Dependency finding is undoubtedly the main task of CC wrapper.
It is currently accomplished by collecting directories of host-platform dependencies (i.e. <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>) in environment variables.
CC wrapper's setup hook causes any <filename>include</filename> subdirectory of such a dependency to be added to <envar>NIX_CFLAGS_COMPILE</envar>, and any <filename>lib</filename> and <filename>lib64</filename> subdirectories to <envar>NIX_LDFLAGS</envar>.
The setup hook itself contains some lengthy comments describing the exact convoluted mechanism by which this is accomplished.
</para>
<para>
A final task of the setup hook is defining a number of standard environment variables to tell build systems which executables full-fill which purpose.
They are defined to just be the base name of the tools, under the assumption that CC Wrapper's binaries will be on the path.
Firstly, this helps poorly-written packages, e.g. ones that look for just <command>gcc</command> when <envar>CC</envar> isn't defined yet <command>clang</command> is to be used.
Secondly, this helps packages not get confused when cross-compiling, in which case multiple CC wrappers may be simultaneous in use (targeting different platforms).
<envar>BUILD_</envar>- and <envar>TARGET_</envar>-prefixed versions of the normal environment variable are defined for the additional CC Wrappers, properly disambiguating them.
</para>
<para>
A problem with this final task is that CC Wrapper is honest and defines <envar>LD</envar> as <command>ld</command>.
Most packages, however, firstly use the C compiler for linking, secondly use <envar>LD</envar> anyways, defining it as the C compiler, and thirdly, only so define <envar>LD</envar> when it is undefined as a fallback.
This triple-threat means CC Wrapper will break those packages, as LD is already defined as the actually linker which the package won't override yet doesn't want to use.
The workaround is to define, just for the problematic package, <envar>LD</envar> as the C compiler.
A good way to do this would be <command>preConfigure = "LD=$CC"</command>.
</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -309,48 +309,6 @@ rec {
mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
mergeAttrsByFuncDefaultsClean = list: removeAttrs (mergeAttrsByFuncDefaults list) ["mergeAttrBy"];
# merge attrs based on version key into mkDerivation args, see mergeAttrBy to learn about smart merge defaults
#
# This function is best explained by an example:
#
# {version ? "2.x"}:
#
# mkDerivation (mergeAttrsByVersion "package-name" version
# { # version specific settings
# "git" = { src = ..; preConfigre = "autogen.sh"; buildInputs = [automake autoconf libtool]; };
# "2.x" = { src = ..; };
# }
# { // shared settings
# buildInputs = [ common build inputs ];
# meta = { .. }
# }
# )
#
# Please note that e.g. Eelco Dolstra usually prefers having one file for
# each version. On the other hand there are valuable additional design goals
# - readability
# - do it once only
# - try to avoid duplication
#
# Marc Weber and Michael Raskin sometimes prefer keeping older
# versions around for testing and regression tests - as long as its cheap to
# do so.
#
# Very often it just happens that the "shared" code is the bigger part.
# Then using this function might be appropriate.
#
# Be aware that its easy to cause recompilations in all versions when using
# this function - also if derivations get too complex splitting into multiple
# files is the way to go.
#
# See misc.nix -> versionedDerivation
# discussion: nixpkgs: pull/310
mergeAttrsByVersion = name: version: attrsByVersion: base:
mergeAttrsByFuncDefaultsClean [ { name = "${name}-${version}"; }
base
(maybeAttr version (throw "bad version ${version} for ${name}") attrsByVersion)
];
# sane defaults (same name as attr name so that inherit can be used)
mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
listToAttrs (map (n: nameValuePair n lib.concat)

View File

@ -546,12 +546,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) rec {
fullName = "zlib License";
};
zpt20 = spdx { # FIXME: why zpt* instead of zpl*
zpl20 = spdx {
spdxId = "ZPL-2.0";
fullName = "Zope Public License 2.0";
};
zpt21 = spdx {
zpl21 = spdx {
spdxId = "ZPL-2.1";
fullName = "Zope Public License 2.1";
};

View File

@ -33,6 +33,7 @@
algorith = "Dries Van Daele <dries_van_daele@telenet.be>";
alibabzo = "Alistair Bill <alistair.bill@gmail.com>";
all = "Nix Committers <nix-commits@lists.science.uu.nl>";
alunduil = "Alex Brandt <alunduil@alunduil.com>";
ambrop72 = "Ambroz Bizjak <ambrop7@gmail.com>";
amiddelk = "Arie Middelkoop <amiddelk@gmail.com>";
amiloradovsky = "Andrew Miloradovsky <miloradovsky@gmail.com>";
@ -75,6 +76,7 @@
berdario = "Dario Bertini <berdario@gmail.com>";
bergey = "Daniel Bergey <bergey@teallabs.org>";
bhipple = "Benjamin Hipple <bhipple@protonmail.com>";
binarin = "Alexey Lebedeff <binarin@binarin.ru>";
bjg = "Brian Gough <bjg@gnu.org>";
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
@ -88,11 +90,13 @@
bstrik = "Berno Strik <dutchman55@gmx.com>";
bzizou = "Bruno Bzeznik <Bruno@bzizou.net>";
c0dehero = "CodeHero <codehero@nerdpol.ch>";
calbrecht = "Christian Albrecht <christian.albrecht@mayflower.de>";
calrama = "Moritz Maxeiner <moritz@ucworks.org>";
calvertvl = "Victor Calvert <calvertvl@gmail.com>";
campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
canndrew = "Andrew Cann <shum@canndrew.org>";
carlsverre = "Carl Sverre <accounts@carlsverre.com>";
casey = "Casey Rodarmor <casey@rodarmor.net>";
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
changlinli = "Changlin Li <mail@changlinli.com>";
@ -135,12 +139,14 @@
dbrock = "Daniel Brockman <daniel@brockman.se>";
deepfire = "Kosyrev Serge <_deepfire@feelingofgreen.ru>";
demin-dmitriy = "Dmitriy Demin <demindf@gmail.com>";
derchris = "Christian Gerbrandt <derchris@me.com>";
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
dermetfan = "Robin Stumm <serverkorken@gmail.com>";
DerTim1 = "Tim Digel <tim.digel@active-group.de>";
desiderius = "Didier J. Devroye <didier@devroye.name>";
devhell = "devhell <\"^\"@regexmail.net>";
dezgeg = "Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>";
dfordivam = "Divam <dfordivam+nixpkgs@gmail.com>";
dfoxfranke = "Daniel Fox Franke <dfoxfranke@gmail.com>";
dgonyeo = "Derek Gonyeo <derek@gonyeo.com>";
dipinhora = "Dipin Hora <dipinhora+github@gmail.com>";
@ -172,6 +178,7 @@
ekleog = "Leo Gaspard <leo@gaspard.io>";
elasticdog = "Aaron Bull Schaefer <aaron@elasticdog.com>";
eleanor = "Dejan Lukan <dejan@proteansec.com>";
elijahcaine = "Elijah Caine <elijahcainemv@gmail.com>";
elitak = "Eric Litak <elitak@gmail.com>";
ellis = "Ellis Whitehead <nixos@ellisw.net>";
eperuffo = "Emanuele Peruffo <info@emanueleperuffo.com>";
@ -208,10 +215,12 @@
garrison = "Jim Garrison <jim@garrison.cc>";
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
gebner = "Gabriel Ebner <gebner@gebner.org>";
geistesk = "Alvar Penning <post@0x21.biz>";
georgewhewell = "George Whewell <georgerw@gmail.com>";
gilligan = "Tobias Pflug <tobias.pflug@gmail.com>";
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
gleber = "Gleb Peregud <gleber.p@gmail.com>";
glenns = "Glenn Searby <glenn.searby@gmail.com>";
globin = "Robin Gloster <mail@glob.in>";
gnidorah = "Alex Ivanov <yourbestfriend@opmbx.org>";
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
@ -219,6 +228,7 @@
goodrone = "Andrew Trachenko <goodrone@gmail.com>";
gpyh = "Yacine Hmito <yacine.hmito@gmail.com>";
grahamc = "Graham Christensen <graham@grahamc.com>";
grburst = "Julius Elias <grburst@openmailbox.org>";
gridaphobe = "Eric Seidel <eric@seidel.io>";
guibert = "David Guibert <david.guibert@gmail.com>";
guillaumekoenig = "Guillaume Koenig <guillaume.edward.koenig@gmail.com>";
@ -230,6 +240,7 @@
hectorj = "Hector Jusforgues <hector.jusforgues+nixos@gmail.com>";
heel = "Sergii Paryzhskyi <parizhskiy@gmail.com>";
henrytill = "Henry Till <henrytill@gmail.com>";
hhm = "hhm <heehooman+nixpkgs@gmail.com>";
hinton = "Tom Hinton <t@larkery.com>";
hodapp = "Chris Hodapp <hodapp87@gmail.com>";
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
@ -238,14 +249,14 @@
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
igsha = "Igor Sharonov <igor.sharonov@gmail.com>";
ikervagyok = "Balázs Lengyel <ikervagyok@gmail.com>";
infinisil = "Silvan Mosberger <infinisil@icloud.com";
infinisil = "Silvan Mosberger <infinisil@icloud.com>";
ivan-tkatchev = "Ivan Tkatchev <tkatchev@gmail.com>";
j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>";
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
jammerful = "jammerful <jammerful@gmail.com>";
jansol = "Jan Solanti <jan.solanti@paivola.fi>";
javaguirre = "Javier Aguirre <contacto@javaguirre.net>";
jb55 = "William Casarin <bill@casarin.me>";
jb55 = "William Casarin <jb55@jb55.com>";
jbedo = "Justin Bedő <cu@cua0.org>";
jcumming = "Jack Cummings <jack@mudshark.org>";
jdagilliland = "Jason Gilliland <jdagilliland@gmail.com>";
@ -286,8 +297,10 @@
khumba = "Bryan Gardiner <bog@khumba.net>";
KibaFox = "Kiba Fox <kiba.fox@foxypossibilities.com>";
kierdavis = "Kier Davis <kierdavis@gmail.com>";
kiloreux = "Kiloreux Emperex <kiloreux@gmail.com>";
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
knedlsepp = "Josef Kemetmüller <josef.kemetmueller@gmail.com>";
konimex = "Muhammad Herdiansyah <herdiansyah@openmailbox.org>";
koral = "Koral <koral@mailoo.org>";
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
kragniz = "Louis Taylor <louis@kragniz.eu>";
@ -308,6 +321,7 @@
lihop = "Leroy Hopson <nixos@leroy.geek.nz>";
linquize = "Linquize <linquize@yahoo.com.hk>";
linus = "Linus Arver <linusarver@gmail.com>";
lluchs = "Lukas Werling <lukas.werling@gmail.com>";
lnl7 = "Daiderd Jordan <daiderd@gmail.com>";
loskutov = "Ignat Loskutov <ignat.loskutov@gmail.com>";
lovek323 = "Jason O'Conal <jason@oconal.id.au>";
@ -371,6 +385,7 @@
MostAwesomeDude = "Corbin Simpson <cds@corbinsimpson.com>";
mounium = "Katona László <muoniurn@gmail.com>";
MP2E = "Cray Elliott <MP2E@archlinux.us>";
mpcsh = "Mark Cohen <m@mpc.sh>";
mpscholten = "Marc Scholten <marc@mpscholten.de>";
mpsyco = "Francis St-Amour <fr.st-amour@gmail.com>";
msackman = "Matthew Sackman <matthew@wellquite.org>";
@ -402,6 +417,7 @@
np = "Nicolas Pouillard <np.nix@nicolaspouillard.fr>";
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
nthorne = "Niklas Thörne <notrupertthorne@gmail.com>";
nyarly = "Judson Lester <nyarly@gmail.com>";
obadz = "obadz <obadz-nixos@obadz.com>";
ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
odi = "Oliver Dunkl <oliver.dunkl@gmail.com>";
@ -496,6 +512,7 @@
ryanartecona = "Ryan Artecona <ryanartecona@gmail.com>";
ryansydnor = "Ryan Sydnor <ryan.t.sydnor@gmail.com>";
ryantm = "Ryan Mulligan <ryan@ryantm.com>";
rybern = "Ryan Bernstein <ryan.bernstein@columbia.edu>";
rycee = "Robert Helgesson <robert@rycee.net>";
ryneeverett = "Ryne Everett <ryneeverett@gmail.com>";
rzetterberg = "Richard Zetterberg <richard.zetterberg@gmail.com>";
@ -503,10 +520,12 @@
samuelrivas = "Samuel Rivas <samuelrivas@gmail.com>";
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
sargon = "Daniel Ehlers <danielehlers@mindeye.net>";
sauyon = "Sauyon Lee <s@uyon.co>";
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
schneefux = "schneefux <schneefux+nixos_pkg@schneefux.xyz>";
schristo = "Scott Christopher <schristopher@konputa.com>";
scolobb = "Sergiu Ivanov <sivanov@colimite.fr>";
sdll = "Sasha Illarionov <sasha.delly@gmail.com>";
sepi = "Raffael Mancini <raffael@mancini.lu>";
seppeljordan = "Sebastian Jordan <sebastian.jordan.mail@googlemail.com>";
shanemikel = "Shane Pearlman <shanemikel1@gmail.com>";
@ -560,9 +579,11 @@
thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
timbertson = "Tim Cuthbertson <tim@gfxmonk.net>";
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
tnias = "Philipp Bartsch <phil@grmr.de>";
tohl = "Tomas Hlavaty <tom@logand.com>";
tokudan = "Daniel Frank <git@danielfrank.net>";
tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
tomsmeets = "Tom Smeets <tom@tsmeets.nl>";
travisbhartwell = "Travis B. Hartwell <nafai@travishartwell.net>";
trevorj = "Trevor Joynson <nix@trevor.joynson.io>";
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
@ -577,7 +598,9 @@
utdemir = "Utku Demir <me@utdemir.com>";
#urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; inactive since 2012
uwap = "uwap <me@uwap.name>";
vaibhavsagar = "Vaibhav Sagar <vaibhavsagar@gmail.com>";
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
vanschelven = "Klaas van Schelven <klaas@vanschelven.com>";
vanzef = "Ivan Solyankin <vanzef@gmail.com>";
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
@ -585,6 +608,7 @@
vdemeester = "Vincent Demeester <vincent@sbr.pm>";
veprbl = "Dmitry Kalinkin <veprbl@gmail.com>";
vifino = "Adrian Pistol <vifino@tty.sh>";
vinymeuh = "VinyMeuh <vinymeuh@gmail.com>";
viric = "Lluís Batlle i Rossell <viric@viric.name>";
vizanto = "Danny Wilson <danny@prime.vc>";
vklquevs = "vklquevs <vklquevs@gmail.com>";
@ -596,7 +620,9 @@
volth = "Jaroslavas Pocepko <jaroslavas@volth.com>";
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
vrthra = "Rahul Gopinath <rahul@gopinath.org>";
vyp = "vyp <elisp.vim@gmail.com>";
wedens = "wedens <kirill.wedens@gmail.com>";
willibutz = "Willi Butz <willibutz@posteo.de>";
willtim = "Tim Philip Williams <tim.williams.public@gmail.com>";
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
@ -621,6 +647,7 @@
zauberpony = "Elmar Athmer <elmar@athmer.org>";
zef = "Zef Hemel <zef@zef.me>";
zimbatm = "zimbatm <zimbatm@zimbatm.com>";
Zimmi48 = "Théo Zimmermann <theo.zimmermann@univ-paris-diderot.fr>";
zohl = "Al Zohali <zohl@fmap.me>";
zoomulator = "Kim Simmons <zoomulator@gmail.com>";
zraexy = "David Mell <zraexy@gmail.com>";

View File

@ -1,2 +1,2 @@
# Expose the minimum required version for evaluating Nixpkgs
"1.10"
"1.11"

View File

@ -543,6 +543,10 @@ rec {
# Cavium ThunderX stuff.
PCI_HOST_THUNDER_ECAM y
# The default (=y) forces us to have the XHCI firmware available in initrd,
# which our initrd builder can't currently do easily.
USB_XHCI_TEGRA m
'';
uboot = null;
kernelTarget = "Image";

View File

@ -2,11 +2,11 @@
set -o pipefail
GNOME_FTP="ftp.gnome.org/pub/GNOME/sources"
GNOME_FTP=ftp.gnome.org/pub/GNOME/sources
# projects that don't follow the GNOME major versioning, or that we don't want to
# programmatically update
NO_GNOME_MAJOR="gtkhtml gdm"
NO_GNOME_MAJOR="ghex gtkhtml gdm"
usage() {
echo "Usage: $0 gnome_dir <show project>|<update project>|<update-all> [major.minor]" >&2
@ -18,10 +18,10 @@ if [ "$#" -lt 2 ]; then
usage
fi
GNOME_TOP="$1"
GNOME_TOP=$1
shift
action="$1"
action=$1
# curl -l ftp://... doesn't work from my office in HSE, and I don't want to have
# any conversations with sysadmin. Somehow lftp works.
@ -36,18 +36,18 @@ else
fi
find_project() {
exec find "$GNOME_TOP" -mindepth 2 -maxdepth 2 -type d $@
exec find "$GNOME_TOP" -mindepth 2 -maxdepth 2 -type d "$@"
}
show_project() {
local project="$1"
local majorVersion="$2"
local version=""
local project=$1
local majorVersion=$2
local version=
if [ -z "$majorVersion" ]; then
echo "Looking for available versions..." >&2
local available_baseversions=( `ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n` )
if [ "$?" -ne "0" ]; then
local available_baseversions=$(ls_ftp ftp://${GNOME_FTP}/${project} | grep '[0-9]\.[0-9]' | sort -t. -k1,1n -k 2,2n)
if [ "$?" -ne 0 ]; then
echo "Project $project not found" >&2
return 1
fi
@ -59,11 +59,11 @@ show_project() {
if echo "$majorVersion" | grep -q "[0-9]\+\.[0-9]\+\.[0-9]\+"; then
# not a major version
version="$majorVersion"
version=$majorVersion
majorVersion=$(echo "$majorVersion" | cut -d '.' -f 1,2)
fi
local FTPDIR="${GNOME_FTP}/${project}/${majorVersion}"
local FTPDIR=${GNOME_FTP}/${project}/${majorVersion}
#version=`curl -l ${FTPDIR}/ 2>/dev/null | grep LATEST-IS | sed -e s/LATEST-IS-//`
# gnome's LATEST-IS is broken. Do not trust it.
@ -92,7 +92,7 @@ show_project() {
esac
done
echo "Found versions ${!versions[@]}" >&2
version=`echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1`
version=$(echo ${!versions[@]} | sed -e 's/ /\n/g' | sort -t. -k1,1n -k 2,2n -k 3,3n | tail -n1)
if [ -z "$version" ]; then
echo "No version available for major $majorVersion" >&2
return 1
@ -103,7 +103,7 @@ show_project() {
local name=${project}-${version}
echo "Fetching .sha256 file" >&2
local sha256out=$(curl -s -f http://${FTPDIR}/${name}.sha256sum)
local sha256out=$(curl -s -f http://"${FTPDIR}"/"${name}".sha256sum)
if [ "$?" -ne "0" ]; then
echo "Version not found" >&2
@ -136,8 +136,8 @@ fetchurl: {
}
update_project() {
local project="$1"
local majorVersion="$2"
local project=$1
local majorVersion=$2
# find project in nixpkgs tree
projectPath=$(find_project -name "$project" -print)
@ -150,14 +150,14 @@ update_project() {
if [ "$?" -eq "0" ]; then
echo "Updating $projectPath/src.nix" >&2
echo -e "$src" > "$projectPath/src.nix"
echo -e "$src" > "$projectPath"/src.nix
fi
return 0
}
if [ "$action" == "update-all" ]; then
majorVersion="$2"
if [ "$action" = "update-all" ]; then
majorVersion=$2
if [ -z "$majorVersion" ]; then
echo "No major version specified" >&2
usage
@ -170,23 +170,23 @@ if [ "$action" == "update-all" ]; then
echo "Skipping $project"
else
echo "= Updating $project to $majorVersion" >&2
update_project $project $majorVersion
update_project "$project" "$majorVersion"
echo >&2
fi
done
else
project="$2"
majorVersion="$3"
project=$2
majorVersion=$3
if [ -z "$project" ]; then
echo "No project specified, exiting" >&2
usage
fi
if [ "$action" == "show" ]; then
show_project $project $majorVersion
elif [ "$action" == "update" ]; then
update_project $project $majorVersion
if [ "$action" = show ]; then
show_project "$project" "$majorVersion"
elif [ "$action" = update ]; then
update_project "$project" "$majorVersion"
else
echo "Unknown action $action" >&2
usage

View File

@ -53,8 +53,8 @@ while test -n "$1"; do
nox)
echo "=== Fetching Nox from binary cache"
# build nox silently so it's not in the log
nix-build "<nixpkgs>" -A nox -A stdenv
# build nox (+ a basic nix-shell env) silently so it's not in the log
nix-shell -p nox stdenv --command true
;;
pr)

View File

@ -91,6 +91,7 @@ def _get_latest_version_pypi(package, extension):
if release['filename'].endswith(extension):
# TODO: In case of wheel we need to do further checks!
sha256 = release['digests']['sha256']
break
else:
sha256 = None
return version, sha256

View File

@ -11,7 +11,7 @@ a USB stick. You can use the <command>dd</command> utility to write the image:
<command>dd if=<replaceable>path-to-image</replaceable>
of=<replaceable>/dev/sdb</replaceable></command>. Be careful about specifying the
correct drive; you can use the <command>lsblk</command> command to get a list of
block devices. If you're on OS X you can run <command>diskutil list</command>
block devices. If you're on macOS you can run <command>diskutil list</command>
to see the list of devices; the device you'll use for the USB must be ejected
before writing the image.</para>

View File

@ -17,11 +17,16 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-option</command>
<arg choice='plain'><replaceable>option.name</replaceable></arg>
<arg>
<option>-I</option>
<replaceable>path</replaceable>
</arg>
<arg><option>--verbose</option></arg>
<arg><option>--xml</option></arg>
<arg choice="plain"><replaceable>option.name</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>This command evaluates the configuration specified in
@ -33,6 +38,45 @@ attributes contained in the attribute set.</para>
</refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>-I</option> <replaceable>path</replaceable></term>
<listitem>
<para>
This option is passed to the underlying
<command>nix-instantiate</command> invocation.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--verbose</option></term>
<listitem>
<para>
This option enables verbose mode, which currently is just
the Bash <command>set</command> <option>-x</option> debug mode.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--xml</option></term>
<listitem>
<para>
This option causes the output to be rendered as XML.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Environment</title>
<variablelist>

View File

@ -18,7 +18,7 @@
<para>If you encounter problems, please report them on the
<literal
xlink:href="http://lists.science.uu.nl/mailman/listinfo/nix-dev">nix-dev@lists.science.uu.nl</literal>
xlink:href="https://groups.google.com/forum/#!forum/nix-devel">nix-devel</literal>
mailing list or on the <link
xlink:href="irc://irc.freenode.net/#nixos">
<literal>#nixos</literal> channel on Freenode</link>. Bugs should

View File

@ -28,7 +28,7 @@ has the following highlights:</para>
since version 0.0 as well as the most recent <link
xlink:href="http://www.stackage.org/">Stackage Nightly</link>
snapshot. The announcement <link
xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2015-September/018138.html">&quot;Full
xlink:href="https://nixos.org/nix-dev/2015-September/018138.html">&quot;Full
Stackage Support in Nixpkgs&quot;</link> gives additional
details.</para>
</listitem>

View File

@ -78,13 +78,13 @@ following incompatible changes:</para>
our package set it loosely based on the latest available LTS release, i.e.
LTS 7.x at the time of this writing. New releases of NixOS and Nixpkgs will
drop those old names entirely. <link
xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2016-June/020585.html">The
xlink:href="https://nixos.org/nix-dev/2016-June/020585.html">The
motivation for this change</link> has been discussed at length on the
<literal>nix-dev</literal> mailing list and in <link
xlink:href="https://github.com/NixOS/nixpkgs/issues/14897">Github issue
#14897</link>. Development strategies for Haskell hackers who want to rely
on Nix and NixOS have been described in <link
xlink:href="http://lists.science.uu.nl/pipermail/nix-dev/2016-June/020642.html">another
xlink:href="https://nixos.org/nix-dev/2016-June/020642.html">another
nix-dev article</link>.</para>
</listitem>

View File

@ -85,6 +85,10 @@ rmdir /var/lib/ipfs/.ipfs
</para>
</listitem>
<listitem>
<para>
The following changes apply if the <literal>stateVersion</literal> is changed to 17.09 or higher.
For <literal>stateVersion = "17.03</literal> or lower the old behavior is preserved.
</para>
<para>
The <literal>postgres</literal> default version was changed from 9.5 to 9.6.
</para>
@ -94,6 +98,9 @@ rmdir /var/lib/ipfs/.ipfs
<para>
The <literal>postgres</literal> default <literal>dataDir</literal> has changed from <literal>/var/db/postgres</literal> to <literal>/var/lib/postgresql/$psqlSchema</literal> where $psqlSchema is 9.6 for example.
</para>
<para>
The <literal>mysql</literal> default <literal>dataDir</literal> has changed from <literal>/var/mysql</literal> to <literal>/var/lib/mysql</literal>.
</para>
</listitem>
<listitem>
<para>
@ -113,9 +120,50 @@ rmdir /var/lib/ipfs/.ipfs
also serve as a SSH agent if <literal>enableSSHSupport</literal> is set.
</para>
</listitem>
<listitem>
<para>
The <literal>services.tinc.networks.&lt;name&gt;.listenAddress</literal>
option had a misleading name that did not correspond to its behavior. It
now correctly defines the ip to listen for incoming connections on. To
keep the previous behaviour, use
<literal>services.tinc.networks.&lt;name&gt;.bindToAddress</literal>
instead. Refer to the description of the options for more details.
</para>
</listitem>
<listitem>
<para>
<literal>tlsdate</literal> package and module were removed. This is due to the project
being dead and not building with openssl 1.1.
</para>
</listitem>
<listitem>
<para>
<literal>wvdial</literal> package and module were removed. This is due to the project
being dead and not building with openssl 1.1.
</para>
</listitem>
<listitem>
<para>
<literal>cc-wrapper</literal>'s setup-hook now exports a number of
environment variables corresponding to binutils binaries,
(e.g. <envar>LD</envar>, <envar>STRIP</envar>, <envar>RANLIB</envar>,
etc). This is done to prevent packages' build systems guessing, which is
harder to predict, especially when cross-compiling. However, some packages
have broken due to this—their build systems either not supporting, or
claiming to support without adequate testing, taking such environment
variables as parameters.
</para>
</listitem>
<listitem>
<para>
<literal>services.firefox.syncserver</literal> now runs by default as a
non-root user. To accomodate this change, the default sqlite database
location has also been changed. Migration should work automatically.
Refer to the description of the options for more details.
</para>
</listitem>
</itemizedlist>
<para>Other notable improvements:</para>
<itemizedlist>
@ -141,6 +189,32 @@ rmdir /var/lib/ipfs/.ipfs
module where user Fontconfig settings are available.
</para>
</listitem>
<listitem>
<para>
ZFS/SPL have been updated to 0.7.0, <literal>zfsUnstable, splUnstable</literal>
have therefore been removed.
</para>
</listitem>
<listitem>
<para>
The <option>time.timeZone</option> option now allows the value
<literal>null</literal> in addition to timezone strings. This value
allows changing the timezone of a system imperatively using
<command>timedatectl set-timezone</command>. The default timezone
is still UTC.
</para>
</listitem>
<listitem>
<para>
Nixpkgs overlays may now be specified with a file as well as a directory. The
value of <literal>&lt;nixpkgs-overlays></literal> may be a file, and
<filename>~/.config/nixpkgs/overlays.nix</filename> can be used instead of the
<filename>~/.config/nixpkgs/overalys</filename> directory.
</para>
<para>
See the overlays chapter of the Nixpkgs manual for more details.
</para>
</listitem>
</itemizedlist>

View File

@ -39,6 +39,12 @@
with lib;
let
extensions = {
qcow2 = "qcow2";
vpc = "vhd";
raw = "img";
};
# Copied from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/cd-dvd/channel.nix
# TODO: factor out more cleanly
@ -142,8 +148,8 @@ in pkgs.vmTools.runInLinuxVM (
mv $diskImage $out/nixos.img
diskImage=$out/nixos.img
'' else ''
${pkgs.qemu}/bin/qemu-img convert -f raw -O qcow2 $diskImage $out/nixos.qcow2
diskImage=$out/nixos.qcow2
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${format} $diskImage $out/nixos.${extensions.${format}}
diskImage=$out/nixos.${extensions.${format}}
''}
${postVM}
'';

View File

@ -33,7 +33,7 @@ pkgs.stdenv.mkDerivation {
echo "Creating an EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
truncate -s $bytes $out
faketime "1970-01-01 00:00:00" mkfs.ext4 -L ${volumeLabel} -U 44444444-4444-4444-8888-888888888888 $out
faketime -f "1970-01-01 00:00:01" mkfs.ext4 -L ${volumeLabel} -U 44444444-4444-4444-8888-888888888888 $out
# Populate the image contents by piping a bunch of commands to the `debugfs` tool from e2fsprogs.
# For example, to copy /nix/store/abcd...efg-coreutils-8.23/bin/sleep:
@ -76,7 +76,7 @@ pkgs.stdenv.mkDerivation {
echo sif $file gid 30000 # chgrp to nixbld
done
) | faketime "1970-01-01 00:00:00" debugfs -w $out -f /dev/stdin > errorlog 2>&1
) | faketime -f "1970-01-01 00:00:01" debugfs -w $out -f /dev/stdin > errorlog 2>&1
# The debugfs tool doesn't terminate on error nor exit with a non-zero status. Check manually.
if egrep -q 'Could not allocate|File not found' errorlog; then

View File

@ -22,15 +22,26 @@ in {
generated image. Glob patterns work.
'';
};
sizeMB = mkOption {
type = types.int;
default = if config.ec2.hvm then 2048 else 8192;
description = "The size in MB of the image";
};
format = mkOption {
type = types.enum [ "raw" "qcow2" "vpc" ];
default = "qcow2";
description = "The image format to output";
};
};
config.system.build.amazonImage = import ../../../lib/make-disk-image.nix {
inherit lib config;
inherit (cfg) contents;
inherit (cfg) contents format;
pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
partitioned = config.ec2.hvm;
diskSize = if config.ec2.hvm then 2048 else 8192;
format = "qcow2";
diskSize = cfg.sizeMB;
configFile = pkgs.writeText "configuration.nix"
''
{
@ -41,5 +52,4 @@ in {
}
'';
};
}

View File

@ -19,7 +19,6 @@ let
bind_policy ${config.users.ldap.bind.policy}
${optionalString config.users.ldap.useTLS ''
ssl start_tls
tls_checkpeer no
''}
${optionalString (config.users.ldap.bind.distinguishedName != "") ''
binddn ${config.users.ldap.bind.distinguishedName}

View File

@ -20,12 +20,26 @@ in
options = {
networking.hosts = lib.mkOption {
type = types.attrsOf ( types.listOf types.str );
default = {};
example = literalExample ''
{
"127.0.0.1" = [ "foo.bar.baz" ];
"192.168.0.2" = [ "fileserver.local" "nameserver.local" ];
};
'';
description = ''
Locally defined maps of hostnames to IP addresses.
'';
};
networking.extraHosts = lib.mkOption {
type = types.lines;
default = "";
example = "192.168.0.1 lanlocalhost";
description = ''
Additional entries to be appended to <filename>/etc/hosts</filename>.
Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
'';
};
@ -188,11 +202,22 @@ in
# /etc/hosts: Hostname-to-IP mappings.
"hosts".text =
let oneToString = set : ip : ip + " " + concatStringsSep " " ( getAttr ip set );
allToString = set : concatMapStringsSep "\n" ( oneToString set ) ( attrNames set );
userLocalHosts = optionalString
( builtins.hasAttr "127.0.0.1" cfg.hosts )
( concatStringsSep " " ( remove "localhost" cfg.hosts."127.0.0.1" ));
userLocalHosts6 = optionalString
( builtins.hasAttr "::1" cfg.hosts )
( concatStringsSep " " ( remove "localhost" cfg.hosts."::1" ));
otherHosts = allToString ( removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]);
in
''
127.0.0.1 localhost
127.0.0.1 ${userLocalHosts} localhost
${optionalString cfg.enableIPv6 ''
::1 localhost
::1 ${userLocalHosts6} localhost
''}
${otherHosts}
${cfg.extraHosts}
'';
@ -223,7 +248,9 @@ in
'';
} // optionalAttrs config.services.resolved.enable {
"resolv.conf".source = "/run/systemd/resolve/resolv.conf";
# symlink the static version of resolv.conf as recommended by upstream:
# https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf
"resolv.conf".source = "${pkgs.systemd}/lib/systemd/resolv.conf";
} // optionalAttrs (config.services.resolved.enable && dnsmasqResolve) {
"dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
};

View File

@ -26,7 +26,15 @@ with lib;
fonts.fontconfig.enable = false;
nixpkgs.config.packageOverrides = pkgs:
{ dbus = pkgs.dbus.override { x11Support = false; }; };
nixpkgs.config.packageOverrides = pkgs: {
dbus = pkgs.dbus.override { x11Support = false; };
networkmanager_fortisslvpn = pkgs.networkmanager_fortisslvpn.override { withGnome = false; };
networkmanager_l2tp = pkgs.networkmanager_l2tp.override { withGnome = false; };
networkmanager_openconnect = pkgs.networkmanager_openconnect.override { withGnome = false; };
networkmanager_openvpn = pkgs.networkmanager_openvpn.override { withGnome = false; };
networkmanager_pptp = pkgs.networkmanager_pptp.override { withGnome = false; };
networkmanager_vpnc = pkgs.networkmanager_vpnc.override { withGnome = false; };
pinentry = pkgs.pinentry.override { gtk2 = null; qt4 = null; };
};
};
}

View File

@ -28,7 +28,8 @@ let
passwdArray = [ "files" ]
++ optional sssd "sss"
++ optionals ldap [ "ldap" ]
++ optionals mymachines [ "mymachines" ];
++ optionals mymachines [ "mymachines" ]
++ [ "systemd" ];
shadowArray = [ "files" ]
++ optional sssd "sss"

View File

@ -6,6 +6,7 @@ with lib;
let
cfg = config.hardware.pulseaudio;
alsaCfg = config.sound;
systemWide = cfg.enable && cfg.systemWide;
nonSystemWide = cfg.enable && !cfg.systemWide;
@ -76,6 +77,7 @@ let
ctl.!default {
type pulse
}
${alsaCfg.extraConfig}
'');
in {
@ -222,7 +224,7 @@ in {
# Allow PulseAudio to get realtime priority using rtkit.
security.rtkit.enable = true;
systemd.packages = [ cfg.package ];
systemd.packages = [ overriddenPackage ];
})
(mkIf hasZeroconf {

View File

@ -5,6 +5,52 @@ with lib;
let
randomEncryptionCoerce = enable: { inherit enable; };
randomEncryptionOpts = { ... }: {
options = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Encrypt swap device with a random key. This way you won't have a persistent swap device.
WARNING: Don't try to hibernate when you have at least one swap partition with
this option enabled! We have no way to set the partition into which hibernation image
is saved, so if your image ends up on an encrypted one you would lose it!
WARNING #2: Do not use /dev/disk/by-uuid/… or /dev/disk/by-label/… as your swap device
when using randomEncryption as the UUIDs and labels will get erased on every boot when
the partition is encrypted. Best to use /dev/disk/by-partuuid/
'';
};
cipher = mkOption {
default = "aes-xts-plain64";
example = "serpent-xts-plain64";
type = types.str;
description = ''
Use specified cipher for randomEncryption.
Hint: Run "cryptsetup benchmark" to see which one is fastest on your machine.
'';
};
source = mkOption {
default = "/dev/urandom";
example = "/dev/random";
type = types.str;
description = ''
Define the source of randomness to obtain a random key for encryption.
'';
};
};
};
swapCfg = {config, options, ...}: {
options = {
@ -47,10 +93,17 @@ let
randomEncryption = mkOption {
default = false;
type = types.bool;
example = {
enable = true;
cipher = "serpent-xts-plain64";
source = "/dev/random";
};
type = types.coercedTo types.bool randomEncryptionCoerce (types.submodule randomEncryptionOpts);
description = ''
Encrypt swap device with a random key. This way you won't have a persistent swap device.
HINT: run "cryptsetup benchmark" to test cipher performance on your machine.
WARNING: Don't try to hibernate when you have at least one swap partition with
this option enabled! We have no way to set the partition into which hibernation image
is saved, so if your image ends up on an encrypted one you would lose it!
@ -77,7 +130,7 @@ let
device = mkIf options.label.isDefined
"/dev/disk/by-label/${config.label}";
deviceName = lib.replaceChars ["\\"] [""] (escapeSystemdPath config.device);
realDevice = if config.randomEncryption then "/dev/mapper/${deviceName}" else config.device;
realDevice = if config.randomEncryption.enable then "/dev/mapper/${deviceName}" else config.device;
};
};
@ -125,14 +178,14 @@ in
createSwapDevice = sw:
assert sw.device != "";
assert !(sw.randomEncryption && lib.hasPrefix "/dev/disk/by-uuid" sw.device);
assert !(sw.randomEncryption && lib.hasPrefix "/dev/disk/by-label" sw.device);
assert !(sw.randomEncryption.enable && lib.hasPrefix "/dev/disk/by-uuid" sw.device);
assert !(sw.randomEncryption.enable && lib.hasPrefix "/dev/disk/by-label" sw.device);
let realDevice' = escapeSystemdPath sw.realDevice;
in nameValuePair "mkswap-${sw.deviceName}"
{ description = "Initialisation of swap device ${sw.device}";
wantedBy = [ "${realDevice'}.swap" ];
before = [ "${realDevice'}.swap" ];
path = [ pkgs.utillinux ] ++ optional sw.randomEncryption pkgs.cryptsetup;
path = [ pkgs.utillinux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup;
script =
''
@ -145,13 +198,11 @@ in
truncate --size "${toString sw.size}M" "${sw.device}"
fi
chmod 0600 ${sw.device}
${optionalString (!sw.randomEncryption) "mkswap ${sw.realDevice}"}
${optionalString (!sw.randomEncryption.enable) "mkswap ${sw.realDevice}"}
fi
''}
${optionalString sw.randomEncryption ''
echo "secretkey" | cryptsetup luksFormat --batch-mode ${sw.device}
echo "secretkey" | cryptsetup luksOpen ${sw.device} ${sw.deviceName}
cryptsetup luksErase --batch-mode ${sw.device}
${optionalString sw.randomEncryption.enable ''
cryptsetup plainOpen -c ${sw.randomEncryption.cipher} -d ${sw.randomEncryption.source} ${sw.device} ${sw.deviceName}
mkswap ${sw.realDevice}
''}
'';
@ -159,12 +210,12 @@ in
unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
unitConfig.DefaultDependencies = false; # needed to prevent a cycle
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = sw.randomEncryption;
serviceConfig.ExecStop = optionalString sw.randomEncryption "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
serviceConfig.RemainAfterExit = sw.randomEncryption.enable;
serviceConfig.ExecStop = optionalString sw.randomEncryption.enable "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
restartIfChanged = false;
};
in listToAttrs (map createSwapDevice (filter (sw: sw.size != null || sw.randomEncryption) config.swapDevices));
in listToAttrs (map createSwapDevice (filter (sw: sw.size != null || sw.randomEncryption.enable) config.swapDevices));
};

View File

@ -118,6 +118,9 @@ in
"/share/themes"
"/share/vim-plugins"
"/share/vulkan"
"/share/kservices5"
"/share/kservicetypes5"
"/share/kxmlgui5"
];
system.path = pkgs.buildEnv {

View File

@ -14,13 +14,16 @@ in
time = {
timeZone = mkOption {
default = "UTC";
type = types.str;
default = null;
type = types.nullOr types.str;
example = "America/New_York";
description = ''
The time zone used when displaying times and dates. See <link
xlink:href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"/>
for a comprehensive list of possible values for this setting.
If null, the timezone will default to UTC and can be set imperatively
using timedatectl.
'';
};
@ -40,13 +43,14 @@ in
# This way services are restarted when tzdata changes.
systemd.globalEnvironment.TZDIR = tzdir;
environment.etc.localtime =
{ source = "/etc/zoneinfo/${config.time.timeZone}";
mode = "direct-symlink";
systemd.services.systemd-timedated.environment = lib.optionalAttrs (config.time.timeZone != null) { NIXOS_STATIC_TIMEZONE = "1"; };
environment.etc = {
zoneinfo.source = tzdir;
} // lib.optionalAttrs (config.time.timeZone != null) {
localtime.source = "/etc/zoneinfo/${config.time.timeZone}";
localtime.mode = "direct-symlink";
};
environment.etc.zoneinfo.source = tzdir;
};
}

View File

@ -527,7 +527,7 @@ in {
input.gid = ids.gids.input;
};
system.activationScripts.users = stringAfter [ "etc" ]
system.activationScripts.users = stringAfter [ "stdio" ]
''
${pkgs.perl}/bin/perl -w \
-I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl \

View File

@ -3,7 +3,7 @@
with lib;
{
meta.maintainers = [ maintainers.grahamc ];
meta.maintainers = with maintainers; [ grahamc ];
options = {
hardware.mcelog = {
@ -19,19 +19,17 @@ with lib;
};
config = mkIf config.hardware.mcelog.enable {
systemd.services.mcelog = {
description = "Machine Check Exception Logging Daemon";
wantedBy = [ "multi-user.target" ];
systemd = {
packages = [ pkgs.mcelog ];
serviceConfig = {
ExecStart = "${pkgs.mcelog}/bin/mcelog --daemon --foreground";
SuccessExitStatus = [ 0 15 ];
ProtectHome = true;
PrivateNetwork = true;
PrivateTmp = true;
services.mcelog = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ProtectHome = true;
PrivateNetwork = true;
PrivateTmp = true;
};
};
};
};
}

View File

@ -1,5 +1,5 @@
{
x86_64-linux = "/nix/store/crqd5wmrqipl4n1fcm5kkc1zg4sj80js-nix-1.11.11";
i686-linux = "/nix/store/wsjn14xp5ja509d4dxb1c78zhirw0b5x-nix-1.11.11";
x86_64-darwin = "/nix/store/zqkqnhk85g2shxlpb04y72h1i3db3gpl-nix-1.11.11";
x86_64-linux = "/nix/store/avwiw7hb1qckag864sc6ixfxr8qmf94w-nix-1.11.13";
i686-linux = "/nix/store/8wv3ms0afw95hzsz4lxzv0nj4w3614z9-nix-1.11.13";
x86_64-darwin = "/nix/store/z21lvakv1l7lhasmv5fvaz8mlzxia8k9-nix-1.11.13";
}

View File

@ -140,7 +140,7 @@ channel_closure="$tmpdir/channel.closure"
nix-store --export $channel_root > $channel_closure
# Populate the target root directory with the basics
@prepare_root@/bin/nixos-prepare-root $mountPoint $channel_root $system_root @nixClosure@ $system_closure $channel_closure
@prepare_root@/bin/nixos-prepare-root "$mountPoint" "$channel_root" "$system_root" @nixClosure@ "$system_closure" "$channel_closure"
# nixos-prepare-root doesn't currently do anything with file ownership, so we set it up here instead
chown @root_uid@:@nixbld_gid@ $mountPoint/nix/store

View File

@ -139,6 +139,7 @@
btsync = 113;
minecraft = 114;
#monetdb = 115; # unused (not packaged), removed 2016-09-19
vault = 115;
rippled = 116;
murmur = 117;
foundationdb = 118;
@ -213,7 +214,7 @@
plex = 193;
grafana = 196;
skydns = 197;
ripple-rest = 198;
# ripple-rest = 198; # unused, removed 2017-08-12
nix-serve = 199;
tvheadend = 200;
uwsgi = 201;
@ -334,7 +335,7 @@
dialout = 27;
#polkituser = 28; # currently unused, polkitd doesn't need a group
utmp = 29;
#ddclient = 30; # unused
ddclient = 30;
davfs2 = 31;
disnix = 33;
osgi = 34;
@ -415,6 +416,7 @@
btsync = 113;
#minecraft = 114; # unused
#monetdb = 115; # unused (not packaged), removed 2016-09-19
vault = 115;
#ripped = 116; # unused
#murmur = 117; # unused
foundationdb = 118;
@ -487,7 +489,7 @@
sabnzbd = 194;
#grafana = 196; #unused
#skydns = 197; #unused
#ripple-rest = 198; #unused
# ripple-rest = 198; # unused, removed 2017-08-12
#nix-serve = 199; #unused
#tvheadend = 200; #unused
uwsgi = 201;

View File

@ -105,7 +105,6 @@
./programs/venus.nix
./programs/vim.nix
./programs/wireshark.nix
./programs/wvdial.nix
./programs/xfs_quota.nix
./programs/xonsh.nix
./programs/zsh/oh-my-zsh.nix
@ -166,6 +165,7 @@
./services/continuous-integration/buildbot/master.nix
./services/continuous-integration/buildbot/worker.nix
./services/continuous-integration/buildkite-agent.nix
./services/continuous-integration/hail.nix
./services/continuous-integration/hydra/default.nix
./services/continuous-integration/gitlab-runner.nix
./services/continuous-integration/gocd-agent/default.nix
@ -186,6 +186,7 @@
./services/databases/neo4j.nix
./services/databases/openldap.nix
./services/databases/opentsdb.nix
./services/databases/postage.nix
./services/databases/postgresql.nix
./services/databases/redis.nix
./services/databases/riak.nix
@ -243,6 +244,7 @@
./services/logging/graylog.nix
./services/logging/heartbeat.nix
./services/logging/journalbeat.nix
./services/logging/journalwatch.nix
./services/logging/klogd.nix
./services/logging/logcheck.nix
./services/logging/logrotate.nix
@ -267,6 +269,7 @@
./services/mail/rspamd.nix
./services/mail/rmilter.nix
./services/mail/nullmailer.nix
./services/misc/airsonic.nix
./services/misc/apache-kafka.nix
./services/misc/autofs.nix
./services/misc/autorandr.nix
@ -286,6 +289,7 @@
./services/misc/emby.nix
./services/misc/errbot.nix
./services/misc/etcd.nix
./services/misc/exhibitor.nix
./services/misc/felix.nix
./services/misc/folding-at-home.nix
./services/misc/fstrim.nix
@ -322,10 +326,10 @@
./services/misc/radarr.nix
./services/misc/redmine.nix
./services/misc/rippled.nix
./services/misc/ripple-rest.nix
./services/misc/ripple-data-api.nix
./services/misc/rogue.nix
./services/misc/siproxd.nix
./services/misc/snapper.nix
./services/misc/sonarr.nix
./services/misc/spice-vdagentd.nix
./services/misc/ssm-agent.nix
@ -353,6 +357,7 @@
./services/monitoring/munin.nix
./services/monitoring/nagios.nix
./services/monitoring/netdata.nix
./services/monitoring/osquery.nix
./services/monitoring/prometheus/default.nix
./services/monitoring/prometheus/alertmanager.nix
./services/monitoring/prometheus/blackbox-exporter.nix
@ -513,7 +518,6 @@
./services/networking/teamspeak3.nix
./services/networking/tinc.nix
./services/networking/tftpd.nix
./services/networking/tlsdated.nix
./services/networking/tox-bootstrapd.nix
./services/networking/toxvpn.nix
./services/networking/tvheadend.nix
@ -554,16 +558,20 @@
./services/security/oauth2_proxy.nix
./services/security/physlock.nix
./services/security/shibboleth-sp.nix
./services/security/sks.nix
./services/security/sshguard.nix
./services/security/tor.nix
./services/security/torify.nix
./services/security/torsocks.nix
./services/security/usbguard.nix
./services/security/vault.nix
./services/system/cgmanager.nix
./services/system/cloud-init.nix
./services/system/dbus.nix
./services/system/earlyoom.nix
./services/system/kerberos.nix
./services/system/nscd.nix
./services/system/saslauthd.nix
./services/system/uptimed.nix
./services/torrent/deluge.nix
./services/torrent/flexget.nix
@ -579,6 +587,7 @@
./services/web-apps/frab.nix
./services/web-apps/mattermost.nix
./services/web-apps/nixbot.nix
./services/web-apps/pgpkeyserver-lite.nix
./services/web-apps/piwik.nix
./services/web-apps/pump.io.nix
./services/web-apps/tt-rss.nix

View File

@ -41,6 +41,9 @@
# Virtio (QEMU, KVM etc.) support.
"virtio_net" "virtio_pci" "virtio_blk" "virtio_scsi" "virtio_balloon" "virtio_console"
# VMware support.
"mptspi" "vmw_balloon" "vmwgfx" "vmw_vmci" "vmw_vsock_vmci_transport" "vmxnet3" "vsock"
# Hyper-V support.
"hv_storvsc"

View File

@ -59,4 +59,10 @@ with lib;
# the feature at runtime. Attempting to create a user namespace
# with unshare will then fail with "no space left on device".
boot.kernel.sysctl."user.max_user_namespaces" = mkDefault 0;
# Raise ASLR entropy for 64bit & 32bit, respectively.
#
# Note: mmap_rnd_compat_bits may not exist on 64bit.
boot.kernel.sysctl."vm.mmap_rnd_bits" = mkDefault 32;
boot.kernel.sysctl."vm.mmap_rnd_compat_bits" = mkDefault 16;
}

View File

@ -55,79 +55,24 @@ in
};
config = mkIf cfg.agent.enable {
systemd.user.services.gpg-agent = {
serviceConfig = {
ExecStart = [
""
("${pkgs.gnupg}/bin/gpg-agent --supervised "
+ optionalString cfg.agent.enableSSHSupport "--enable-ssh-support")
];
ExecReload = "${pkgs.gnupg}/bin/gpgconf --reload gpg-agent";
};
};
systemd.user.sockets.gpg-agent = {
wantedBy = [ "sockets.target" ];
listenStreams = [ "%t/gnupg/S.gpg-agent" ];
socketConfig = {
FileDescriptorName = "std";
SocketMode = "0600";
DirectoryMode = "0700";
};
};
systemd.user.sockets.gpg-agent-ssh = mkIf cfg.agent.enableSSHSupport {
wantedBy = [ "sockets.target" ];
listenStreams = [ "%t/gnupg/S.gpg-agent.ssh" ];
socketConfig = {
FileDescriptorName = "ssh";
Service = "gpg-agent.service";
SocketMode = "0600";
DirectoryMode = "0700";
};
};
systemd.user.sockets.gpg-agent-extra = mkIf cfg.agent.enableExtraSocket {
wantedBy = [ "sockets.target" ];
listenStreams = [ "%t/gnupg/S.gpg-agent.extra" ];
socketConfig = {
FileDescriptorName = "extra";
Service = "gpg-agent.service";
SocketMode = "0600";
DirectoryMode = "0700";
};
};
systemd.user.sockets.gpg-agent-browser = mkIf cfg.agent.enableBrowserSocket {
wantedBy = [ "sockets.target" ];
listenStreams = [ "%t/gnupg/S.gpg-agent.browser" ];
socketConfig = {
FileDescriptorName = "browser";
Service = "gpg-agent.service";
SocketMode = "0600";
DirectoryMode = "0700";
};
};
systemd.user.services.dirmngr = {
requires = [ "dirmngr.socket" ];
after = [ "dirmngr.socket" ];
unitConfig = {
RefuseManualStart = "true";
};
serviceConfig = {
ExecStart = "${pkgs.gnupg}/bin/dirmngr --supervised";
ExecReload = "${pkgs.gnupg}/bin/gpgconf --reload dirmngr";
};
};
systemd.user.sockets.dirmngr = {
systemd.user.sockets.dirmngr = mkIf cfg.dirmngr.enable {
wantedBy = [ "sockets.target" ];
listenStreams = [ "%t/gnupg/S.dirmngr" ];
socketConfig = {
SocketMode = "0600";
DirectoryMode = "0700";
};
};
systemd.packages = [ pkgs.gnupg ];
@ -147,7 +92,7 @@ in
'');
assertions = [
{ assertion = cfg.agent.enableSSHSupport && !config.programs.ssh.startAgent;
{ assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
message = "You can't use ssh-agent and GnuPG agent with SSH support enabled at the same time!";
}
];

View File

@ -27,6 +27,7 @@ in
type = types.int;
default = 70;
description = ''
Opacity percentage of Cairo rendered backgrounds.
'';
};
@ -34,6 +35,7 @@ in
type = types.str;
default = "black";
description = ''
Colour name or hex code (#ffffff) of the background color.
'';
};
@ -41,6 +43,9 @@ in
type = types.str;
default = "simplistic";
description = ''
Icon theme for the buttons, must be in the themes folder of
the package, or in
<filename>~/.themes/&lt;name&gt;/oblogout/</filename>.
'';
};
@ -48,6 +53,7 @@ in
type = types.str;
default = "cancel, logout, restart, shutdown, suspend, hibernate";
description = ''
List and order of buttons to show.
'';
};
@ -55,6 +61,7 @@ in
type = types.str;
default = "Escape";
description = ''
Cancel logout/shutdown shortcut.
'';
};
@ -62,6 +69,7 @@ in
type = types.str;
default = "S";
description = ''
Shutdown shortcut.
'';
};
@ -69,6 +77,7 @@ in
type = types.str;
default = "R";
description = ''
Restart shortcut.
'';
};
@ -76,6 +85,7 @@ in
type = types.str;
default = "U";
description = ''
Suspend shortcut.
'';
};
@ -83,6 +93,7 @@ in
type = types.str;
default = "L";
description = ''
Logout shortcut.
'';
};
@ -90,6 +101,7 @@ in
type = types.str;
default = "K";
description = ''
Lock session shortcut.
'';
};
@ -97,6 +109,7 @@ in
type = types.str;
default = "H";
description = ''
Hibernate shortcut.
'';
};
@ -104,6 +117,7 @@ in
type = types.str;
default = "openbox --exit";
description = ''
Command to logout.
'';
};
@ -111,6 +125,7 @@ in
type = types.str;
default = "";
description = ''
Command to lock screen.
'';
};
@ -118,6 +133,7 @@ in
type = types.str;
default = "";
description = ''
Command to switch user.
'';
};
};

View File

@ -26,6 +26,6 @@ with lib;
###### implementation
config = mkIf config.programs.qt5ct.enable {
environment.variables.QT_QPA_PLATFORMTHEME = "qt5ct";
environment.systemPackages = [ pkgs.qt5ct ];
environment.systemPackages = with pkgs; [ qt5ct libsForQt5.qtstyleplugins ];
};
}

View File

@ -3,7 +3,12 @@
with lib;
let
cfg = config.programs.thefuck;
prg = config.programs;
cfg = prg.thefuck;
initScript = ''
eval $(${pkgs.thefuck}/bin/thefuck --alias ${cfg.alias})
'';
in
{
options = {
@ -24,8 +29,11 @@ in
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [ thefuck ];
environment.shellInit = ''
eval $(${pkgs.thefuck}/bin/thefuck --alias ${cfg.alias})
environment.shellInit = initScript;
programs.zsh.shellInit = mkIf prg.zsh.enable initScript;
programs.fish.shellInit = mkIf prg.fish.enable ''
${pkgs.thefuck}/bin/thefuck --alias | source
'';
};
}

View File

@ -1,71 +0,0 @@
# Global configuration for wvdial.
{ config, lib, pkgs, ... }:
with lib;
let
configFile = ''
[Dialer Defaults]
PPPD PATH = ${pkgs.ppp}/sbin/pppd
${config.environment.wvdial.dialerDefaults}
'';
cfg = config.environment.wvdial;
in
{
###### interface
options = {
environment.wvdial = {
dialerDefaults = mkOption {
default = "";
type = types.str;
example = ''Init1 = AT+CGDCONT=1,"IP","internet.t-mobile"'';
description = ''
Contents of the "Dialer Defaults" section of
<filename>/etc/wvdial.conf</filename>.
'';
};
pppDefaults = mkOption {
default = ''
noipdefault
usepeerdns
defaultroute
persist
noauth
'';
type = types.str;
description = "Default ppp settings for wvdial.";
};
};
};
###### implementation
config = mkIf (cfg.dialerDefaults != "") {
environment = {
etc =
[
{ source = pkgs.writeText "wvdial.conf" configFile;
target = "wvdial.conf";
}
{ source = pkgs.writeText "wvdial" cfg.pppDefaults;
target = "ppp/peers/wvdial";
}
];
};
};
}

View File

@ -15,6 +15,16 @@ in
'';
};
package = mkOption {
default = pkgs.oh-my-zsh;
defaultText = "pkgs.oh-my-zsh";
description = ''
Package to install for `oh-my-zsh` usage.
'';
type = types.package;
};
plugins = mkOption {
default = [];
type = types.listOf(types.str);
@ -46,11 +56,11 @@ in
# Prevent zsh from overwriting oh-my-zsh's prompt
programs.zsh.promptInit = mkDefault "";
environment.systemPackages = with pkgs; [ oh-my-zsh ];
environment.systemPackages = [ cfg.package ];
programs.zsh.interactiveShellInit = with pkgs; with builtins; ''
programs.zsh.interactiveShellInit = with builtins; ''
# oh-my-zsh configuration generated by NixOS
export ZSH=${oh-my-zsh}/share/oh-my-zsh
export ZSH=${cfg.package}/share/oh-my-zsh
${optionalString (length(cfg.plugins) > 0)
"plugins=(${concatStringsSep " " cfg.plugins})"

View File

@ -158,6 +158,11 @@ in
HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
# Tell zsh how to find installed completions
for p in ''${(z)NIX_PROFILES}; do
fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
done
${optionalString cfg.enableCompletion "autoload -U compinit && compinit"}
${optionalString (cfg.enableAutosuggestions)
@ -172,11 +177,6 @@ in
${cfg.promptInit}
# Tell zsh how to find installed completions
for p in ''${(z)NIX_PROFILES}; do
fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
done
# Read system-wide modifications.
if test -f /etc/zshrc.local; then
. /etc/zshrc.local

View File

@ -17,14 +17,16 @@ with lib;
(mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
(mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
(mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ])
(mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ])
(mkRenamedOptionModule [ "services" "i2pd" "extIp" ] [ "services" "i2pd" "address" ])
(mkRenamedOptionModule [ "services" "kibana" "host" ] [ "services" "kibana" "listenAddress" ])
(mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ])
(mkRenamedOptionModule [ "services" "mpd" "network" "host" ] [ "services" "mpd" "network" "listenAddress" ])
(mkRenamedOptionModule [ "services" "neo4j" "host" ] [ "services" "neo4j" "listenAddress" ])
(mkRenamedOptionModule [ "services" "shout" "host" ] [ "services" "shout" "listenAddress" ])
(mkRenamedOptionModule [ "services" "sslh" "host" ] [ "services" "sslh" "listenAddress" ])
(mkRenamedOptionModule [ "services" "statsd" "host" ] [ "services" "statsd" "listenAddress" ])
(mkRenamedOptionModule [ "services" "subsonic" "host" ] [ "services" "subsonic" "listenAddress" ])
(mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ])
(mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ])
(mkRenamedOptionModule [ "services" "gitlab" "stateDir" ] [ "services" "gitlab" "statePath" ])
@ -195,6 +197,8 @@ with lib;
(mkRemovedOptionModule [ "services" "openvpn" "enable" ] "")
(mkRemovedOptionModule [ "services" "printing" "cupsFilesConf" ] "")
(mkRemovedOptionModule [ "services" "printing" "cupsdConf" ] "")
(mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.")
(mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.")
(mkRemovedOptionModule [ "services" "xserver" "startGnuPGAgent" ]
"See the 16.09 release notes for more information.")
(mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
@ -204,6 +208,7 @@ with lib;
"Set the option `services.xserver.displayManager.sddm.package' instead.")
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
(mkRemovedOptionModule [ "boot" "zfs" "enableUnstable" ] "0.7.0 is now the default")
# ZSH
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])

View File

@ -13,6 +13,7 @@ with lib;
unitConfig = {
ConditionVirtualization = "!container";
ConditionSecurity = [ "audit" ];
DefaultDependencies = false;
};
path = [ pkgs.audit ];

View File

@ -281,7 +281,7 @@ let
"auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString cfg.enableKwallet
("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
" kwalletd=${pkgs.libsForQt5.kwallet}/bin/kwalletd5")}
" kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
'') + ''
${optionalString cfg.unixAuth
"auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
@ -350,7 +350,7 @@ let
"session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"}
${optionalString (cfg.enableKwallet)
("session optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
" kwalletd=${pkgs.libsForQt5.kwallet}/bin/kwalletd5")}
" kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
'');
};

View File

@ -7,6 +7,8 @@ let
inherit (pkgs) alsaUtils;
pulseaudioEnabled = config.hardware.pulseaudio.enable;
in
{
@ -80,7 +82,7 @@ in
environment.systemPackages = [ alsaUtils ];
environment.etc = mkIf (config.sound.extraConfig != "")
environment.etc = mkIf (!pulseaudioEnabled && config.sound.extraConfig != "")
[
{ source = pkgs.writeText "asound.conf" config.sound.extraConfig;
target = "asound.conf";

View File

@ -10,11 +10,9 @@ let
gid = config.ids.gids.mpd;
cfg = config.services.mpd;
playlistDir = "${cfg.dataDir}/playlists";
mpdConf = pkgs.writeText "mpd.conf" ''
music_directory "${cfg.musicDirectory}"
playlist_directory "${playlistDir}"
playlist_directory "${cfg.playlistDirectory}"
db_file "${cfg.dbFile}"
state_file "${cfg.dataDir}/state"
sticker_file "${cfg.dataDir}/sticker.sql"
@ -57,11 +55,21 @@ in {
musicDirectory = mkOption {
type = types.path;
default = "${cfg.dataDir}/music";
defaultText = ''''${dataDir}/music'';
description = ''
The directory where mpd reads music from.
'';
};
playlistDirectory = mkOption {
type = types.path;
default = "${cfg.dataDir}/playlists";
defaultText = ''''${dataDir}/playlists'';
description = ''
The directory where mpd stores playlists.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
@ -120,6 +128,7 @@ in {
dbFile = mkOption {
type = types.str;
default = "${cfg.dataDir}/tag_cache";
defaultText = ''''${dataDir}/tag_cache'';
description = ''
The path to MPD's database.
'';
@ -153,7 +162,7 @@ in {
preStart = ''
mkdir -p "${cfg.dataDir}" && chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}"
mkdir -p "${playlistDir}" && chown -R ${cfg.user}:${cfg.group} "${playlistDir}"
mkdir -p "${cfg.playlistDirectory}" && chown -R ${cfg.user}:${cfg.group} "${cfg.playlistDirectory}"
'';
serviceConfig = {
User = "${cfg.user}";

View File

@ -36,9 +36,9 @@ in
package = mkOption {
type = types.package;
default = pkgs.slurm-llnl;
defaultText = "pkgs.slurm-llnl";
example = literalExample "pkgs.slurm-llnl-full";
default = pkgs.slurm;
defaultText = "pkgs.slurm";
example = literalExample "pkgs.slurm-full";
description = ''
The package to use for slurm binaries.
'';

View File

@ -4,15 +4,65 @@ with lib;
let
cfg = config.services.gitlab-runner;
configFile = pkgs.writeText "config.toml" cfg.configText;
configFile =
if (cfg.configFile == null) then
(pkgs.runCommand "config.toml" {
buildInputs = [ pkgs.remarshal ];
} ''
remarshal -if json -of toml \
< ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)} \
> $out
'')
else
cfg.configFile;
hasDocker = config.virtualisation.docker.enable;
in
{
options.services.gitlab-runner = {
enable = mkEnableOption "Gitlab Runner";
configText = mkOption {
description = "Verbatim config.toml to use";
configFile = mkOption {
default = null;
description = ''
Configuration file for gitlab-runner.
Use this option in favor of configOptions to avoid placing CI tokens in the nix store.
<option>configFile</option> takes precedence over <option>configOptions</option>.
Warning: Not using <option>configFile</option> will potentially result in secrets
leaking into the WORLD-READABLE nix store.
'';
type = types.nullOr types.path;
};
configOptions = mkOption {
description = ''
Configuration for gitlab-runner
<option>configFile</option> will take precedence over this option.
Warning: all Configuration, especially CI token, will be stored in a
WORLD-READABLE file in the Nix Store.
If you want to protect your CI token use <option>configFile</option> instead.
'';
type = types.attrs;
example = {
concurrent = 2;
runners = [{
name = "docker-nix-1.11";
url = "https://CI/";
token = "TOKEN";
executor = "docker";
builds_dir = "";
docker = {
host = "";
image = "nixos/nix:1.11";
privileged = true;
disable_cache = true;
cache_dir = "";
};
}];
};
};
gracefulTermination = mkOption {

View File

@ -0,0 +1,61 @@
{ config, lib, pkgs, ...}:
with lib;
let
cfg = config.services.hail;
in {
###### interface
options.services.hail = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enables the Hail Auto Update Service. Hail can automatically deploy artifacts
built by a Hydra Continous Integration server. A common use case is to provide
continous deployment for single services or a full NixOS configuration.'';
};
profile = mkOption {
type = types.str;
default = "hail-profile";
description = "The name of the Nix profile used by Hail.";
};
hydraJobUri = mkOption {
type = types.str;
description = "The URI of the Hydra Job.";
};
netrc = mkOption {
type = types.nullOr types.path;
description = "The netrc file to use when fetching data from Hydra.";
default = null;
};
package = mkOption {
type = types.package;
default = pkgs.haskellPackages.hail;
defaultText = "pkgs.haskellPackages.hail";
description = "Hail package to use.";
};
};
###### implementation
config = mkIf cfg.enable {
systemd.services.hail = {
description = "Hail Auto Update Service";
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ nix ];
environment = {
HOME = "/var/lib/empty";
};
serviceConfig = {
ExecStart = "${cfg.package}/bin/hail --profile ${cfg.profile} --job-uri ${cfg.hydraJobUri}"
+ lib.optionalString (cfg.netrc != null) " --netrc-file ${cfg.netrc}";
};
};
};
}

View File

@ -68,9 +68,9 @@ let
collectd = [{
enabled = false;
typesdb = "${pkgs.collectd}/share/collectd/types.db";
typesdb = "${pkgs.collectd-data}/share/collectd/types.db";
database = "collectd_db";
port = 25826;
bind-address = ":25826";
}];
opentsdb = [{
@ -149,7 +149,6 @@ in
type = types.attrs;
};
};
};

View File

@ -108,7 +108,7 @@ in
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${mongodb}/bin/mongod --quiet --config ${mongoCnf} --fork --pidfilepath ${cfg.pidFile}";
ExecStart = "${mongodb}/bin/mongod --config ${mongoCnf} --fork --pidfilepath ${cfg.pidFile}";
User = cfg.user;
PIDFile = cfg.pidFile;
Type = "forking";

View File

@ -0,0 +1,205 @@
{ lib, pkgs, config, ... } :
with lib;
let
cfg = config.services.postage;
confFile = pkgs.writeTextFile {
name = "postage.conf";
text = ''
connection_file = ${postageConnectionsFile}
allow_custom_connections = ${builtins.toJSON cfg.allowCustomConnections}
postage_port = ${toString cfg.port}
super_only = ${builtins.toJSON cfg.superOnly}
${optionalString (!isNull cfg.loginGroup) "login_group = ${cfg.loginGroup}"}
login_timeout = ${toString cfg.loginTimeout}
web_root = ${cfg.package}/etc/postage/web_root
data_root = ${cfg.dataRoot}
${optionalString (!isNull cfg.tls) ''
tls_cert = ${cfg.tls.cert}
tls_key = ${cfg.tls.key}
''}
log_level = ${cfg.logLevel}
'';
};
postageConnectionsFile = pkgs.writeTextFile {
name = "postage-connections.conf";
text = concatStringsSep "\n"
(mapAttrsToList (name : conn : "${name}: ${conn}") cfg.connections);
};
postage = "postage";
in {
options.services.postage = {
enable = mkEnableOption "PostgreSQL Administration for the web";
package = mkOption {
type = types.package;
default = pkgs.postage;
defaultText = "pkgs.postage";
description = ''
The postage package to use.
'';
};
connections = mkOption {
type = types.attrsOf types.str;
default = {};
example = {
"nuc-server" = "hostaddr=192.168.0.100 port=5432 dbname=postgres";
"mini-server" = "hostaddr=127.0.0.1 port=5432 dbname=postgres sslmode=require";
};
description = ''
Postage requires at least one PostgreSQL server be defined.
</para><para>
Detailed information about PostgreSQL connection strings is available at:
<link xlink:href="http://www.postgresql.org/docs/current/static/libpq-connect.html"/>
</para><para>
Note that you should not specify your user name or password. That
information will be entered on the login screen. If you specify a
username or password, it will be removed by Postage before attempting to
connect to a database.
'';
};
allowCustomConnections = mkOption {
type = types.bool;
default = false;
description = ''
This tells Postage whether or not to allow anyone to use a custom
connection from the login screen.
'';
};
port = mkOption {
type = types.int;
default = 8080;
description = ''
This tells Postage what port to listen on for browser requests.
'';
};
localOnly = mkOption {
type = types.bool;
default = true;
description = ''
This tells Postage whether or not to set the listening socket to local
addresses only.
'';
};
superOnly = mkOption {
type = types.bool;
default = true;
description = ''
This tells Postage whether or not to only allow super users to
login. The recommended value is true and will restrict users who are not
super users from logging in to any PostgreSQL instance through
Postage. Note that a connection will be made to PostgreSQL in order to
test if the user is a superuser.
'';
};
loginGroup = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
This tells Postage to only allow users in a certain PostgreSQL group to
login to Postage. Note that a connection will be made to PostgreSQL in
order to test if the user is a member of the login group.
'';
};
loginTimeout = mkOption {
type = types.int;
default = 3600;
description = ''
Number of seconds of inactivity before user is automatically logged
out.
'';
};
dataRoot = mkOption {
type = types.str;
default = "/var/lib/postage";
description = ''
This tells Postage where to put the SQL file history. All tabs are saved
to this location so that if you get disconnected from Postage you
don't lose your work.
'';
};
tls = mkOption {
type = types.nullOr (types.submodule {
options = {
cert = mkOption {
type = types.str;
description = "TLS certificate";
};
key = mkOption {
type = types.str;
description = "TLS key";
};
};
});
default = null;
description = ''
These options tell Postage where the TLS Certificate and Key files
reside. If you use these options then you'll only be able to access
Postage through a secure TLS connection. These options are only
necessary if you wish to connect directly to Postage using a secure TLS
connection. As an alternative, you can set up Postage in a reverse proxy
configuration. This allows your web server to terminate the secure
connection and pass on the request to Postage. You can find help to set
up this configuration in:
<link xlink:href="https://github.com/workflowproducts/postage/blob/master/INSTALL_NGINX.md"/>
'';
};
logLevel = mkOption {
type = types.enum ["error" "warn" "notice" "info"];
default = "error";
description = ''
Verbosity of logs
'';
};
};
config = mkIf cfg.enable {
systemd.services.postage = {
description = "postage - PostgreSQL Administration for the web";
wants = [ "postgresql.service" ];
after = [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = postage;
Group = postage;
ExecStart = "${pkgs.postage}/sbin/postage -c ${confFile}" +
optionalString cfg.localOnly " --local-only=true";
};
};
users = {
users."${postage}" = {
name = postage;
group = postage;
home = cfg.dataRoot;
createHome = true;
};
groups."${postage}" = {
name = postage;
};
};
};
}

View File

@ -24,7 +24,7 @@
<para>
Emacs runs within a graphical desktop environment using the X
Window System, but works equally well on a text terminal. Under
<productname>OS X</productname>, a "Mac port" edition is
<productname>macOS</productname>, a "Mac port" edition is
available, which uses Apple's native GUI frameworks.
</para>
@ -84,7 +84,7 @@
<listitem>
<para>
Emacs 25 with the "Mac port" patches, providing a more
native look and feel under OS X.
native look and feel under macOS.
</para>
</listitem>
</varlistentry>

View File

@ -39,7 +39,7 @@ let
admins = [];
};
serverSettingsFile = pkgs.writeText "server-settings.json" (builtins.toJSON (filterAttrsRecursive (n: v: v != null) serverSettings));
modDir = pkgs.factorio-mkModDirDrv cfg.mods;
modDir = pkgs.factorio-utils.mkModDirDrv cfg.mods;
in
{
options = {

View File

@ -57,6 +57,8 @@ in
powerManagement.scsiLinkPolicy = null;
powerManagement.cpuFreqGovernor = null;
systemd.sockets."systemd-rfkill".enable = false;
systemd.services = {
"systemd-rfkill@".enable = false;
"systemd-rfkill".enable = false;

View File

@ -4,6 +4,8 @@ with lib;
let
cfg = config.services.fluentd;
pluginArgs = concatStringsSep " " (map (x: "-p ${x}") cfg.plugins);
in {
###### interface
@ -28,6 +30,15 @@ in {
defaultText = "pkgs.fluentd";
description = "The fluentd package to use.";
};
plugins = mkOption {
type = types.listOf types.path;
default = [];
description = ''
A list of plugin paths to pass into fluentd. It will make plugins defined in ruby files
there available in your config.
'';
};
};
};
@ -39,7 +50,7 @@ in {
description = "Fluentd Daemon";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/fluentd -c ${pkgs.writeText "fluentd.conf" cfg.config}";
ExecStart = "${cfg.package}/bin/fluentd -c ${pkgs.writeText "fluentd.conf" cfg.config} ${pluginArgs}";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
};
};

View File

@ -11,9 +11,7 @@ let
password_secret = ${cfg.passwordSecret}
root_username = ${cfg.rootUsername}
root_password_sha2 = ${cfg.rootPasswordSha2}
elasticsearch_cluster_name = ${cfg.elasticsearchClusterName}
elasticsearch_discovery_zen_ping_multicast_enabled = ${boolToString cfg.elasticsearchDiscoveryZenPingMulticastEnabled}
elasticsearch_discovery_zen_ping_unicast_hosts = ${cfg.elasticsearchDiscoveryZenPingUnicastHosts}
elasticsearch_hosts = ${concatStringsSep "," cfg.elasticsearchHosts}
message_journal_dir = ${cfg.messageJournalDir}
mongodb_uri = ${cfg.mongodbUri}
plugin_dir = /var/lib/graylog/plugins
@ -91,22 +89,10 @@ in
'';
};
elasticsearchClusterName = mkOption {
type = types.str;
example = "graylog";
description = "This must be the same as for your Elasticsearch cluster";
};
elasticsearchDiscoveryZenPingMulticastEnabled = mkOption {
type = types.bool;
default = false;
description = "Whether to use elasticsearch multicast discovery";
};
elasticsearchDiscoveryZenPingUnicastHosts = mkOption {
type = types.str;
default = "127.0.0.1:9300";
description = "Tells Graylogs Elasticsearch client how to find other cluster members. See Elasticsearch documentation for details";
elasticsearchHosts = mkOption {
type = types.listOf types.str;
example = literalExample ''[ "http://node1:9200" "http://user:password@node2:19200" ]'';
description = "List of valid URIs of the http ports of your elastic nodes. If one or more of your elasticsearch hosts require authentication, include the credentials in each node URI that requires authentication";
};
messageJournalDir = mkOption {

View File

@ -0,0 +1,246 @@
{ config, lib, pkgs, services, ... }:
with lib;
let
cfg = config.services.journalwatch;
user = "journalwatch";
dataDir = "/var/lib/${user}";
journalwatchConfig = pkgs.writeText "config" (''
# (File Generated by NixOS journalwatch module.)
[DEFAULT]
mail_binary = ${cfg.mailBinary}
priority = ${toString cfg.priority}
mail_from = ${cfg.mailFrom}
''
+ optionalString (cfg.mailTo != null) ''
mail_to = ${cfg.mailTo}
''
+ cfg.extraConfig);
journalwatchPatterns = pkgs.writeText "patterns" ''
# (File Generated by NixOS journalwatch module.)
${mkPatterns cfg.filterBlocks}
'';
# empty line at the end needed to to separate the blocks
mkPatterns = filterBlocks: concatStringsSep "\n" (map (block: ''
${block.match}
${block.filters}
'') filterBlocks);
in {
options = {
services.journalwatch = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, periodically check the journal with journalwatch and report the results by mail.
'';
};
priority = mkOption {
type = types.int;
default = 6;
description = ''
Lowest priority of message to be considered.
A value between 7 ("debug"), and 0 ("emerg"). Defaults to 6 ("info").
If you don't care about anything with "info" priority, you can reduce
this to e.g. 5 ("notice") to considerably reduce the amount of
messages without needing many <option>filterBlocks</option>.
'';
};
# HACK: this is a workaround for journalwatch's usage of socket.getfqdn() which always returns localhost if
# there's an alias for the localhost on a separate line in /etc/hosts, or take for ages if it's not present and
# then return something right-ish in the direction of /etc/hostname. Just bypass it completely.
mailFrom = mkOption {
type = types.str;
default = "journalwatch@${config.networking.hostName}";
description = ''
Mail address to send journalwatch reports from.
'';
};
mailTo = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Mail address to send journalwatch reports to.
'';
};
mailBinary = mkOption {
type = types.path;
default = "/run/wrappers/bin/sendmail";
description = ''
Sendmail-compatible binary to be used to send the messages.
'';
};
extraConfig = mkOption {
type = types.str;
default = "";
description = ''
Extra lines to be added verbatim to the journalwatch/config configuration file.
You can add any commandline argument to the config, without the '--'.
See <literal>journalwatch --help</literal> for all arguments and their description.
'';
};
filterBlocks = mkOption {
type = types.listOf (types.submodule {
options = {
match = mkOption {
type = types.str;
example = "SYSLOG_IDENTIFIER = systemd";
description = ''
Syntax: <literal>field = value</literal>
Specifies the log entry <literal>field</literal> this block should apply to.
If the <literal>field</literal> of a message matches this <literal>value</literal>,
this patternBlock's <option>filters</option> are applied.
If <literal>value</literal> starts and ends with a slash, it is interpreted as
an extended python regular expression, if not, it's an exact match.
The journal fields are explained in systemd.journal-fields(7).
'';
};
filters = mkOption {
type = types.str;
example = ''
(Stopped|Stopping|Starting|Started) .*
(Reached target|Stopped target) .*
'';
description = ''
The filters to apply on all messages which satisfy <option>match</option>.
Any of those messages that match any specified filter will be removed from journalwatch's output.
Each filter is an extended Python regular expression.
You can specify multiple filters and separate them by newlines.
Lines starting with '#' are comments. Inline-comments are not permitted.
'';
};
};
});
example = [
# examples taken from upstream
{
match = "_SYSTEMD_UNIT = systemd-logind.service";
filters = ''
New session [a-z]?\d+ of user \w+\.
Removed session [a-z]?\d+\.
'';
}
{
match = "SYSLOG_IDENTIFIER = /(CROND|crond)/";
filters = ''
pam_unix\(crond:session\): session (opened|closed) for user \w+
\(\w+\) CMD .*
'';
}
];
# another example from upstream.
# very useful on priority = 6, and required as journalwatch throws an error when no pattern is defined at all.
default = [
{
match = "SYSLOG_IDENTIFIER = systemd";
filters = ''
(Stopped|Stopping|Starting|Started) .*
(Created slice|Removed slice) user-\d*\.slice\.
Received SIGRTMIN\+24 from PID .*
(Reached target|Stopped target) .*
Startup finished in \d*ms\.
'';
}
];
description = ''
filterBlocks can be defined to blacklist journal messages which are not errors.
Each block matches on a log entry field, and the filters in that block then are matched
against all messages with a matching log entry field.
All messages whose PRIORITY is at least 6 (INFO) are processed by journalwatch.
If you don't specify any filterBlocks, PRIORITY is reduced to 5 (NOTICE) by default.
All regular expressions are extended Python regular expressions, for details
see: http://doc.pyschools.com/html/regex.html
'';
};
interval = mkOption {
type = types.str;
default = "hourly";
description = ''
How often to run journalwatch.
The format is described in systemd.time(7).
'';
};
accuracy = mkOption {
type = types.str;
default = "10min";
description = ''
The time window around the interval in which the journalwatch run will be scheduled.
The format is described in systemd.time(7).
'';
};
};
};
config = mkIf cfg.enable {
users.extraUsers.${user} = {
isSystemUser = true;
createHome = true;
home = dataDir;
# for journal access
group = "systemd-journal";
};
systemd.services.journalwatch = {
environment = {
XDG_DATA_HOME = "${dataDir}/share";
XDG_CONFIG_HOME = "${dataDir}/config";
};
serviceConfig = {
User = user;
Type = "oneshot";
PermissionsStartOnly = true;
ExecStart = "${pkgs.python3Packages.journalwatch}/bin/journalwatch mail";
# lowest CPU and IO priority, but both still in best-effort class to prevent starvation
Nice=19;
IOSchedulingPriority=7;
};
preStart = ''
chown -R ${user}:systemd-journal ${dataDir}
chmod -R u+rwX,go-w ${dataDir}
mkdir -p ${dataDir}/config/journalwatch
ln -sf ${journalwatchConfig} ${dataDir}/config/journalwatch/config
ln -sf ${journalwatchPatterns} ${dataDir}/config/journalwatch/patterns
'';
};
systemd.timers.journalwatch = {
description = "Periodic journalwatch run";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = cfg.interval;
AccuracySec = cfg.accuracy;
Persistent = true;
};
};
};
meta = {
maintainers = with stdenv.lib.maintainers; [ florianjacob ];
};
}

View File

@ -9,7 +9,8 @@ let
group = cfg.group;
setgidGroup = cfg.setgidGroup;
haveAliases = cfg.postmasterAlias != "" || cfg.rootAlias != "" || cfg.extraAliases != "";
haveAliases = cfg.postmasterAlias != "" || cfg.rootAlias != ""
|| cfg.extraAliases != "";
haveTransport = cfg.transport != "";
haveVirtual = cfg.virtual != "";
@ -25,149 +26,275 @@ let
clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
mainCf =
''
compatibility_level = 9999
mainCf = let
escape = replaceStrings ["$"] ["$$"];
mkList = items: "\n " + concatMapStringsSep "\n " escape items;
mkVal = value:
if isList value then mkList value
else " " + (if value == true then "yes"
else if value == false then "no"
else toString value);
mkEntry = name: value: "${escape name} =${mkVal value}";
in
concatStringsSep "\n" (mapAttrsToList mkEntry (recursiveUpdate defaultConf cfg.config))
+ "\n" + cfg.extraConfig;
mail_owner = ${user}
default_privs = nobody
defaultConf = {
compatibility_level = "9999";
mail_owner = user;
default_privs = "nobody";
# NixOS specific locations
data_directory = /var/lib/postfix/data
queue_directory = /var/lib/postfix/queue
# NixOS specific locations
data_directory = "/var/lib/postfix/data";
queue_directory = "/var/lib/postfix/queue";
# Default location of everything in package
meta_directory = ${pkgs.postfix}/etc/postfix
command_directory = ${pkgs.postfix}/bin
sample_directory = /etc/postfix
newaliases_path = ${pkgs.postfix}/bin/newaliases
mailq_path = ${pkgs.postfix}/bin/mailq
readme_directory = no
sendmail_path = ${pkgs.postfix}/bin/sendmail
daemon_directory = ${pkgs.postfix}/libexec/postfix
manpage_directory = ${pkgs.postfix}/share/man
html_directory = ${pkgs.postfix}/share/postfix/doc/html
shlib_directory = no
# Default location of everything in package
meta_directory = "${pkgs.postfix}/etc/postfix";
command_directory = "${pkgs.postfix}/bin";
sample_directory = "/etc/postfix";
newaliases_path = "${pkgs.postfix}/bin/newaliases";
mailq_path = "${pkgs.postfix}/bin/mailq";
readme_directory = false;
sendmail_path = "${pkgs.postfix}/bin/sendmail";
daemon_directory = "${pkgs.postfix}/libexec/postfix";
manpage_directory = "${pkgs.postfix}/share/man";
html_directory = "${pkgs.postfix}/share/postfix/doc/html";
shlib_directory = false;
relayhost = if cfg.lookupMX || cfg.relayHost == ""
then cfg.relayHost
else "[${cfg.relayHost}]";
mail_spool_directory = "/var/spool/mail/";
setgid_group = setgidGroup;
}
// optionalAttrs config.networking.enableIPv6 { inet_protocols = "all"; }
// optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
// optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
// optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
// optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
// optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
// optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
// optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
// optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
// optionalAttrs haveAliases { alias_maps = "${cfg.aliasMapType}:/etc/postfix/aliases"; }
// optionalAttrs haveTransport { transport_maps = "hash:/etc/postfix/transport"; }
// optionalAttrs haveVirtual { virtual_alias_maps = "${cfg.virtualMapType}:/etc/postfix/virtual"; }
// optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
// optionalAttrs cfg.enableHeaderChecks { header_checks = "regexp:/etc/postfix/header_checks"; }
// optionalAttrs (cfg.sslCert != "") {
smtp_tls_CAfile = cfg.sslCACert;
smtp_tls_cert_file = cfg.sslCert;
smtp_tls_key_file = cfg.sslKey;
''
+ optionalString config.networking.enableIPv6 ''
inet_protocols = all
''
+ (if cfg.networks != null then
''
mynetworks = ${concatStringsSep ", " cfg.networks}
''
else if cfg.networksStyle != "" then
''
mynetworks_style = ${cfg.networksStyle}
''
else
"")
+ optionalString (cfg.hostname != "") ''
myhostname = ${cfg.hostname}
''
+ optionalString (cfg.domain != "") ''
mydomain = ${cfg.domain}
''
+ optionalString (cfg.origin != "") ''
myorigin = ${cfg.origin}
''
+ optionalString (cfg.destination != null) ''
mydestination = ${concatStringsSep ", " cfg.destination}
''
+ optionalString (cfg.relayDomains != null) ''
relay_domains = ${concatStringsSep ", " cfg.relayDomains}
''
+ ''
relayhost = ${if cfg.lookupMX || cfg.relayHost == "" then
cfg.relayHost
else
"[" + cfg.relayHost + "]"}
smtp_use_tls = true;
mail_spool_directory = /var/spool/mail/
smtpd_tls_CAfile = cfg.sslCACert;
smtpd_tls_cert_file = cfg.sslCert;
smtpd_tls_key_file = cfg.sslKey;
setgid_group = ${setgidGroup}
''
+ optionalString (cfg.sslCert != "") ''
smtpd_use_tls = true;
};
smtp_tls_CAfile = ${cfg.sslCACert}
smtp_tls_cert_file = ${cfg.sslCert}
smtp_tls_key_file = ${cfg.sslKey}
masterCfOptions = { options, config, name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
example = "smtp";
description = ''
The name of the service to run. Defaults to the attribute set key.
'';
};
smtp_use_tls = yes
type = mkOption {
type = types.enum [ "inet" "unix" "fifo" "pass" ];
default = "unix";
example = "inet";
description = "The type of the service";
};
smtpd_tls_CAfile = ${cfg.sslCACert}
smtpd_tls_cert_file = ${cfg.sslCert}
smtpd_tls_key_file = ${cfg.sslKey}
private = mkOption {
type = types.bool;
example = false;
description = ''
Whether the service's sockets and storage directory is restricted to
be only available via the mail system. If <literal>null</literal> is
given it uses the postfix default <literal>true</literal>.
'';
};
smtpd_use_tls = yes
''
+ optionalString (cfg.recipientDelimiter != "") ''
recipient_delimiter = ${cfg.recipientDelimiter}
''
+ optionalString haveAliases ''
alias_maps = hash:/etc/postfix/aliases
''
+ optionalString haveTransport ''
transport_maps = hash:/etc/postfix/transport
''
+ optionalString haveVirtual ''
virtual_alias_maps = hash:/etc/postfix/virtual
''
+ optionalString (cfg.dnsBlacklists != []) ''
smtpd_client_restrictions = ${clientRestrictions}
''
+ cfg.extraConfig;
privileged = mkOption {
type = types.bool;
example = true;
description = "";
};
masterCf = ''
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
'' + 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
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
''
+ optionalString cfg.enableSmtp ''
smtp unix - - n - - smtp
relay unix - - n - - smtp
-o smtp_fallback_relay=
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
''
+ ''
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
${cfg.extraMasterConf}
'';
chroot = mkOption {
type = types.bool;
example = true;
description = ''
Whether the service is chrooted to have only access to the
<option>services.postfix.queueDir</option> and the closure of
store paths specified by the <option>program</option> option.
'';
};
aliases =
wakeup = mkOption {
type = types.int;
example = 60;
description = ''
Automatically wake up the service after the specified number of
seconds. If <literal>0</literal> is given, never wake the service
up.
'';
};
wakeupUnusedComponent = mkOption {
type = types.bool;
example = false;
description = ''
If set to <literal>false</literal> the component will only be woken
up if it is used. This is equivalent to postfix' notion of adding a
question mark behind the wakeup time in
<filename>master.cf</filename>
'';
};
maxproc = mkOption {
type = types.int;
example = 1;
description = ''
The maximum number of processes to spawn for this service. If the
value is <literal>0</literal> it doesn't have any limit. If
<literal>null</literal> is given it uses the postfix default of
<literal>100</literal>.
'';
};
command = mkOption {
type = types.str;
default = name;
example = "smtpd";
description = ''
A program name specifying a Postfix service/daemon process.
By default it's the attribute <option>name</option>.
'';
};
args = mkOption {
type = types.listOf types.str;
default = [];
example = [ "-o" "smtp_helo_timeout=5" ];
description = ''
Arguments to pass to the <option>command</option>. There is no shell
processing involved and shell syntax is passed verbatim to the
process.
'';
};
rawEntry = mkOption {
type = types.listOf types.str;
default = [];
internal = true;
description = ''
The raw configuration line for the <filename>master.cf</filename>.
'';
};
};
config.rawEntry = let
mkBool = bool: if bool then "y" else "n";
mkArg = arg: "${optionalString (hasPrefix "-" arg) "\n "}${arg}";
maybeOption = fun: option:
if options.${option}.isDefined then fun config.${option} else "-";
# This is special, because we have two options for this value.
wakeup = let
wakeupDefined = options.wakeup.isDefined;
wakeupUCDefined = options.wakeupUnusedComponent.isDefined;
finalValue = toString config.wakeup
+ optionalString (wakeupUCDefined && !config.wakeupUnusedComponent) "?";
in if wakeupDefined then finalValue else "-";
in [
config.name
config.type
(maybeOption mkBool "private")
(maybeOption (b: mkBool (!b)) "privileged")
(maybeOption mkBool "chroot")
wakeup
(maybeOption toString "maxproc")
(config.command + " " + concatMapStringsSep " " mkArg config.args)
];
};
masterCfContent = let
labels = [
"# service" "type" "private" "unpriv" "chroot" "wakeup" "maxproc"
"command + args"
];
labelDefaults = [
"# " "" "(yes)" "(yes)" "(no)" "(never)" "(100)" "" ""
];
masterCf = mapAttrsToList (const (getAttr "rawEntry")) cfg.masterConfig;
# A list of the maximum width of the columns across all lines and labels
maxWidths = let
foldLine = line: acc: let
columnLengths = map stringLength line;
in zipListsWith max acc columnLengths;
# We need to handle the last column specially here, because it's
# open-ended (command + args).
lines = [ labels labelDefaults ] ++ (map (l: init l ++ [""]) masterCf);
in fold foldLine (genList (const 0) (length labels)) lines;
# Pad a string with spaces from the right (opposite of fixedWidthString).
pad = width: str: let
padWidth = width - stringLength str;
padding = concatStrings (genList (const " ") padWidth);
in str + optionalString (padWidth > 0) padding;
# It's + 2 here, because that's the amount of spacing between columns.
fullWidth = fold (width: acc: acc + width + 2) 0 maxWidths;
formatLine = line: concatStringsSep " " (zipListsWith pad maxWidths line);
formattedLabels = let
sep = "# " + concatStrings (genList (const "=") (fullWidth + 5));
lines = [ sep (formatLine labels) (formatLine labelDefaults) sep ];
in concatStringsSep "\n" lines;
in formattedLabels + "\n" + concatMapStringsSep "\n" formatLine masterCf + "\n" + cfg.extraMasterConf;
headerCheckOptions = { ... }:
{
options = {
pattern = mkOption {
type = types.str;
default = "/^.*/";
example = "/^X-Mailer:/";
description = "A regexp pattern matching the header";
};
action = mkOption {
type = types.str;
default = "DUNNO";
example = "BCC mail@example.com";
description = "The action to be executed when the pattern is matched";
};
};
};
headerChecks = concatStringsSep "\n" (map (x: "${x.pattern} ${x.action}") cfg.headerChecks) + cfg.extraHeaderChecks;
aliases = let seperator = if cfg.aliasMapType == "hash" then ":" else ""; in
optionalString (cfg.postmasterAlias != "") ''
postmaster: ${cfg.postmasterAlias}
postmaster${seperator} ${cfg.postmasterAlias}
''
+ optionalString (cfg.rootAlias != "") ''
root: ${cfg.rootAlias}
root${seperator} ${cfg.rootAlias}
''
+ cfg.extraAliases
;
@ -176,8 +303,9 @@ let
virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
checkClientAccessFile = pkgs.writeText "postfix-check-client-access" cfg.dnsBlacklistOverrides;
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
masterCfFile = pkgs.writeText "postfix-master.cf" masterCf;
masterCfFile = pkgs.writeText "postfix-master.cf" masterCfContent;
transportFile = pkgs.writeText "postfix-transport" cfg.transport;
headerChecksFile = pkgs.writeText "postfix-header-checks" headerChecks;
in
@ -199,27 +327,29 @@ in
default = true;
description = "Whether to enable smtp in master.cf.";
};
enableSubmission = mkOption {
type = types.bool;
default = false;
description = "Whether to enable smtp submission";
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";
};
default = {
smtpd_tls_security_level = "encrypt";
smtpd_sasl_auth_enable = "yes";
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
milter_macro_daemon_name = "ORIGINATING";
};
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";
};
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 {
@ -352,6 +482,25 @@ in
";
};
aliasMapType = mkOption {
type = with types; enum [ "hash" "regexp" "pcre" ];
default = "hash";
example = "regexp";
description = "The format the alias map should have. Use regexp if you want to use regular expressions.";
};
config = mkOption {
type = with types; attrsOf (either bool (either str (listOf str)));
default = defaultConf;
description = ''
The main.cf configuration file as key value set.
'';
example = {
mail_owner = "postfix";
smtp_use_tls = true;
};
};
extraConfig = mkOption {
type = types.lines;
default = "";
@ -395,6 +544,14 @@ in
";
};
virtualMapType = mkOption {
type = types.enum ["hash" "regexp" "pcre"];
default = "hash";
description = ''
What type of virtual alias map file to use. Use <literal>"regexp"</literal> for regular expressions.
'';
};
transport = mkOption {
default = "";
description = "
@ -413,6 +570,22 @@ in
description = "contents of check_client_access for overriding dnsBlacklists";
};
masterConfig = mkOption {
type = types.attrsOf (types.submodule masterCfOptions);
default = {};
example =
{ submission = {
type = "inet";
args = [ "-o" "smtpd_tls_security_level=encrypt" ];
};
};
description = ''
An attribute set of service options, which correspond to the service
definitions usually done within the Postfix
<filename>master.cf</filename> file.
'';
};
extraMasterConf = mkOption {
type = types.lines;
default = "";
@ -420,6 +593,27 @@ in
description = "Extra lines to append to the generated master.cf file.";
};
enableHeaderChecks = mkOption {
type = types.bool;
default = false;
example = true;
description = "Whether to enable postfix header checks";
};
headerChecks = mkOption {
type = types.listOf (types.submodule headerCheckOptions);
default = [];
example = [ { pattern = "/^X-Spam-Flag:/"; action = "REDIRECT spam@example.com"; } ];
description = "Postfix header checks.";
};
extraHeaderChecks = mkOption {
type = types.lines;
default = "";
example = "/^X-Spam-Flag:/ REDIRECT spam@example.com";
description = "Extra lines to /etc/postfix/header_checks file.";
};
aliasFiles = mkOption {
type = types.attrsOf types.path;
default = {};
@ -530,6 +724,101 @@ in
${pkgs.postfix}/bin/postfix set-permissions config_directory=/var/lib/postfix/conf
'';
};
services.postfix.masterConfig = {
smtp_inet = {
name = "smtp";
type = "inet";
private = false;
command = "smtpd";
};
pickup = {
private = false;
wakeup = 60;
maxproc = 1;
};
cleanup = {
private = false;
maxproc = 0;
};
qmgr = {
private = false;
wakeup = 300;
maxproc = 1;
};
tlsmgr = {
wakeup = 1000;
wakeupUnusedComponent = false;
maxproc = 1;
};
rewrite = {
command = "trivial-rewrite";
};
bounce = {
maxproc = 0;
};
defer = {
maxproc = 0;
command = "bounce";
};
trace = {
maxproc = 0;
command = "bounce";
};
verify = {
maxproc = 1;
};
flush = {
private = false;
wakeup = 1000;
wakeupUnusedComponent = false;
maxproc = 0;
};
proxymap = {
command = "proxymap";
};
proxywrite = {
maxproc = 1;
command = "proxymap";
};
showq = {
private = false;
};
error = {};
retry = {
command = "error";
};
discard = {};
local = {
privileged = true;
};
virtual = {
privileged = true;
};
lmtp = {
};
anvil = {
maxproc = 1;
};
scache = {
maxproc = 1;
};
} // optionalAttrs cfg.enableSubmission {
submission = {
type = "inet";
private = false;
command = "smtpd";
args = let
mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
in concatLists (mapAttrsToList mkKeyVal cfg.submissionOptions);
};
} // optionalAttrs cfg.enableSmtp {
smtp = {};
relay = {
command = "smtp";
args = [ "-o" "smtp_fallback_relay=" ];
};
};
}
(mkIf haveAliases {
@ -541,9 +830,17 @@ in
(mkIf haveVirtual {
services.postfix.mapFiles."virtual" = virtualFile;
})
(mkIf cfg.enableHeaderChecks {
services.postfix.mapFiles."header_checks" = headerChecksFile;
})
(mkIf (cfg.dnsBlacklists != []) {
services.postfix.mapFiles."client_access" = checkClientAccessFile;
})
(mkIf (cfg.extraConfig != "") {
warnings = [ "The services.postfix.extraConfig option was deprecated. Please use services.postfix.config instead." ];
})
(mkIf (cfg.extraMasterConf != "") {
warnings = [ "The services.postfix.extraMasterConf option was deprecated. Please use services.postfix.masterConfig instead." ];
})
]);
}

View File

@ -0,0 +1,117 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.airsonic;
in {
options = {
services.airsonic = {
enable = mkEnableOption "Airsonic, the Free and Open Source media streaming server (fork of Subsonic and Libresonic)";
user = mkOption {
type = types.str;
default = "airsonic";
description = "User account under which airsonic runs.";
};
home = mkOption {
type = types.path;
default = "/var/lib/airsonic";
description = ''
The directory where Airsonic will create files.
Make sure it is writable.
'';
};
listenAddress = mkOption {
type = types.string;
default = "127.0.0.1";
description = ''
The host name or IP address on which to bind Airsonic.
Only relevant if you have multiple network interfaces and want
to make Airsonic available on only one of them. The default value
will bind Airsonic to all available network interfaces.
'';
};
port = mkOption {
type = types.int;
default = 4040;
description = ''
The port on which Airsonic will listen for
incoming HTTP traffic. Set to 0 to disable.
'';
};
contextPath = mkOption {
type = types.path;
default = "/";
description = ''
The context path, i.e., the last part of the Airsonic
URL. Typically '/' or '/airsonic'. Default '/'
'';
};
maxMemory = mkOption {
type = types.int;
default = 100;
description = ''
The memory limit (max Java heap size) in megabytes.
Default: 100
'';
};
transcoders = mkOption {
type = types.listOf types.path;
default = [ "${pkgs.ffmpeg.bin}/bin/ffmpeg" ];
defaultText= [ "\${pkgs.ffmpeg.bin}/bin/ffmpeg" ];
description = ''
List of paths to transcoder executables that should be accessible
from Airsonic. Symlinks will be created to each executable inside
${cfg.home}/transcoders.
'';
};
};
};
config = mkIf cfg.enable {
systemd.services.airsonic = {
description = "Airsonic Media Server";
after = [ "local-fs.target" "network.target" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
# Install transcoders.
rm -rf ${cfg.home}/transcode
mkdir -p ${cfg.home}/transcode
for exe in ${toString cfg.transcoders}; do
ln -sf "$exe" ${cfg.home}/transcode
done
'';
serviceConfig = {
ExecStart = ''
${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
-Dairsonic.home=${cfg.home} \
-Dserver.address=${cfg.listenAddress} \
-Dserver.port=${toString cfg.port} \
-Dairsonic.contextPath=${cfg.contextPath} \
-Djava.awt.headless=true \
-verbose:gc \
-jar ${pkgs.airsonic}/webapps/airsonic.war
'';
Restart = "always";
User = "airsonic";
UMask = "0022";
};
};
users.extraUsers.airsonic = {
description = "Airsonic service user";
name = cfg.user;
home = cfg.home;
createHome = true;
};
};
}

View File

@ -20,10 +20,10 @@ in
enable = mkOption {
default = false;
description = "
description = ''
Mount filesystems on demand. Unmount them automatically.
You may also be interested in afuse.
";
'';
};
autoMaster = mkOption {
@ -45,10 +45,9 @@ in
/auto file:''${mapConf}
'''
'';
description = "
file contents of /etc/auto.master. See man auto.master
See man 5 auto.master and man 5 autofs.
";
description = ''
Contents of <literal>/etc/auto.master</literal> file. See <command>auto.master(5)</command> and <command>autofs(5)</command>.
'';
};
timeout = mkOption {
@ -58,9 +57,9 @@ in
debug = mkOption {
default = false;
description = "
pass -d and -7 to automount and write log to /var/log/autofs
";
description = ''
Pass -d and -7 to automount and write log to the system journal.
'';
};
};

View File

@ -30,4 +30,5 @@ in {
};
meta.maintainers = with maintainers; [ gnidorah ];
}

View File

@ -0,0 +1,418 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.exhibitor;
exhibitor = cfg.package;
exhibitorConfig = ''
zookeeper-install-directory=${cfg.baseDir}/zookeeper
zookeeper-data-directory=${cfg.zkDataDir}
zookeeper-log-directory=${cfg.zkLogDir}
zoo-cfg-extra=${cfg.zkExtraCfg}
client-port=${toString cfg.zkClientPort}
connect-port=${toString cfg.zkConnectPort}
election-port=${toString cfg.zkElectionPort}
cleanup-period-ms=${toString cfg.zkCleanupPeriod}
servers-spec=${concatStringsSep "," cfg.zkServersSpec}
auto-manage-instances=${toString cfg.autoManageInstances}
${cfg.extraConf}
'';
# NB: toString rather than lib.boolToString on cfg.autoManageInstances is intended.
# Exhibitor tests if it's an integer not equal to 0, so the empty string (toString false)
# will operate in the same fashion as a 0.
configDir = pkgs.writeTextDir "exhibitor.properties" exhibitorConfig;
cliOptionsCommon = {
configtype = cfg.configType;
defaultconfig = "${configDir}/exhibitor.properties";
port = toString cfg.port;
hostname = cfg.hostname;
headingtext = if (cfg.headingText != null) then (lib.escapeShellArg cfg.headingText) else null;
nodemodification = lib.boolToString cfg.nodeModification;
configcheckms = toString cfg.configCheckMs;
jquerystyle = cfg.jqueryStyle;
loglines = toString cfg.logLines;
servo = lib.boolToString cfg.servo;
timeout = toString cfg.timeout;
};
s3CommonOptions = { s3region = cfg.s3Region; s3credentials = cfg.s3Credentials; };
cliOptionsPerConfig = {
s3 = {
s3config = "${cfg.s3Config.bucketName}:${cfg.s3Config.objectKey}";
s3configprefix = cfg.s3Config.configPrefix;
};
zookeeper = {
zkconfigconnect = concatStringsSep "," cfg.zkConfigConnect;
zkconfigexhibitorpath = cfg.zkConfigExhibitorPath;
zkconfigpollms = toString cfg.zkConfigPollMs;
zkconfigretry = "${toString cfg.zkConfigRetry.sleepMs}:${toString cfg.zkConfigRetry.retryQuantity}";
zkconfigzpath = cfg.zkConfigZPath;
zkconfigexhibitorport = toString cfg.zkConfigExhibitorPort; # NB: This might be null
};
file = {
fsconfigdir = cfg.fsConfigDir;
fsconfiglockprefix = cfg.fsConfigLockPrefix;
fsConfigName = fsConfigName;
};
none = {
noneconfigdir = configDir;
};
};
cliOptions = concatStringsSep " " (mapAttrsToList (k: v: "--${k} ${v}") (filterAttrs (k: v: v != null && v != "") (cliOptionsCommon //
cliOptionsPerConfig."${cfg.configType}" //
s3CommonOptions //
optionalAttrs cfg.s3Backup { s3backup = "true"; } //
optionalAttrs cfg.fileSystemBackup { filesystembackup = "true"; }
)));
in
{
options = {
services.exhibitor = {
enable = mkOption {
type = types.bool;
default = false;
description = "
Whether to enable the exhibitor server.
";
};
# See https://github.com/soabase/exhibitor/wiki/Running-Exhibitor for what these mean
# General options for any type of config
port = mkOption {
type = types.int;
default = 8080;
description = ''
The port for exhibitor to listen on and communicate with other exhibitors.
'';
};
baseDir = mkOption {
type = types.str;
default = "/var/exhibitor";
description = ''
Baseline directory for exhibitor runtime config.
'';
};
configType = mkOption {
type = types.enum [ "file" "s3" "zookeeper" "none" ];
description = ''
Which configuration type you want to use. Additional config will be
required depending on which type you are using.
'';
};
hostname = mkOption {
type = types.nullOr types.str;
description = ''
Hostname to use and advertise
'';
default = null;
};
nodeModification = mkOption {
type = types.bool;
description = ''
Whether the Explorer UI will allow nodes to be modified (use with caution).
'';
default = true;
};
configCheckMs = mkOption {
type = types.int;
description = ''
Period (ms) to check for shared config updates.
'';
default = 30000;
};
headingText = mkOption {
type = types.nullOr types.str;
description = ''
Extra text to display in UI header
'';
default = null;
};
jqueryStyle = mkOption {
type = types.enum [ "red" "black" "custom" ];
description = ''
Styling used for the JQuery-based UI.
'';
default = "red";
};
logLines = mkOption {
type = types.int;
description = ''
Max lines of logging to keep in memory for display.
'';
default = 1000;
};
servo = mkOption {
type = types.bool;
description = ''
ZooKeeper will be queried once a minute for its state via the 'mntr' four
letter word (this requires ZooKeeper 3.4.x+). Servo will be used to publish
this data via JMX.
'';
default = false;
};
timeout = mkOption {
type = types.int;
description = ''
Connection timeout (ms) for ZK connections.
'';
default = 30000;
};
autoManageInstances = mkOption {
type = types.bool;
description = ''
Automatically manage ZooKeeper instances in the ensemble
'';
default = false;
};
zkDataDir = mkOption {
type = types.str;
default = "${cfg.baseDir}/zkData";
description = ''
The Zookeeper data directory
'';
};
zkLogDir = mkOption {
type = types.path;
default = "${cfg.baseDir}/zkLogs";
description = ''
The Zookeeper logs directory
'';
};
extraConf = mkOption {
type = types.str;
default = "";
description = ''
Extra Exhibitor configuration to put in the ZooKeeper config file.
'';
};
zkExtraCfg = mkOption {
type = types.str;
default = ''initLimit=5&syncLimit=2&tickTime=2000'';
description = ''
Extra options to pass into Zookeeper
'';
};
zkClientPort = mkOption {
type = types.int;
default = 2181;
description = ''
Zookeeper client port
'';
};
zkConnectPort = mkOption {
type = types.int;
default = 2888;
description = ''
The port to use for followers to talk to each other.
'';
};
zkElectionPort = mkOption {
type = types.int;
default = 3888;
description = ''
The port for Zookeepers to use for leader election.
'';
};
zkCleanupPeriod = mkOption {
type = types.int;
default = 0;
description = ''
How often (in milliseconds) to run the Zookeeper log cleanup task.
'';
};
zkServersSpec = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Zookeeper server spec for all servers in the ensemble.
'';
example = [ "S:1:zk1.example.com" "S:2:zk2.example.com" "S:3:zk3.example.com" "O:4:zk-observer.example.com" ];
};
# Backup options
s3Backup = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable backups to S3
'';
};
fileSystemBackup = mkOption {
type = types.bool;
default = false;
description = ''
Enables file system backup of ZooKeeper log files
'';
};
# Options for using zookeeper configType
zkConfigConnect = mkOption {
type = types.listOf types.str;
description = ''
The initial connection string for ZooKeeper shared config storage
'';
example = ["host1:2181" "host2:2181"];
};
zkConfigExhibitorPath = mkOption {
type = types.string;
description = ''
If the ZooKeeper shared config is also running Exhibitor, the URI path for the REST call
'';
default = "/";
};
zkConfigExhibitorPort = mkOption {
type = types.nullOr types.int;
description = ''
If the ZooKeeper shared config is also running Exhibitor, the port that
Exhibitor is listening on. IMPORTANT: if this value is not set it implies
that Exhibitor is not being used on the ZooKeeper shared config.
'';
};
zkConfigPollMs = mkOption {
type = types.int;
description = ''
The period in ms to check for changes in the config ensemble
'';
default = 10000;
};
zkConfigRetry = {
sleepMs = mkOption {
type = types.int;
default = 1000;
description = ''
Retry sleep time connecting to the ZooKeeper config
'';
};
retryQuantity = mkOption {
type = types.int;
default = 3;
description = ''
Retries connecting to the ZooKeeper config
'';
};
};
zkConfigZPath = mkOption {
type = types.str;
description = ''
The base ZPath that Exhibitor should use
'';
example = "/exhibitor/config";
};
# Config options for s3 configType
s3Config = {
bucketName = mkOption {
type = types.str;
description = ''
Bucket name to store config
'';
};
objectKey = mkOption {
type = types.str;
description = ''
S3 key name to store the config
'';
};
configPrefix = mkOption {
type = types.str;
description = ''
When using AWS S3 shared config files, the prefix to use for values such as locks
'';
default = "exhibitor-";
};
};
# The next two are used for either s3backup or s3 configType
s3Credentials = mkOption {
type = types.nullOr types.path;
description = ''
Optional credentials to use for s3backup or s3config. Argument is the path
to an AWS credential properties file with two properties:
com.netflix.exhibitor.s3.access-key-id and com.netflix.exhibitor.s3.access-secret-key
'';
default = null;
};
s3Region = mkOption {
type = types.nullOr types.str;
description = ''
Optional region for S3 calls
'';
default = null;
};
# Config options for file config type
fsConfigDir = mkOption {
type = types.path;
description = ''
Directory to store Exhibitor properties (cannot be used with s3config).
Exhibitor uses file system locks so you can specify a shared location
so as to enable complete ensemble management.
'';
};
fsConfigLockPrefix = mkOption {
type = types.str;
description = ''
A prefix for a locking mechanism used in conjunction with fsconfigdir
'';
default = "exhibitor-lock-";
};
fsConfigName = mkOption {
type = types.str;
description = ''
The name of the file to store config in
'';
default = "exhibitor.properties";
};
};
};
config = mkIf cfg.enable {
systemd.services.exhibitor = {
description = "Exhibitor Daemon";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = {
ZOO_LOG_DIR = cfg.baseDir;
};
serviceConfig = {
/***
Exhibitor is a bit un-nixy. It wants to present to you a user interface in order to
mutate the configuration of both itself and ZooKeeper, and to coordinate changes
among the members of the Zookeeper ensemble. I'm going for a different approach here,
which is to manage all the configuration via nix and have it write out the configuration
files that exhibitor will use, and to reduce the amount of inter-exhibitor orchestration.
***/
ExecStart = ''
${pkgs.exhibitor}/bin/startExhibitor.sh ${cliOptions}
'';
User = "zookeeper";
PermissionsStartOnly = true;
};
# This is a bit wonky, but the reason for this is that Exhibitor tries to write to
# ${cfg.baseDir}/zookeeper/bin/../conf/zoo.cfg
# I want everything but the conf directory to be in the immutable nix store, and I want defaults
# from the nix store
# If I symlink the bin directory in, then bin/../ will resolve to the parent of the symlink in the
# immutable nix store. Bind mounting a writable conf over the existing conf might work, but it gets very
# messy with trying to copy the existing out into a mutable store.
# Another option is to try to patch upstream exhibitor, but the current package just pulls down the
# prebuild JARs off of Maven, rather than building them ourselves, as Maven support in Nix isn't
# very mature. So, it seems like a reasonable compromise is to just copy out of the immutable store
# just before starting the service, so we're running binaries from the immutable store, but we work around
# Exhibitor's desire to mutate its current installation.
preStart = ''
mkdir -m 0700 -p ${cfg.baseDir}/zookeeper
# Not doing a chown -R to keep the base ZK files owned by root
chown zookeeper ${cfg.baseDir} ${cfg.baseDir}/zookeeper
cp -Rf ${pkgs.zookeeper}/* ${cfg.baseDir}/zookeeper
chown -R zookeeper ${cfg.baseDir}/zookeeper/conf
chmod -R u+w ${cfg.baseDir}/zookeeper/conf
'';
};
users.extraUsers = singleton {
name = "zookeeper";
uid = config.ids.uids.zookeeper;
description = "Zookeeper daemon user";
home = cfg.baseDir;
};
};
}

View File

@ -42,4 +42,5 @@ in {
};
meta.maintainers = with maintainers; [ gnidorah ];
}

View File

@ -439,6 +439,8 @@ in {
environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH;
path = with pkgs; [
gitAndTools.git
gnutar
gzip
openssh
gitlab-workhorse
];

View File

@ -62,8 +62,7 @@ let
name = "nixos-manual";
desktopName = "NixOS Manual";
genericName = "View NixOS documentation in a web browser";
# TODO: find a better icon (Nix logo + help overlay?)
icon = "system-help";
icon = "nix-snowflake";
exec = "${helpScript}/bin/nixos-help";
categories = "System";
};
@ -115,7 +114,7 @@ in
environment.systemPackages =
[ manual.manual helpScript ]
++ optional config.services.xserver.enable desktopItem
++ optionals config.services.xserver.enable [desktopItem pkgs.nixos-icons]
++ optional config.programs.man.enable manual.manpages;
boot.extraTTYs = mkIf cfg.showManual ["tty${toString cfg.ttyNumber}"];

View File

@ -1,110 +0,0 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.rippleRest;
configFile = pkgs.writeText "ripple-rest-config.json" (builtins.toJSON {
config_version = "2.0.3";
debug = cfg.debug;
port = cfg.port;
host = cfg.host;
ssl_enabled = cfg.ssl.enable;
ssl = {
key_path = cfg.ssl.keyPath;
cert_path = cfg.ssl.certPath;
reject_unathorized = cfg.ssl.rejectUnathorized;
};
db_path = cfg.dbPath;
max_transaction_fee = cfg.maxTransactionFee;
rippled_servers = cfg.rippleds;
});
in {
options.services.rippleRest = {
enable = mkEnableOption "ripple rest";
debug = mkEnableOption "debug for ripple-rest";
host = mkOption {
description = "Ripple rest host.";
default = "localhost";
type = types.str;
};
port = mkOption {
description = "Ripple rest port.";
default = 5990;
type = types.int;
};
ssl = {
enable = mkEnableOption "ssl";
keyPath = mkOption {
description = "Path to the ripple rest key file.";
default = null;
type = types.nullOr types.path;
};
certPath = mkOption {
description = "Path to the ripple rest cert file.";
default = null;
type = types.nullOr types.path;
};
rejectUnathorized = mkOption {
description = "Whether to reject unatohroized.";
default = true;
type = types.bool;
};
};
dbPath = mkOption {
description = "Ripple rest database path.";
default = "${cfg.dataDir}/ripple-rest.db";
type = types.path;
};
maxTransactionFee = mkOption {
description = "Ripple rest max transaction fee.";
default = 1000000;
type = types.int;
};
rippleds = mkOption {
description = "List of rippled servers.";
default = [
"wss://s1.ripple.com:443"
];
type = types.listOf types.str;
};
dataDir = mkOption {
description = "Ripple rest data directory.";
default = "/var/lib/ripple-rest";
type = types.path;
};
};
config = mkIf (cfg.enable) {
systemd.services.ripple-rest = {
wantedBy = [ "multi-user.target"];
after = ["network.target" ];
environment.NODE_PATH="${pkgs.ripple-rest}/lib/node_modules/ripple-rest/node_modules";
serviceConfig = {
ExecStart = "${pkgs.nodejs}/bin/node ${pkgs.ripple-rest}/lib/node_modules/ripple-rest/server/server.js --config ${configFile}";
User = "ripple-rest";
};
};
users.extraUsers.postgres = {
name = "ripple-rest";
uid = config.ids.uids.ripple-rest;
createHome = true;
home = cfg.dataDir;
};
};
}

View File

@ -0,0 +1,152 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.snapper;
in
{
options.services.snapper = {
snapshotInterval = mkOption {
type = types.str;
default = "hourly";
description = ''
Snapshot interval.
The format is described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
cleanupInterval = mkOption {
type = types.str;
default = "1d";
description = ''
Cleanup interval.
The format is described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>.
'';
};
filters = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
Global display difference filter. See man:snapper(8) for more details.
'';
};
configs = mkOption {
default = { };
example = literalExample {
"home" = {
subvolume = "/home";
extraConfig = ''
ALLOW_USERS="alice"
'';
};
};
description = ''
Subvolume configuration
'';
type = types.attrsOf (types.submodule {
options = {
subvolume = mkOption {
type = types.path;
description = ''
Path of the subvolume or mount point.
This path is a subvolume and has to contain a subvolume named
.snapshots.
See also man:snapper(8) section PERMISSIONS.
'';
};
fstype = mkOption {
type = types.enum [ "btrfs" ];
default = "btrfs";
description = ''
Filesystem type. Only btrfs is stable and tested.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional configuration next to SUBVOLUME and FSTYPE.
See man:snapper-configs(5).
'';
};
};
});
};
};
config = mkIf (cfg.configs != {}) (let
documentation = [ "man:snapper(8)" "man:snapper-configs(5)" ];
in {
environment = {
systemPackages = [ pkgs.snapper ];
# Note: snapper/config-templates/default is only needed for create-config
# which is not the NixOS way to configure.
etc = {
"sysconfig/snapper".text = ''
SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
'';
}
// (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
text = ''
${subvolume.extraConfig}
FSTYPE="${subvolume.fstype}"
SUBVOLUME="${subvolume.subvolume}"
'';
})) cfg.configs)
// (lib.optionalAttrs (cfg.filters != null) {
"snapper/filters/default.txt".text = cfg.filters;
});
};
services.dbus.packages = [ pkgs.snapper ];
systemd.services.snapper-timeline = {
description = "Timeline of Snapper Snapshots";
inherit documentation;
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
};
systemd.timers.snapper-timeline = {
description = "Timeline of Snapper Snapshots";
inherit documentation;
wantedBy = [ "basic.target" ];
timerConfig.OnCalendar = cfg.snapshotInterval;
};
systemd.services.snapper-cleanup = {
description = "Cleanup of Snapper Snapshots";
inherit documentation;
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
};
systemd.timers.snapper-cleanup = {
description = "Cleanup of Snapper Snapshots";
inherit documentation;
wantedBy = [ "basic.target" ];
timerConfig.OnBootSec = "10m";
timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
};
});
}

View File

@ -23,7 +23,7 @@ in
'';
serviceConfig = {
Type = "forking";
ExecStart = "/bin/sh -c '${pkgs.spice-vdagent}/bin/spice-vdagentd'";
ExecStart = "${pkgs.spice-vdagent}/bin/spice-vdagentd";
};
};
};

View File

@ -448,6 +448,8 @@ def cli(ctx):
"""
Manage Taskserver users and certificates
"""
if not IS_AUTO_CONFIG:
return
for path in (CA_KEY, CA_CERT, CRL_FILE):
if not os.path.exists(path):
msg = "CA setup not done or incomplete, missing file {}."

View File

@ -4,7 +4,7 @@ with lib;
let
cfg = config.services.zookeeper;
zookeeperConfig = ''
dataDir=${cfg.dataDir}
clientPort=${toString cfg.port}
@ -49,7 +49,7 @@ in {
default = 1;
type = types.int;
};
extraConf = mkOption {
description = "Extra configuration for Zookeeper.";
type = types.lines;
@ -119,7 +119,7 @@ in {
ExecStart = ''
${pkgs.jre}/bin/java \
-cp "${pkgs.zookeeper}/lib/*:${pkgs.zookeeper}/${pkgs.zookeeper.name}.jar:${configDir}" \
${toString cfg.extraCmdLineOptions} \
${escapeShellArgs cfg.extraCmdLineOptions} \
-Dzookeeper.datadir.autocreate=false \
${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
org.apache.zookeeper.server.quorum.QuorumPeerMain \

View File

@ -26,7 +26,9 @@ let
for file in $out/*; do
case "$file" in
plugin.sh) continue;;
*/plugin.sh|*/plugins.history)
chmod +x "$file"
continue;;
esac
# read magic makers from the file

View File

@ -0,0 +1,91 @@
{ config, lib, pkgs, ... }:
with builtins;
with lib;
let
cfg = config.services.osquery;
in
{
options = {
services.osquery = {
enable = mkEnableOption "osquery";
loggerPath = mkOption {
type = types.path;
description = "Base directory used for logging.";
default = "/var/log/osquery";
};
pidfile = mkOption {
type = types.path;
description = "Path used for pid file.";
default = "/var/osquery/osqueryd.pidfile";
};
utc = mkOption {
type = types.bool;
description = "Attempt to convert all UNIX calendar times to UTC.";
default = true;
};
databasePath = mkOption {
type = types.path;
description = "Path used for database file.";
default = "/var/osquery/osquery.db";
};
extraConfig = mkOption {
type = types.attrs // {
merge = loc: foldl' (res: def: recursiveUpdate res def.value) {};
};
description = "Extra config to be recursively merged into the JSON config file.";
default = { };
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.osquery ];
environment.etc."osquery/osquery.conf".text = toJSON (
recursiveUpdate {
options = {
config_plugin = "filesystem";
logger_plugin = "filesystem";
logger_path = cfg.loggerPath;
database_path = cfg.databasePath;
utc = cfg.utc;
};
} cfg.extraConfig
);
systemd.services.osqueryd = {
description = "The osquery Daemon";
after = [ "network.target" "syslog.service" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.osquery ];
preStart = ''
mkdir -p ${escapeShellArg cfg.loggerPath}
mkdir -p "$(dirname ${escapeShellArg cfg.pidfile})"
mkdir -p "$(dirname ${escapeShellArg cfg.databasePath})"
'';
serviceConfig = {
TimeoutStartSec = 0;
ExecStart = "${pkgs.osquery}/bin/osqueryd --logger_path ${escapeShellArg cfg.loggerPath} --pidfile ${escapeShellArg cfg.pidfile} --database_path ${escapeShellArg cfg.databasePath}";
KillMode = "process";
KillSignal = "SIGTERM";
Restart = "on-failure";
};
};
};
}

View File

@ -57,8 +57,8 @@ in {
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
-web.listen-address :${toString cfg.port} \
-config.file ${cfg.configFile} \
--web.listen-address :${toString cfg.port} \
--config.file ${cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";

View File

@ -83,6 +83,7 @@ in {
description = "Prometheus exporter for UniFi Controller metrics";
unitConfig.Documentation = "https://github.com/mdlayher/unifi_exporter";
wantedBy = [ "multi-user.target" ];
after = optional config.services.unifi.enable "unifi.service";
serviceConfig = {
User = "nobody";
Restart = "always";

View File

@ -49,6 +49,12 @@ in
description = "The data dir for IPFS";
};
defaultMode = mkOption {
description = "systemd service that is enabled by default";
type = types.enum [ "online" "offline" "norouting" ];
default = "online";
};
autoMigrate = mkOption {
type = types.bool;
default = false;
@ -147,10 +153,11 @@ in
systemd.services.ipfs = {
description = "IPFS Daemon";
wantedBy = [ "multi-user.target" ];
wantedBy = mkIf (cfg.defaultMode == "online") [ "multi-user.target" ];
after = [ "network.target" "local-fs.target" "ipfs-init.service" ];
conflicts = [ "ipfs-offline.service" ];
conflicts = [ "ipfs-offline.service" "ipfs-norouting.service"];
wants = [ "ipfs-init.service" ];
environment.IPFS_PATH = cfg.dataDir;
@ -169,9 +176,11 @@ in
systemd.services.ipfs-offline = {
description = "IPFS Daemon (offline mode)";
wantedBy = mkIf (cfg.defaultMode == "offline") [ "multi-user.target" ];
after = [ "local-fs.target" "ipfs-init.service" ];
conflicts = [ "ipfs.service" ];
conflicts = [ "ipfs.service" "ipfs-norouting.service"];
wants = [ "ipfs-init.service" ];
environment.IPFS_PATH = cfg.dataDir;
@ -186,5 +195,29 @@ in
RestartSec = 1;
};
};
systemd.services.ipfs-norouting = {
description = "IPFS Daemon (no routing mode)";
wantedBy = mkIf (cfg.defaultMode == "norouting") [ "multi-user.target" ];
after = [ "local-fs.target" "ipfs-init.service" ];
conflicts = [ "ipfs.service" "ipfs-offline.service"];
wants = [ "ipfs-init.service" ];
environment.IPFS_PATH = cfg.dataDir;
path = [ pkgs.ipfs ];
serviceConfig = {
ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags} --routing=none";
User = cfg.user;
Group = cfg.group;
Restart = "on-failure";
RestartSec = 1;
};
};
};
}

View File

@ -8,22 +8,21 @@ let
motdFile = builtins.toFile "rsyncd-motd" cfg.motd;
moduleConfig = name:
let module = getAttr name cfg.modules; in
"[${name}]\n " + (toString (
map
(key: "${key} = ${toString (getAttr key module)}\n")
(attrNames module)
));
foreach = attrs: f:
concatStringsSep "\n" (mapAttrsToList f attrs);
cfgFile = builtins.toFile "rsyncd.conf"
''
cfgFile = ''
${optionalString (cfg.motd != "") "motd file = ${motdFile}"}
${optionalString (cfg.address != "") "address = ${cfg.address}"}
${optionalString (cfg.port != 873) "port = ${toString cfg.port}"}
${cfg.extraConfig}
${toString (map moduleConfig (attrNames cfg.modules))}
'';
${foreach cfg.modules (name: module: ''
[${name}]
${foreach module (k: v:
"${k} = ${v}"
)}
'')}
'';
in
{
@ -84,6 +83,24 @@ in
};
};
user = mkOption {
type = types.str;
default = "root";
description = ''
The user to run the daemon as.
By default the daemon runs as root.
'';
};
group = mkOption {
type = types.str;
default = "root";
description = ''
The group to run the daemon as.
By default the daemon runs as root.
'';
};
};
};
@ -91,16 +108,17 @@ in
config = mkIf cfg.enable {
environment.etc = singleton {
source = cfgFile;
target = "rsyncd.conf";
};
environment.etc."rsyncd.conf".text = cfgFile;
systemd.services.rsyncd = {
description = "Rsync daemon";
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.rsync}/bin/rsync --daemon --no-detach";
restartTriggers = [ config.environment.etc."rsyncd.conf".source ];
serviceConfig = {
ExecStart = "${pkgs.rsync}/bin/rsync --daemon --no-detach";
User = cfg.user;
Group = cfg.group;
};
};
};
}

View File

@ -243,7 +243,7 @@ in
};
};
security.pam.services.sambda = {};
security.pam.services.samba = {};
})
];

View File

@ -237,13 +237,13 @@ in
# arguments to $(tahoe start). The node directory must come first,
# and arguments which alter Twisted's behavior come afterwards.
ExecStart = ''
${settings.package}/bin/tahoe start ${nodedir} -n -l- --pidfile=${pidfile}
${settings.package}/bin/tahoe start ${lib.escapeShellArg nodedir} -n -l- --pidfile=${lib.escapeShellArg pidfile}
'';
};
preStart = ''
if [ \! -d ${nodedir} ]; then
if [ ! -d ${lib.escapeShellArg nodedir} ]; then
mkdir -p /var/db/tahoe-lafs
tahoe create-introducer ${nodedir}
tahoe create-introducer ${lib.escapeShellArg nodedir}
fi
# Tahoe has created a predefined tahoe.cfg which we must now
@ -252,7 +252,7 @@ in
# we must do this on every prestart. Fixes welcome.
# rm ${nodedir}/tahoe.cfg
# ln -s /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg
cp /etc/tahoe-lafs/introducer-${node}.cfg ${nodedir}/tahoe.cfg
cp /etc/tahoe-lafs/introducer-"${node}".cfg ${lib.escapeShellArg nodedir}/tahoe.cfg
'';
});
users.extraUsers = flip mapAttrs' cfg.introducers (node: _:
@ -337,13 +337,13 @@ in
# arguments to $(tahoe start). The node directory must come first,
# and arguments which alter Twisted's behavior come afterwards.
ExecStart = ''
${settings.package}/bin/tahoe start ${nodedir} -n -l- --pidfile=${pidfile}
${settings.package}/bin/tahoe start ${lib.escapeShellArg nodedir} -n -l- --pidfile=${lib.escapeShellArg pidfile}
'';
};
preStart = ''
if [ \! -d ${nodedir} ]; then
if [ ! -d ${lib.escapeShellArg nodedir} ]; then
mkdir -p /var/db/tahoe-lafs
tahoe create-node --hostname=localhost ${nodedir}
tahoe create-node --hostname=localhost ${lib.escapeShellArg nodedir}
fi
# Tahoe has created a predefined tahoe.cfg which we must now
@ -351,8 +351,8 @@ in
# XXX I thought that a symlink would work here, but it doesn't, so
# we must do this on every prestart. Fixes welcome.
# rm ${nodedir}/tahoe.cfg
# ln -s /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg
cp /etc/tahoe-lafs/${node}.cfg ${nodedir}/tahoe.cfg
# ln -s /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg ${nodedir}/tahoe.cfg
cp /etc/tahoe-lafs/${lib.escapeShellArg node}.cfg ${lib.escapeShellArg nodedir}/tahoe.cfg
'';
});
users.extraUsers = flip mapAttrs' cfg.nodes (node: _:

View File

@ -22,6 +22,7 @@ let
${optionalString (interfaces!=null) "allow-interfaces=${concatStringsSep "," interfaces}"}
${optionalString (domainName!=null) "domain-name=${domainName}"}
allow-point-to-point=${yesNo allowPointToPoint}
${optionalString (cacheEntriesMax!=null) "cache-entries-max=${toString cacheEntriesMax}"}
[wide-area]
enable-wide-area=${yesNo wideArea}
@ -166,6 +167,15 @@ in
'';
};
cacheEntriesMax = mkOption {
default = null;
type = types.nullOr types.int;
description = ''
Number of resource records to be cached per interface. Use 0 to
disable caching. Avahi daemon defaults to 4096 if not set.
'';
};
};
};

View File

@ -7,6 +7,10 @@ let
cfg = config.services.bitlbee;
bitlbeeUid = config.ids.uids.bitlbee;
bitlbeePkg = if cfg.libpurple_plugins == []
then pkgs.bitlbee
else pkgs.bitlbee.override { enableLibPurple = true; };
bitlbeeConfig = pkgs.writeText "bitlbee.conf"
''
[settings]
@ -25,6 +29,12 @@ let
${cfg.extraDefaults}
'';
purple_plugin_path =
lib.concatMapStringsSep ":"
(plugin: "${plugin}/lib/pidgin/")
cfg.libpurple_plugins
;
in
{
@ -90,6 +100,15 @@ in
'';
};
libpurple_plugins = mkOption {
type = types.listOf types.package;
default = [];
example = literalExample "[ pkgs.purple-matrix ]";
description = ''
The list of libpurple plugins to install.
'';
};
configDir = mkOption {
default = "/var/lib/bitlbee";
type = types.path;
@ -144,14 +163,16 @@ in
};
systemd.services.bitlbee =
{ description = "BitlBee IRC to other chat networks gateway";
{
environment.PURPLE_PLUGIN_PATH = purple_plugin_path;
description = "BitlBee IRC to other chat networks gateway";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.User = "bitlbee";
serviceConfig.ExecStart = "${pkgs.bitlbee}/sbin/bitlbee -F -n -c ${bitlbeeConfig}";
serviceConfig.ExecStart = "${bitlbeePkg}/sbin/bitlbee -F -n -c ${bitlbeeConfig}";
};
environment.systemPackages = [ pkgs.bitlbee ];
environment.systemPackages = [ bitlbeePkg ];
};

View File

@ -320,6 +320,14 @@ in {
RuntimeDirectory = "turnserver";
User = "turnserver";
Group = "turnserver";
AmbientCapabilities =
mkIf (
cfg.listening-port < 1024 ||
cfg.alt-listening-port < 1024 ||
cfg.tls-listening-port < 1024 ||
cfg.alt-tls-listening-port < 1024 ||
cfg.min-port < 1024
) "cap_net_bind_service";
Restart = "on-abort";
};
};

View File

@ -1,17 +1,33 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.ddclient;
boolToStr = bool: if bool then "yes" else "no";
inherit (lib) mkOption mkIf singleton;
inherit (pkgs) ddclient;
stateDir = "/var/spool/ddclient";
ddclientUser = "ddclient";
ddclientFlags = "-foreground -file ${config.services.ddclient.configFile}";
ddclientPIDFile = "${stateDir}/ddclient.pid";
configText = ''
# This file can be used as a template for configFile or is automatically generated by Nix options.
daemon=${toString cfg.interval}
cache=${cfg.homeDir}/ddclient.cache
pid=/run/ddclient/ddclient.pid
foreground=NO
use=${cfg.use}
login=${cfg.username}
password=${cfg.password}
protocol=${cfg.protocol}
${let server = cfg.server; in
lib.optionalString (server != "") "server=${server}"}
ssl=${boolToStr cfg.ssl}
wildcard=YES
quiet=${boolToStr cfg.quiet}
verbose=${boolToStr cfg.verbose}
${cfg.domain}
${cfg.extraConfig}
'';
in
with lib;
{
###### interface
@ -28,6 +44,12 @@ in
'';
};
homeDir = mkOption {
default = "/var/lib/ddclient";
type = str;
description = "Home directory for the daemon user.";
};
domain = mkOption {
default = "";
type = str;
@ -52,6 +74,12 @@ in
'';
};
interval = mkOption {
default = 600;
type = int;
description = "The interval at which to run the check and update.";
};
configFile = mkOption {
default = "/etc/ddclient.conf";
type = path;
@ -126,37 +154,24 @@ in
config = mkIf config.services.ddclient.enable {
environment.systemPackages = [ ddclient ];
users = {
extraGroups.ddclient.gid = config.ids.gids.ddclient;
users.extraUsers = singleton {
name = ddclientUser;
uid = config.ids.uids.ddclient;
description = "ddclient daemon user";
home = stateDir;
extraUsers.ddclient = {
uid = config.ids.uids.ddclient;
description = "ddclient daemon user";
group = "ddclient";
home = cfg.homeDir;
createHome = true;
};
};
environment.etc."ddclient.conf" = {
enable = config.services.ddclient.configFile == "/etc/ddclient.conf";
enable = cfg.configFile == "/etc/ddclient.conf";
uid = config.ids.uids.ddclient;
gid = config.ids.gids.ddclient;
mode = "0600";
text = ''
# This file can be used as a template for configFile or is automatically generated by Nix options.
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}
${let server = config.services.ddclient.server; in
lib.optionalString (server != "") "server=${server}"}
ssl=${if config.services.ddclient.ssl then "yes" else "no"}
wildcard=YES
quiet=${if config.services.ddclient.quiet then "yes" else "no"}
verbose=${if config.services.ddclient.verbose then "yes" else "no"}
${config.services.ddclient.domain}
${config.services.ddclient.extraConfig}
'';
text = configText;
};
systemd.services.ddclient = {
@ -166,17 +181,14 @@ in
restartTriggers = [ config.environment.etc."ddclient.conf".source ];
serviceConfig = {
# Uncomment this if too many problems occur:
# Type = "forking";
User = ddclientUser;
Group = "nogroup"; #TODO get this to work
PermissionsStartOnly = "true";
PIDFile = ddclientPIDFile;
ExecStartPre = ''
${pkgs.stdenv.shell} -c "${pkgs.coreutils}/bin/mkdir -m 0755 -p ${stateDir} && ${pkgs.coreutils}/bin/chown ${ddclientUser} ${stateDir}"
'';
ExecStart = "${ddclient}/bin/ddclient ${ddclientFlags}";
#ExecStartPost = "${pkgs.coreutils}/bin/rm -r ${stateDir}"; # Should we have this?
RuntimeDirectory = "ddclient";
# we cannot run in forking mode as it swallows all the program output
Type = "simple";
User = "ddclient";
Group = "ddclient";
ExecStart = "${lib.getBin pkgs.ddclient}/bin/ddclient -foreground -file ${cfg.configFile}";
ProtectSystem = "full";
PrivateTmp = true;
};
};
};

View File

@ -82,14 +82,13 @@ in
};
resolverName = mkOption {
default = "dnscrypt.eu-nl";
default = "random";
example = "dnscrypt.eu-nl";
type = types.nullOr types.str;
description = ''
The name of the DNSCrypt resolver to use, taken from
<filename>${resolverList}</filename>. The default
resolver is located in Holland, supports DNS security
extensions, and <emphasis>claims</emphasis> to not
keep logs.
<filename>${resolverList}</filename>. The default is to
pick a random non-logging resolver that supports DNSSEC.
'';
};

View File

@ -4,6 +4,10 @@ with lib;
let
cfg = config.services.firefox.syncserver;
defaultDbLocation = "/var/db/firefox-sync-server/firefox-sync-server.db";
defaultSqlUri = "sqlite:///${defaultDbLocation}";
syncServerIni = pkgs.writeText "syncserver.ini" ''
[DEFAULT]
overrides = ${cfg.privateConfig}
@ -25,6 +29,7 @@ let
backend = tokenserver.verifiers.LocalVerifier
audiences = ${removeSuffix "/" cfg.publicUrl}
'';
in
{
@ -65,6 +70,18 @@ in
'';
};
user = mkOption {
type = types.str;
default = "syncserver";
description = "User account under which syncserver runs.";
};
group = mkOption {
type = types.str;
default = "syncserver";
description = "Group account under which syncserver runs.";
};
publicUrl = mkOption {
type = types.str;
default = "http://localhost:5000/";
@ -85,7 +102,7 @@ in
sqlUri = mkOption {
type = types.str;
default = "sqlite:////var/db/firefox-sync-server.db";
default = defaultSqlUri;
example = "postgresql://scott:tiger@localhost/test";
description = ''
The location of the database. This URL is composed of
@ -119,22 +136,52 @@ in
config = mkIf cfg.enable {
systemd.services.syncserver = {
systemd.services.syncserver = let
syncServerEnv = pkgs.python.withPackages(ps: with ps; [ syncserver pasteScript ]);
in {
after = [ "network.target" ];
description = "Firefox Sync Server";
wantedBy = [ "multi-user.target" ];
path = [ pkgs.pythonPackages.pasteScript pkgs.coreutils ];
environment.PYTHONPATH = "${pkgs.pythonPackages.syncserver}/lib/${pkgs.pythonPackages.python.libPrefix}/site-packages";
path = [ pkgs.coreutils syncServerEnv ];
serviceConfig = {
User = cfg.user;
Group = cfg.group;
PermissionsStartOnly = true;
};
preStart = ''
if ! test -e ${cfg.privateConfig}; then
umask u=rwx,g=x,o=x
mkdir -p $(dirname ${cfg.privateConfig})
mkdir -m 700 -p $(dirname ${cfg.privateConfig})
echo > ${cfg.privateConfig} '[syncserver]'
echo >> ${cfg.privateConfig} "secret = $(head -c 20 /dev/urandom | sha1sum | tr -d ' -')"
fi
chown ${cfg.user}:${cfg.group} ${cfg.privateConfig}
'' + optionalString (cfg.sqlUri == defaultSqlUri) ''
if ! test -e $(dirname ${defaultDbLocation}); then
mkdir -m 700 -p $(dirname ${defaultDbLocation})
chown ${cfg.user}:${cfg.group} $(dirname ${defaultDbLocation})
fi
# Move previous database file if it exists
oldDb="/var/db/firefox-sync-server.db"
if test -f $oldDb; then
mv $oldDb ${defaultDbLocation}
chown ${cfg.user}:${cfg.group} ${defaultDbLocation}
fi
'';
serviceConfig.ExecStart = "${pkgs.pythonPackages.pasteScript}/bin/paster serve ${syncServerIni}";
serviceConfig.ExecStart = "${syncServerEnv}/bin/paster serve ${syncServerIni}";
};
users.extraUsers = optionalAttrs (cfg.user == "syncserver")
(singleton {
name = "syncserver";
group = cfg.group;
isSystemUser = true;
});
users.extraGroups = optionalAttrs (cfg.group == "syncserver")
(singleton {
name = "syncserver";
});
};
}

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