Merge branch 'master' into fetchurl-no-hash

gstqt5
Matthew Bauer 2020-07-06 14:40:49 -04:00 committed by GitHub
commit 669eb09bd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2717 changed files with 46003 additions and 26415 deletions

3
.github/CODEOWNERS vendored
View File

@ -193,3 +193,6 @@
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman
/nixos/modules/virtualisation/podman.nix @NixOS/podman
/nixos/tests/podman.nix @NixOS/podman
# Blockchains
/pkgs/applications/blockchains @mmahut

32
.github/stale.yml vendored
View File

@ -9,17 +9,33 @@ exemptLabels:
# Label to use when marking an issue as stale
staleLabel: "2.status: stale"
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: |
Thank you for your contributions.
pulls:
markComment: |
Hello, I'm a bot and I thank you in the name of the community for your contributions.
This has been automatically marked as stale because it has had no activity for 180 days.
Nixpkgs is a busy repository, and unfortunately sometimes PRs get left behind for too long. Nevertheless, we'd like to help committers reach the PRs that are still important. This PR has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human.
If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.
If this is still important to you and you'd like to remove the stale label, we ask that you leave a comment. Your comment can be as simple as "still important to me". But there's a bit more you can do:
Here are suggestions that might help resolve this more quickly:
If you received an approval by an unpriviledged maintainer and you are just waiting for a merge, you can @ mention someone with merge permissions and ask them to help. You might be able to find someone relevant by using [Git blame](https://git-scm.com/docs/git-blame) on the relevant files, or via [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file). You can see if someone's a member of the [nixpkgs-committers](https://github.com/orgs/NixOS/teams/nixpkgs-committers) team, by hovering with the mouse over their username on the web interface, or by searching them directly on [the list](https://github.com/orgs/NixOS/teams/nixpkgs-committers).
If your PR wasn't reviewed at all, it might help to find someone who's perhaps a user of the package or module you are changing, or alternatively, ask once more for a review by the maintainer of the package/module this is about. If you don't know any, you can use [Git blame](https://git-scm.com/docs/git-blame) on the relevant files, or [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) to find someone who touched the relevant files in the past.
If your PR has had reviews and nevertheless got stale, make sure you've responded to all of the reviewer's requests / questions. Usually when PR authors show responsibility and dedication, reviewers (privileged or not) show dedication as well. If you've pushed a change, it's possible the reviewer wasn't notified about your push via email, so you can always [officially request them for a review](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/requesting-a-pull-request-review), or just @ mention them and say you've addressed their comments.
Lastly, you can always ask for help at [our Discourse Forum](https://discourse.nixos.org/), or more specifically, [at this thread](https://discourse.nixos.org/t/prs-in-distress/3604) or at [#nixos' IRC channel](https://webchat.freenode.net/#nixos).
issues:
markComment: |
Hello, I'm a bot and I thank you in the name of the community for opening this issue.
To help our human contributors focus on the most-relevant reports, I check up on old issues to see if they're still relevant. This issue has had no activity for 180 days, and so I marked it as stale, but you can rest assured it will never be closed by a non-human.
The community would appreciate your effort in checking if the issue is still valid. If it isn't, please close it.
If the issue persists, and you'd like to remove the stale label, you simply need to leave a comment. Your comment can be as simple as "still important to me". If you'd like it to get more attention, you can ask for help by searching for maintainers and people that previously touched related code and @ mention them in a comment. You can use [Git blame](https://git-scm.com/docs/git-blame) or [GitHub's web interface](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) on the relevant files to find them.
Lastly, you can always ask for help at [our Discourse Forum](https://discourse.nixos.org/) or at [#nixos' IRC channel](https://webchat.freenode.net/#nixos).
1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
2. Ask on the [NixOS Discourse](https://discourse.nixos.org/).
3. Ask on the [#nixos channel](irc://irc.freenode.net/#nixos) on [irc.freenode.net](https://freenode.net).
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -34,6 +34,7 @@ the main ones:
* [Nix](https://github.com/NixOS/nix) - the purely functional package manager
* [NixOps](https://github.com/NixOS/nixops) - the tool to remotely deploy NixOS machines
* [nixos-hardware](https://github.com/NixOS/nixos-hardware) - NixOS profiles to optimize settings for different hardware
* [Nix RFCs](https://github.com/NixOS/rfcs) - the formal process for making substantial changes to the community
* [NixOS homepage](https://github.com/NixOS/nixos-homepage) - the [NixOS.org](https://nixos.org) website
* [hydra](https://github.com/NixOS/hydra) - our continuous integration system

View File

@ -166,7 +166,7 @@ hello latest de2bf4786de6 About a minute ago 25.2MB
<title>buildLayeredImage</title>
<para>
Create a Docker image with many of the store paths being on their own layer to improve sharing between images.
Create a Docker image with many of the store paths being on their own layer to improve sharing between images. The image is realized into the Nix store as a gzipped tarball. Depending on the intended usage, many users might prefer to use <function>streamLayeredImage</function> instead, which this function uses internally.
</para>
<variablelist>
@ -327,6 +327,27 @@ pkgs.dockerTools.buildLayeredImage {
</section>
</section>
<section xml:id="ssec-pkgs-dockerTools-streamLayeredImage">
<title>streamLayeredImage</title>
<para>
Builds a script which, when run, will stream an uncompressed tarball of a Docker image to stdout. The arguments to this function are as for <function>buildLayeredImage</function>. This method of constructing an image does not realize the image into the Nix store, so it saves on IO and disk/cache space, particularly with large images.
</para>
<para>
The image produced by running the output script can be piped directly into <command>docker load</command>, to load it into the local docker daemon:
<screen><![CDATA[
$(nix-build) | docker load
]]></screen>
</para>
<para>
Alternatively, the image be piped via <command>gzip</command> into <command>skopeo</command>, e.g. to copy it into a registry:
<screen><![CDATA[
$(nix-build) | gzip --fast | skopeo copy docker-archive:/dev/stdin docker://some_docker_registry/myimage:tag
]]></screen>
</para>
</section>
<section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
<title>pullImage</title>

View File

@ -67,7 +67,17 @@ A derivation can then be written using `agdaPackages.mkDerivation`. This has sim
+ `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
+ `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
The build phase for `agdaPackages.mkDerivation` simply runs `agda` on the `Everything.agda` file. If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden (or a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the `Everything.agda` file). `agda` and the Agda libraries contained in `buildInputs` are made available during the build phase. The install phase simply copies all `.agda`, `.agdai` and `.agda-lib` files to the output directory. Again, this can be overridden.
### Building Agda packages
The default build phase for `agdaPackages.mkDerivation` simply runs `agda` on the `Everything.agda` file.
If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden.
Additionally, a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the `Everything.agda` file.
`agda` and the Agda libraries contained in `buildInputs` are made available during the build phase.
### Installing Agda packages
The default install phase copies agda source files, agda interface files (`*.agdai`) and `*.agda-lib` files to the output directory.
This can be overridden.
By default, agda sources are files ending on `.agda`, or literate agda files ending on `.lagda`, `.lagda.tex`, `.lagda.org`, `.lagda.md`, `.lagda.rst`. The list of recognised agda source extensions can be extended by setting the `extraExtensions` config variable.
To add an agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other agda libraries, so the top line of the `default.nix` can look like:
```

View File

@ -18,7 +18,7 @@
<xi:include href="idris.section.xml" />
<xi:include href="ios.section.xml" />
<xi:include href="java.xml" />
<xi:include href="lua.xml" />
<xi:include href="lua.section.xml" />
<xi:include href="node.section.xml" />
<xi:include href="ocaml.xml" />
<xi:include href="perl.xml" />

View File

@ -0,0 +1,252 @@
---
title: Lua
author: Matthieu Coudron
date: 2019-02-05
---
# User's Guide to Lua Infrastructure
## Using Lua
### Overview of Lua
Several versions of the Lua interpreter are available: luajit, lua 5.1, 5.2, 5.3.
The attribute `lua` refers to the default interpreter, it is also possible to refer to specific versions, e.g. `lua5_2` refers to Lua 5.2.
Lua libraries 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 Lua libraries for this specific
interpreter. E.g., the `busted` package corresponding to the default interpreter
is `lua.pkgs.busted`, and the lua 5.2 version is `lua5_2.pkgs.busted`.
The main package set contains aliases to these package sets, e.g.
`luaPackages` refers to `lua5_1.pkgs` and `lua52Packages` to
`lua5_2.pkgs`.
### Installing Lua and packages
#### Lua environment defined in separate `.nix` file
Create a file, e.g. `build.nix`, with the following expression
```nix
with import <nixpkgs> {};
lua5_2.withPackages (ps: with ps; [ busted luafilesystem ])
```
and install it in your profile with
```shell
nix-env -if build.nix
```
Now you can use the Lua interpreter, as well as the extra packages (`busted`,
`luafilesystem`) that you added to the environment.
#### Lua 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; {
myLuaEnv = lua5_2.withPackages (ps: with ps; [ busted luafilesystem ]);
};
}
```
and install it in your profile with
```shell
nix-env -iA nixpkgs.myLuaEnv
```
The environment is is installed by referring to the attribute, and considering
the `nixpkgs` channel was used.
#### Lua 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; [
(lua.withPackages(ps: with ps; [ busted luafilesystem ]))
];
}
```
### How to override a Lua package using overlays?
Use the following overlay template:
```nix
final: prev:
{
lua = prev.lua.override {
packageOverrides = luaself: luaprev: {
luarocks-nix = luaprev.luarocks-nix.overrideAttrs(oa: {
pname = "luarocks-nix";
src = /home/my_luarocks/repository;
});
};
luaPackages = lua.pkgs;
}
```
### Temporary Lua environment with `nix-shell`
There are two methods for loading a shell with Lua packages. The first and recommended method
is to create an environment with `lua.buildEnv` or `lua.withPackages` and load that. E.g.
```sh
$ nix-shell -p 'lua.withPackages(ps: with ps; [ busted luafilesystem ])'
```
opens a shell from which you can launch the interpreter
```sh
[nix-shell:~] lua
```
The other method, which is not recommended, does not create an environment and requires you to list the packages directly,
```sh
$ nix-shell -p lua.pkgs.busted lua.pkgs.luafilesystem
```
Again, it is possible to launch the interpreter from the shell.
The Lua interpreter has the attribute `pkgs` which contains all Lua libraries for that specific interpreter.
## Developing with Lua
Now that you know how to get a working Lua environment with Nix, it is time
to go forward and start actually developing with Lua. There are two ways to
package lua software, either it is on luarocks and most of it can be taken care
of by the luarocks2nix converter or the packaging has to be done manually.
Let's present the luarocks way first and the manual one in a second time.
### Packaging a library on luarocks
[Luarocks.org](www.luarocks.org) is the main repository of lua packages.
The site proposes two types of packages, the rockspec and the src.rock
(equivalent of a [rockspec](https://github.com/luarocks/luarocks/wiki/Rockspec-format) but with the source).
These packages can have different build types such as `cmake`, `builtin` etc .
Luarocks-based packages are generated in pkgs/development/lua-modules/generated-packages.nix from
the whitelist maintainers/scripts/luarocks-packages.csv and updated by running maintainers/scripts/update-luarocks-packages.
[luarocks2nix](https://github.com/nix-community/luarocks) is a tool capable of generating nix derivations from both rockspec and src.rock (and favors the src.rock).
The automation only goes so far though and some packages need to be customized.
These customizations go in `pkgs/development/lua-modules/overrides.nix`.
For instance if the rockspec defines `external_dependencies`, these need to be manually added in in its rockspec file then it won't work.
You can try converting luarocks packages to nix packages with the command `nix-shell -p luarocks-nix` and then `luarocks nix PKG_NAME`.
Nix rely on luarocks to install lua packages, basically it runs:
`luarocks make --deps-mode=none --tree $out`
#### Packaging a library manually
You can develop your package as you usually would, just don't forget to wrap it
within a `toLuaModule` call, for instance
```nix
mynewlib = toLuaModule ( stdenv.mkDerivation { ... });
```
There is also the `buildLuaPackage` function that can be used when lua modules
are not packaged for luarocks. You can see a few examples at `pkgs/top-level/lua-packages.nix`.
## Lua Reference
### Lua interpreters
Versions 5.1, 5.2 and 5.3 of the lua interpreter are available as
respectively `lua5_1`, `lua5_2` and `lua5_3`. Luajit is available too.
The Nix expressions for the interpreters can be found in `pkgs/development/interpreters/lua-5`.
#### Attributes on lua interpreters packages
Each interpreter has the following attributes:
- `interpreter`. Alias for `${pkgs.lua}/bin/lua`.
- `buildEnv`. Function to build lua interpreter environments with extra packages bundled together. See section *lua.buildEnv function* for usage and documentation.
- `withPackages`. Simpler interface to `buildEnv`.
- `pkgs`. Set of Lua packages for that specific interpreter. The package set can be modified by overriding the interpreter and passing `packageOverrides`.
#### `buildLuarocksPackage` function
The `buildLuarocksPackage` function is implemented in `pkgs/development/interpreters/lua-5/build-lua-package.nix`
The following is an example:
```nix
luaposix = buildLuarocksPackage {
pname = "luaposix";
version = "34.0.4-1";
src = fetchurl {
url = "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/luaposix-34.0.4-1.src.rock";
sha256 = "0yrm5cn2iyd0zjd4liyj27srphvy0gjrjx572swar6zqr4dwjqp2";
};
disabled = (luaOlder "5.1") || (luaAtLeast "5.4");
propagatedBuildInputs = [ bit32 lua std_normalize ];
meta = with stdenv.lib; {
homepage = "https://github.com/luaposix/luaposix/";
description = "Lua bindings for POSIX";
maintainers = with maintainers; [ vyp lblasc ];
license.fullName = "MIT/X11";
};
};
```
The `buildLuarocksPackage` delegates most tasks to luarocks:
* it adds `luarocks` as an unpacker for `src.rock` files (zip files really).
* configurePhase` writes a temporary luarocks configuration file which location
is exported via the environment variable `LUAROCKS_CONFIG`.
* the `buildPhase` does nothing.
* `installPhase` calls `luarocks make --deps-mode=none --tree $out` to build and
install the package
* In the `postFixup` phase, the `wrapLuaPrograms` bash function is called to
wrap all programs in the `$out/bin/*` directory to include `$PATH`
environment variable and add dependent libraries to script's `LUA_PATH` and
`LUA_CPATH`.
By default `meta.platforms` is set to the same value as the interpreter unless overridden otherwise.
#### `buildLuaApplication` function
The `buildLuaApplication` function is practically the same as `buildLuaPackage`.
The difference is that `buildLuaPackage` by default prefixes the names of the packages with the version of the interpreter.
Because with an application we're not interested in multiple version the prefix is dropped.
#### lua.withPackages function
The `lua.withPackages` takes a function as an argument that is passed the set of lua packages and returns the list of packages to be included in the environment.
Using the `withPackages` function, the previous example for the luafilesystem environment can be written like this:
```nix
with import <nixpkgs> {};
lua.withPackages (ps: [ps.luafilesystem])
```
`withPackages` passes the correct package set for the specific interpreter version as an argument to the function. In the above example, `ps` equals `luaPackages`.
But you can also easily switch to using `lua5_2`:
```nix
with import <nixpkgs> {};
lua5_2.withPackages (ps: [ps.lua])
```
Now, `ps` is set to `lua52Packages`, matching the version of the interpreter.
### Possible Todos
* export/use version specific variables such as `LUA_PATH_5_2`/`LUAROCKS_CONFIG_5_2`
* let luarocks check for dependencies via exporting the different rocktrees in temporary config
### Lua Contributing guidelines
Following rules should be respected:
* Make sure libraries build for all Lua interpreters.
* Commit names of Lua libraries should reflect that they are Lua libraries, so write for example `luaPackages.luafilesystem: 1.11 -> 1.12`.

View File

@ -1,36 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="sec-language-lua">
<title>Lua</title>
<para>
Lua packages are built by the <varname>buildLuaPackage</varname> function. This function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules/generic/default.nix"> <filename>pkgs/development/lua-modules/generic/default.nix</filename></link> and works similarly to <varname>buildPerlPackage</varname>. (See <xref linkend="sec-language-perl"/> for details.)
</para>
<para>
Lua packages are defined in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/lua-packages.nix"><filename>pkgs/top-level/lua-packages.nix</filename></link>. Most of them are simple. For example:
<programlisting>
fileSystem = buildLuaPackage {
name = "filesystem-1.6.2";
src = fetchurl {
url = "https://github.com/keplerproject/luafilesystem/archive/v1_6_2.tar.gz";
sha256 = "1n8qdwa20ypbrny99vhkmx8q04zd2jjycdb5196xdhgvqzk10abz";
};
meta = {
homepage = "https://github.com/keplerproject/luafilesystem";
hydraPlatforms = stdenv.lib.platforms.linux;
maintainers = with maintainers; [ flosse ];
};
};
</programlisting>
</para>
<para>
Though, more complicated package should be placed in a seperate file in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules"><filename>pkgs/development/lua-modules</filename></link>.
</para>
<para>
Lua packages accept additional parameter <varname>disabled</varname>, which defines the condition of disabling package from luaPackages. For example, if package has <varname>disabled</varname> assigned to <literal>lua.luaversion != "5.1"</literal>, it will not be included in any luaPackages except lua51Packages, making it only be built for lua 5.1.
</para>
</section>

View File

@ -643,7 +643,7 @@ and in this case the `python38` interpreter is automatically used.
Versions 2.7, 3.5, 3.6, 3.7 and 3.8 of the CPython interpreter are available as
respectively `python27`, `python35`, `python36`, `python37` and `python38`. The
aliases `python2` and `python3` correspond to respectively `python27` and
`python37`. The default interpreter, `python`, maps to `python2`. The PyPy
`python38`. The default interpreter, `python`, maps to `python2`. The PyPy
interpreters compatible with Python 2.7 and 3 are available as `pypy27` and
`pypy3`, with aliases `pypy2` mapping to `pypy27` and `pypy` mapping to `pypy2`.
The Nix expressions for the interpreters can be found in
@ -764,9 +764,6 @@ following are specific to `buildPythonPackage`:
* `dontWrapPythonPrograms ? false`: Skip wrapping of Python programs.
* `permitUserSite ? false`: Skip setting the `PYTHONNOUSERSITE` environment
variable in wrapped programs.
* `installFlags ? []`: A list of strings. Arguments to be passed to `pip
install`. To pass options to `python setup.py install`, use
`--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"]`.
* `format ? "setuptools"`: Format of the source. Valid options are
`"setuptools"`, `"pyproject"`, `"flit"`, `"wheel"`, and `"other"`.
`"setuptools"` is for when the source has a `setup.py` and `setuptools` is
@ -782,6 +779,9 @@ following are specific to `buildPythonPackage`:
* `namePrefix`: Prepends text to `${name}` parameter. In case of libraries, this
defaults to `"python3.8-"` for Python 3.8, etc., and in case of applications
to `""`.
* `pipInstallFlags ? []`: A list of strings. Arguments to be passed to `pip
install`. To pass options to `python setup.py install`, use
`--install-option`. E.g., `pipInstallFlags=["--install-option='--cpp_implementation'"]`.
* `pythonPath ? []`: List of packages to be added into `$PYTHONPATH`. Packages
in `pythonPath` are not propagated (contrary to `propagatedBuildInputs`).
* `preShellHook`: Hook to execute commands before `shellHook`.

View File

@ -75,6 +75,72 @@ pkgs.rustPlatform.buildRustPackage {
}
```
### Running package tests
When using `buildRustPackage`, the `checkPhase` is enabled by default and runs
`cargo test` on the package to build. To make sure that we don't compile the
sources twice and to actually test the artifacts that will be used at runtime,
the tests will be ran in the `release` mode by default.
However, in some cases the test-suite of a package doesn't work properly in the
`release` mode. For these situations, the mode for `checkPhase` can be changed like
so:
```nix
rustPlatform.buildRustPackage {
/* ... */
checkType = "debug";
}
```
Please note that the code will be compiled twice here: once in `release` mode
for the `buildPhase`, and again in `debug` mode for the `checkPhase`.
#### Tests relying on the structure of the `target/` directory
Some tests may rely on the structure of the `target/` directory. Those tests
are likely to fail because we use `cargo --target` during the build. This means that
the artifacts
[are stored in `target/<architecture>/release/`](https://doc.rust-lang.org/cargo/guide/build-cache.html),
rather than in `target/release/`.
This can only be worked around by patching the affected tests accordingly.
#### Disabling package-tests
In some instances, it may be necessary to disable testing altogether (with `doCheck = false;`):
* If no tests exist -- the `checkPhase` should be explicitly disabled to skip
unnecessary build steps to speed up the build.
* If tests are highly impure (e.g. due to network usage).
There will obviously be some corner-cases not listed above where it's sensible to disable tests.
The above are just guidelines, and exceptions may be granted on a case-by-case basis.
However, please check if it's possible to disable a problematic subset of the
test suite and leave a comment explaining your reasoning.
### Building a package in `debug` mode
By default, `buildRustPackage` will use `release` mode for builds. If a package
should be built in `debug` mode, it can be configured like so:
```nix
rustPlatform.buildRustPackage {
/* ... */
buildType = "debug";
}
```
In this scenario, the `checkPhase` will be ran in `debug` mode as well.
### Custom `build`/`install`-procedures
Some packages may use custom scripts for building/installing, e.g. with a `Makefile`.
In these cases, it's recommended to override the `buildPhase`/`installPhase`/`checkPhase`.
Otherwise, some steps may fail because of the modified directory structure of `target/`.
### Building a crate with an absent or out-of-date Cargo.lock file
`buildRustPackage` needs a `Cargo.lock` file to get all dependencies in the

View File

@ -85,19 +85,19 @@
<title>Installing packages on unsupported systems</title>
<para>
There are also two ways to try compiling a package which has been marked as unsuported for the given system.
There are also two ways to try compiling a package which has been marked as unsupported for the given system.
</para>
<itemizedlist>
<listitem>
<para>
For allowing the build of a broken package once, you can use an environment variable for a single invocation of the nix tools:
For allowing the build of an unsupported package once, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1</programlisting>
</para>
</listitem>
<listitem>
<para>
For permanently allowing broken packages to be built, you may add <literal>allowUnsupportedSystem = true;</literal> to your user's configuration file, like this:
For permanently allowing unsupported packages to be built, you may add <literal>allowUnsupportedSystem = true;</literal> to your user's configuration file, like this:
<programlisting>
{
allowUnsupportedSystem = true;
@ -387,7 +387,7 @@ fi
</screen>
<para>
Now just run <literal>source $HOME/.profile</literal> and you can starting loading man pages from your environent.
Now just run <literal>source $HOME/.profile</literal> and you can starting loading man pages from your environment.
</para>
</section>

View File

@ -253,7 +253,7 @@ rec {
/* Like `mapAttrsRecursive', but it takes an additional predicate
function that tells it whether to recursive into an attribute
set. If it returns false, `mapAttrsRecursiveCond' does not
recurse, but does apply the map function. It is returns true, it
recurse, but does apply the map function. If it returns true, it
does recurse, and does not apply the map function.
Type:
@ -469,6 +469,7 @@ rec {
getBin = getOutput "bin";
getLib = getOutput "lib";
getDev = getOutput "dev";
getMan = getOutput "man";
/* Pick the outputs of packages to place in buildInputs */
chooseDevOutputs = drvs: builtins.map getDev drvs;

View File

@ -77,7 +77,7 @@ let
genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
recursiveUpdate matchAttrs overrideExisting getOutput getBin
getLib getDev chooseDevOutputs zipWithNames zip
getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs;
inherit (lists) singleton forEach foldr fold foldl foldl' imap0 imap1
concatMap flatten remove findSingle findFirst any all count

View File

@ -8,10 +8,10 @@ with lib;
option = x:
x // { optional = true; };
yes = { tristate = "y"; };
no = { tristate = "n"; };
module = { tristate = "m"; };
freeform = x: { freeform = x; };
yes = { tristate = "y"; optional = false; };
no = { tristate = "n"; optional = false; };
module = { tristate = "m"; optional = false; };
freeform = x: { freeform = x; optional = false; };
/*
Common patterns/legacy used in common-config/hardened/config.nix

View File

@ -95,6 +95,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''BSD 2-clause "Simplified" License'';
};
bsd2Patent = spdx {
spdxId = "BSD-2-Clause-Patent";
fullName = ''BSD-2-Clause Plus Patent License'';
};
bsd3 = spdx {
spdxId = "BSD-3-Clause";
fullName = ''BSD 3-clause "New" or "Revised" License'';
@ -276,6 +281,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "European Union Public License 1.2";
};
fdl11 = spdx {
spdxId = "GFDL-1.1-only";
fullName = "GNU Free Documentation License v1.1 only";
};
fdl12 = spdx {
spdxId = "GFDL-1.2-only";
fullName = "GNU Free Documentation License v1.2 only";
@ -457,6 +467,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "GNU Lesser General Public License v3.0 or later";
};
lgpllr = spdx {
spdxId = "LGPLLR";
fullName = "Lesser General Public License For Linguistic Resources";
};
libpng = spdx {
spdxId = "Libpng";
fullName = "libpng License";
@ -477,6 +492,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
url = "https://opensource.franz.com/preamble.html";
};
llvm-exception = spdx {
spdxId = "LLVM-exception";
fullName = "LLVM Exception"; # LLVM exceptions to the Apache 2.0 License
};
lppl12 = spdx {
spdxId = "LPPL-1.2";
fullName = "LaTeX Project Public License v1.2";
@ -540,6 +560,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = "Non-Profit Open Software License 3.0";
};
obsidian = {
fullName = "Obsidian End User Agreement";
url = "https://obsidian.md/eula";
free = false;
};
ocamlpro_nc = {
fullName = "OCamlPro Non Commercial license version 1";
url = "https://alt-ergo.ocamlpro.com/http/alt-ergo-2.2.0/OCamlPro-Non-Commercial-License.pdf";

View File

@ -139,6 +139,12 @@
githubId = 1517066;
name = "Aiken Cairncross";
};
aciceri = {
name = "Andrea Ciceri";
email = "andrea.ciceri@autistici.org";
github = "aciceri";
githubId = 2318843;
};
acowley = {
email = "acowley@gmail.com";
github = "acowley";
@ -277,6 +283,12 @@
githubId = 273837;
name = "Mateusz Czapliński";
};
akamaus = {
email = "dmitryvyal@gmail.com";
github = "akamaus";
githubId = 58955;
name = "Dmitry Vyal";
};
akaWolf = {
email = "akawolf0@gmail.com";
github = "akaWolf";
@ -313,6 +325,12 @@
githubId = 2387841;
name = "Alexander Bakker";
};
alexbiehl = {
email = "alexbiehl@gmail.com";
github = "alexbiehl";
githubId = 1876617;
name = "Alex Biehl";
};
alexchapman = {
email = "alex@farfromthere.net";
github = "AJChapman";
@ -1013,6 +1031,12 @@
githubId = 5718007;
name = "Bastian Köcher";
};
blaggacao = {
name = "David Arnold";
email = "dar@xoe.solutions";
github = "blaggacao";
githubId = 7548295;
};
blanky0230 = {
email = "blanky0230@gmail.com";
github = "blanky0230";
@ -1121,6 +1145,12 @@
githubId = 7716744;
name = "Berno Strik";
};
breakds = {
email = "breakds@gmail.com";
github = "breakds";
githubId = 1111035;
name = "Break Yang";
};
brettlyons = {
email = "blyons@fastmail.com";
github = "brettlyons";
@ -1157,6 +1187,12 @@
githubId = 24417923;
name = "Renaud";
};
c00w = {
email = "nix@daedrum.net";
github = "c00w";
githubId = 486199;
name = "Colin";
};
c0deaddict = {
email = "josvanbakel@protonmail.com";
github = "c0deaddict";
@ -1580,6 +1616,12 @@
githubId = 32609395;
name = "B YI";
};
conradmearns = {
email = "conradmearns+github@pm.me";
github = "ConradMearns";
githubId = 5510514;
name = "Conrad Mearns";
};
couchemar = {
email = "couchemar@yandex.ru";
github = "couchemar";
@ -1610,6 +1652,12 @@
githubId = 12202789;
name = "CrazedProgrammer";
};
cript0nauta = {
email = "shareman1204@gmail.com";
github = "cript0nauta";
githubId = 1222362;
name = "Matías Lang";
};
cryptix = {
email = "cryptix@riseup.net";
github = "cryptix";
@ -1752,6 +1800,12 @@
email = "christoph.senjak@googlemail.com";
name = "Christoph-Simon Senjak";
};
david-sawatzke = {
email = "d-nix@sawatzke.dev";
github = "david-sawatzke";
githubId = 11035569;
name = "David Sawatzke";
};
david50407 = {
email = "me@davy.tw";
github = "david50407";
@ -2448,6 +2502,12 @@
githubId = 7432848;
name = "Daniel Albert";
};
eskytthe = {
email = "eskytthe@gmail.com";
github = "eskytthe";
githubId = 2544204;
name = "Erik Skytthe";
};
Esteth = {
email = "adam.copp@gmail.com";
name = "Adam Copp";
@ -2540,6 +2600,16 @@
githubId = 11909469;
name = "Fabian Geiselhart";
};
fabianhauser = {
email = "fabian.nixos@fh2.ch";
github = "fabianhauser";
githubId = 368799;
name = "Fabian Hauser";
keys = [{
longkeyid = "rsa4096/0x8A52A140BEBF7D2C";
fingerprint = "50B7 11F4 3DFD 2018 DCE6 E8D0 8A52 A140 BEBF 7D2C";
}];
};
fadenb = {
email = "tristan.helmich+nixos@gmail.com";
github = "fadenb";
@ -3496,6 +3566,12 @@
githubId = 117874;
name = "Jeroen de Haas";
};
jduan = {
name = "Jingjing Duan";
email = "duanjingjing@gmail.com";
github = "jduan";
githubId = 452450;
};
jefdaj = {
email = "jefdaj@gmail.com";
github = "jefdaj";
@ -3514,6 +3590,12 @@
githubId = 1608697;
name = "Jens Binkert";
};
jeremyschlatter = {
email = "github@jeremyschlatter.com";
github = "jeremyschlatter";
githubId = 5741620;
name = "Jeremy Schlatter";
};
jerith666 = {
email = "github@matt.mchenryfamily.org";
github = "jerith666";
@ -3646,12 +3728,24 @@
githubId = 41977;
name = "Joachim Fasting";
};
joachimschmidt557 = {
email = "joachim.schmidt557@outlook.com";
github = "joachimschmidt557";
githubId = 28556218;
name = "Joachim Schmidt";
};
joamaki = {
email = "joamaki@gmail.com";
github = "joamaki";
githubId = 1102396;
name = "Jussi Maki";
};
jobojeha = {
email = "jobojeha@jeppener.de";
github = "jobojeha";
githubId = 60272884;
name = "Jonathan Jeppener-Haltenhoff";
};
joelburget = {
email = "joelburget@gmail.com";
github = "joelburget";
@ -3855,6 +3949,12 @@
githubId = 11947756;
name = "Julien Dehos";
};
julm = {
email = "julm+nix@sourcephile.fr";
github = "ju1m";
githubId = 21160136;
name = "Julien Moutinho";
};
jumper149 = {
email = "felixspringer149@gmail.com";
github = "jumper149";
@ -3867,6 +3967,12 @@
githubId = 2396926;
name = "Justin Woo";
};
jwatt = {
email = "jwatt@broken.watch";
github = "jjwatt";
githubId = 2397327;
name = "Jesse Wattenbarger";
};
jwiegley = {
email = "johnw@newartisans.com";
github = "jwiegley";
@ -4962,6 +5068,10 @@
github = "mdlayher";
githubId = 1926905;
name = "Matt Layher";
keys = [{
longkeyid = "rsa2048/0x77BFE531397EDE94";
fingerprint = "D709 03C8 0BE9 ACDC 14F0 3BFB 77BF E531 397E DE94";
}];
};
meditans = {
email = "meditans@gmail.com";
@ -5027,6 +5137,12 @@
githubId = 223323;
name = "Miguel de la Cruz";
};
mgdm = {
email = "michael@mgdm.net";
github = "mgdm";
githubId = 71893;
name = "Michael Maclean";
};
mgregoire = {
email = "gregoire@martinache.net";
github = "M-Gregoire";
@ -5154,6 +5270,12 @@
fingerprint = "3196 83D3 9A1B 4DE1 3DC2 51FD FEA8 88C9 F5D6 4F62";
}];
};
mir06 = {
email = "armin.leuprecht@uni-graz.at";
github = "mir06";
githubId = 8479244;
name = "Armin Leuprecht";
};
mirdhyn = {
email = "mirdhyn@gmail.com";
github = "mirdhyn";
@ -6210,6 +6332,12 @@
fingerprint = "240B 57DE 4271 2480 7CE3 EAC8 4F74 D536 1C4C A31E";
}];
};
priegger = {
email = "philipp@riegger.name";
github = "priegger";
githubId = 228931;
name = "Philipp Riegger";
};
prikhi = {
email = "pavan.rikhi@gmail.com";
github = "prikhi";
@ -6364,6 +6492,12 @@
githubId = 131856;
name = "Arnout Engelen";
};
RaghavSood = {
email = "r@raghavsood.com";
github = "RaghavSood";
githubId = 903072;
name = "Raghav Sood";
};
rafaelgg = {
email = "rafael.garcia.gallego@gmail.com";
github = "rafaelgg";
@ -7068,6 +7202,12 @@
githubId = 24496705;
name = "Scott Hamilton";
};
ShamrockLee = {
name = "Shamrock Lee";
email = "44064051+ShamrockLee@users.noreply.github.com";
github = "ShamrockLee";
githubId = 44064051;
};
shanemikel = {
email = "shanepearlman@pm.me";
github = "shanemikel";
@ -7180,6 +7320,16 @@
githubId = 2770647;
name = "Simon Vandel Sillesen";
};
siriobalmelli = {
email = "sirio@b-ad.ch";
github = "siriobalmelli";
githubId = 23038812;
name = "Sirio Balmelli";
keys = [{
longkeyid = "ed25519/0xF72C4A887F9A24CA";
fingerprint = "B234 EFD4 2B42 FE81 EE4D 7627 F72C 4A88 7F9A 24CA";
}];
};
sivteck = {
email = "sivaram1992@gmail.com";
github = "sivteck";
@ -7754,6 +7904,12 @@
githubId = 1141680;
name = "Thane Gill";
};
TheBrainScrambler = {
email = "esthromeris@riseup.net";
github = "TheBrainScrambler";
githubId = 34945377;
name = "John Smith";
};
thedavidmeister = {
email = "thedavidmeister@gmail.com";
github = "thedavidmeister";
@ -8857,6 +9013,12 @@
githubId = 474343;
name = "Xavier Zwirtz";
};
ymarkus = {
name = "Yannick Markus";
email = "nixpkgs@ymarkus.dev";
github = "ymarkus";
githubId = 62380378;
};
ymeister = {
name = "Yuri Meister";
email = "47071325+ymeister@users.noreply.github.com";
@ -8869,4 +9031,16 @@
github = "cpcloud";
githubId = 417981;
};
davegallant = {
name = "Dave Gallant";
email = "davegallant@gmail.com";
github = "davegallant";
githubId = 4519234;
};
saulecabrera = {
name = "Saúl Cabrera";
email = "saulecabrera@gmail.com";
github = "saulecabrera";
githubId = 1423601;
};
}

View File

@ -2,7 +2,7 @@
# Download patches from debian project
# Usage $0 debian-patches.txt debian-patches.nix
# An example input and output files can be found in applications/graphics/xara/
# An example input and output files can be found in tools/graphics/plotutils
DEB_URL=https://sources.debian.org/data/main
declare -a deb_patches

View File

@ -12,12 +12,13 @@ compat53,,,,,vcunat
cosmo,,,,,marsam
coxpcall,,,1.17.0-1,,
cqueues,,,,,vcunat
cyrussasl,,,,,vcunat
cyrussasl,,,,,
digestif,,,,lua5_3,
dkjson,,,,,
fifo,,,,,
http,,,,,vcunat
inspect,,,,,
ldbus,,http://luarocks.org/dev,,,
ldoc,,,,,
lgi,,,,,
linenoise,,,,,
@ -50,9 +51,9 @@ luaepnf,,,,,
luaevent,,,,,
luaexpat,,,1.3.0-1,,arobyn flosse
luaffi,,http://luarocks.org/dev,,,
luafilesystem,,,1.7.0-2,,flosse vcunat
luafilesystem,,,1.7.0-2,,flosse
lualogging,,,,,
luaossl,,,,lua5_1,vcunat
luaossl,,,,lua5_1,
luaposix,,,,,vyp lblasc
luarepl,,,,,
luasec,,,,,flosse
@ -73,6 +74,7 @@ moonscript,,,,,arobyn
nvim-client,,,,,
penlight,,,,,
rapidjson,,,,,
readline,,,,,
say,,,,,
std__debug,std._debug,,,,
std_normalize,std.normalize,,,,

1 # nix name luarocks name server version luaversion maintainers
12 cosmo marsam
13 coxpcall 1.17.0-1
14 cqueues vcunat
15 cyrussasl vcunat
16 digestif lua5_3
17 dkjson
18 fifo
19 http vcunat
20 inspect
21 ldbus http://luarocks.org/dev
22 ldoc
23 lgi
24 linenoise
51 luaevent
52 luaexpat 1.3.0-1 arobyn flosse
53 luaffi http://luarocks.org/dev
54 luafilesystem 1.7.0-2 flosse vcunat flosse
55 lualogging
56 luaossl lua5_1 vcunat
57 luaposix vyp lblasc
58 luarepl
59 luasec flosse
74 nvim-client
75 penlight
76 rapidjson
77 readline
78 say
79 std__debug std._debug
80 std_normalize std.normalize

View File

@ -34,6 +34,21 @@ with lib.maintainers; {
scope = "Maintain Freedesktop.org packages for graphical desktop.";
};
golang = {
members = [
c00w
cstrahan
Frostman
kalbasit
mdlayher
mic92
orivej
rvolosatovs
zowoq
];
scope = "Maintain Golang compilers.";
};
gnome = {
members = [
hedning
@ -43,6 +58,18 @@ with lib.maintainers; {
scope = "Maintain GNOME desktop environment and platform.";
};
matrix = {
members = [
ma27
pacien
fadenb
mguentner
ekleog
ralith
];
scope = "Maintain the ecosystem around Matrix, a decentralized messenger.";
};
php = {
members = [
aanderse

View File

@ -19,9 +19,9 @@
</term>
<listitem>
<para>
Start a root shell if something goes wrong in stage 1 of the boot process
(the initial ramdisk). This is disabled by default because there is no
authentication for the root shell.
Allows the user to start a root shell if something goes wrong in stage 1
of the boot process (the initial ramdisk). This is disabled by default
because there is no authentication for the root shell.
</para>
</listitem>
</varlistentry>
@ -49,6 +49,22 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>boot.debug1mounts</literal>
</term>
<listitem>
<para>
Like <literal>boot.debug1</literal> or
<literal>boot.debug1devices</literal>, but runs stage1 until all
filesystems that are mounted during initrd are mounted (see
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
). As a motivating example, this could be useful if you've forgotten to set
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
on a file system.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>boot.trace</literal>
@ -90,6 +106,15 @@
<manvolnum>1</manvolnum></citerefentry>.
</para>
<para>
Notice that for <literal>boot.shell_on_fail</literal>,
<literal>boot.debug1</literal>, <literal>boot.debug1devices</literal>, and
<literal>boot.debug1mounts</literal>, if you did <emphasis>not</emphasis>
select "start the new shell as pid 1", and you <literal>exit</literal> from
the new shell, boot will proceed normally from the point where it failed, as
if you'd chosen "ignore the error and continue".
</para>
<para>
If no login prompts or X11 login screens appear (e.g. due to hanging
dependencies), you can press Alt+ArrowUp. If youre lucky, this will start

View File

@ -96,6 +96,47 @@
The options are named identically for all other display managers.
</para>
</simplesect>
<simplesect xml:id="sec-x11--graphics-cards-intel">
<title>Intel Graphics drivers</title>
<para>
There are two choices for Intel Graphics drivers in X.org:
<literal>modesetting</literal> (included in the <package>xorg-server</package> itself)
and <literal>intel</literal> (provided by the package <package>xf86-video-intel</package>).
</para>
<para>
The default and recommended is <literal>modesetting</literal>.
It is a generic driver which uses the kernel
<link xlink:href="https://en.wikipedia.org/wiki/Mode_setting">mode setting</link>
(KMS) mechanism. It supports Glamor (2D graphics acceleration via OpenGL)
and is actively maintained but may perform worse in some cases (like in old chipsets).
</para>
<para>
The second driver, <literal>intel</literal>, is specific to Intel GPUs,
but not recommended by most distributions: it lacks several modern features
(for example, it doesn't support Glamor) and the package hasn't been officially
updated since 2015.
</para>
<para>
The results vary depending on the hardware, so you may have to try both drivers.
Use the option <xref linkend="opt-services.xserver.videoDrivers"/> to set one.
The recommended configuration for modern systems is:
<programlisting>
<xref linkend="opt-services.xserver.videoDrivers"/> = [ "modesetting" ];
<xref linkend="opt-services.xserver.useGlamor"/> = true;
</programlisting>
If you experience screen tearing no matter what, this configuration was
reported to resolve the issue:
<programlisting>
<xref linkend="opt-services.xserver.videoDrivers"/> = [ "intel" ];
<xref linkend="opt-services.xserver.deviceSection"/> = ''
Option "DRI" "2"
Option "TearFree" "true"
'';
</programlisting>
Note that this will likely downgrade the performance compared to
<literal>modesetting</literal> or <literal>intel</literal> with DRI 3 (default).
</para>
</simplesect>
<simplesect xml:id="sec-x11-graphics-cards-nvidia">
<title>Proprietary NVIDIA drivers</title>
<para>

View File

@ -38,7 +38,12 @@ starting VDE switch for network 1
</para>
<para>
The machine state is kept across VM restarts in
<filename>/tmp/vm-state-</filename><varname>machinename</varname>.
You can re-use the VM states coming from a previous run
by setting the <command>--keep-vm-state</command> flag.
<screen>
<prompt>$ </prompt>./result/bin/nixos-run-vms --keep-vm-state
</screen>
The machine state is stored in the
<filename>$TMPDIR/vm-state-</filename><varname>machinename</varname> directory.
</para>
</section>

View File

@ -360,6 +360,18 @@ start_all()
</note>
</listitem>
</varlistentry>
<varlistentry>
<term>
<methodname>wait_for_console_text</methodname>
</term>
<listitem>
<para>
Wait until the supplied regular expressions match a line of the serial
console output. This method is useful when OCR is not possibile or
accurate enough.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<methodname>wait_for_window</methodname>

View File

@ -89,7 +89,7 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen>
NixOS partition. They are installed by default on NixOS, but you don't have
NixOS yet..
</para>
<screen><prompt>$ </prompt>nix-env -iE "_: with import &lt;nixpkgs/nixos&gt; { configuration = {}; }; with config.system.build; [ nixos-generate-config nixos-install nixos-enter manual.manpages ]"</screen>
<screen><prompt>$ </prompt>nix-env -f '&lt;nixpkgs/nixos&gt;' --arg configuration {} -iA config.system.build.{nixos-generate-config,nixos-install,nixos-enter,manual.manpages}</screen>
</listitem>
<listitem>
<note>

View File

@ -49,7 +49,7 @@
</listitem>
<listitem>
<para>
Click on Settings / Display / Screen and select VBoxVGA as Graphics Controller
Click on Settings / Display / Screen and select VMSVGA as Graphics Controller
</para>
</listitem>
<listitem>

View File

@ -146,7 +146,7 @@
partition. It uses the initially reserved 512MiB at the start of the
disk.
<screen language="commands"><prompt># </prompt>parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
<prompt># </prompt>parted /dev/sda -- set 3 boot on</screen>
<prompt># </prompt>parted /dev/sda -- set 3 esp on</screen>
</para>
</listitem>
</orderedlist>
@ -513,7 +513,7 @@ Retype new UNIX password: ***</screen>
<prompt># </prompt>parted /dev/sda -- mkpart primary 512MiB -8GiB
<prompt># </prompt>parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
<prompt># </prompt>parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
<prompt># </prompt>parted /dev/sda -- set 3 boot on</screen>
<prompt># </prompt>parted /dev/sda -- set 3 esp on</screen>
</example>
<example xml:id="ex-install-sequence">

View File

@ -42,6 +42,11 @@
PHP now defaults to PHP 7.4, updated from 7.3.
</para>
</listitem>
<listitem>
<para>
Python 3 now defaults to Python 3.8 instead of 3.7.
</para>
</listitem>
<listitem>
<para>
Two new options, <link linkend="opt-services.openssh.authorizedKeysCommand">authorizedKeysCommand</link>
@ -89,6 +94,31 @@ services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" ''
When MariaDB data directory is just upgraded (not initialized), the users are not created or modified.
</para>
</listitem>
<listitem>
<para>
MySQL server is now started with additional systemd sandbox/hardening options for better security. The PrivateTmp, ProtectHome, and ProtectSystem options
may be problematic when MySQL is attempting to read from or write to your filesystem anywhere outside of its own state directory, for example when
calling <literal>LOAD DATA INFILE or SELECT * INTO OUTFILE</literal>. In this scenario a variant of the following may be required:
- allow MySQL to read from /home and /tmp directories when using <literal>LOAD DATA INFILE</literal>
<programlisting>
systemd.services.mysql.serviceConfig.ProtectHome = lib.mkForce "read-only";
</programlisting>
- allow MySQL to write to custom folder <literal>/var/data</literal> when using <literal>SELECT * INTO OUTFILE</literal>, assuming the mysql user has write
access to <literal>/var/data</literal>
<programlisting>
systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
</programlisting>
</para>
</listitem>
<listitem>
<para>
Two new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link>
has been added to automatically generate the <literal>man-db</literal> caches, which are needed by utilities
like <command>whatis</command> and <command>apropos</command>. The caches are generated during the build of
the NixOS configuration: since this can be expensive when a large number of packages are installed, the
feature is disabled by default.
</para>
</listitem>
</itemizedlist>
</section>
@ -176,6 +206,12 @@ services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" ''
<link linkend="opt-security.duosec.integrationKey">security.duosec.integrationKey</link>.
</para>
</listitem>
<listitem>
<para>
<literal>vmware</literal> has been removed from the <literal>services.x11.videoDrivers</literal> defaults.
For VMWare guests set <literal>virtualisation.vmware.guest.enable</literal> to <literal>true</literal> which will include the appropriate drivers.
</para>
</listitem>
<listitem>
<para>
The initrd SSH support now uses OpenSSH rather than Dropbear to
@ -455,6 +491,29 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
initrd file has not been deleted.
</para>
</listitem>
<listitem>
<para>
The <link xlink:href="https://github.com/okTurtles/dnschain">DNSChain</link>
package and NixOS module have been removed from Nixpkgs as the software is
unmaintained and can't be built. For more information see issue
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/89205">#89205</link>.
</para>
</listitem>
<listitem>
<para>
In the <literal>resilio</literal> module, <xref linkend="opt-services.resilio.httpListenAddr"/> has been changed to listen to <literal>[::1]</literal> instead of <literal>0.0.0.0</literal>.
</para>
</listitem>
<listitem>
<para>
Radicale's default package has changed from 2.x to 3.x. An upgrade
checklist can be found
<link xlink:href="https://github.com/Kozea/Radicale/blob/3.0.x/NEWS.md#upgrade-checklist">here</link>.
You can use the newer version in the NixOS service by setting the
<literal>package</literal> to <literal>radicale3</literal>, which is done
automatically if <literal>stateVersion</literal> is 20.09 or higher.
</para>
</listitem>
</itemizedlist>
</section>
@ -467,7 +526,7 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<itemizedlist>
<listitem>
<para>SD and ISO images are now compressed by default using <literal>zstd</literal>.</para>
<para>SD images are now compressed by default using <literal>zstd</literal>. The compression for ISO images has also been changed to <literal>zstd</literal>, but ISO images are still not compressed by default.</para>
</listitem>
<listitem>
<para>
@ -485,9 +544,32 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
the <literal>notmuch.emacs</literal> output.
</para>
</listitem>
<listitem>
<para>
The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
</para>
</listitem>
<listitem>
<para>
Packages built using <literal>buildRustPackage</literal> now use <literal>release</literal>
mode for the <literal>checkPhase</literal> by default.
</para>
<para>
Please note that Rust packages utilizing a custom build/install procedure
(e.g. by using a <filename>Makefile</filename>) or test suites that rely on the
structure of the <filename>target/</filename> directory may break due to those assumptions.
For further information, please read the Rust section in the Nixpkgs manual.
</para>
</listitem>
<listitem>
<para>
The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
The cc- and binutils-wrapper's "infix salt" and <literal>_BUILD_</literal> and <literal>_TARGET_</literal> user infixes have been replaced with with a "suffix salt" and suffixes and <literal>_FOR_BUILD</literal> and <literal>_FOR_TARGET</literal>.
This matches the autotools convention for env vars which standard for these things, making interfacing with other tools easier.
</para>
</listitem>
<listitem>
<para>
Additional Git documentation (HTML and text files) is now available via the <literal>git-doc</literal> package.
</para>
</listitem>
<listitem>
@ -518,6 +600,94 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<link xlink:href="https://grafana.com/docs/grafana/latest/installation/upgrading/#upgrading-to-v7-0">in the Grafana documentation</link>.
</para>
</listitem>
<listitem>
<para>
The <literal>hardware.u2f</literal> module, which was installing udev rules
was removed, as udev gained native support to handle FIDO security tokens.
</para>
</listitem>
<listitem>
<para>
With this release <literal>systemd-networkd</literal> (when enabled through <xref linkend="opt-networking.useNetworkd"/>)
has it's netlink socket created through a <literal>systemd.socket</literal> unit. This gives us control over
socket buffer sizes and other parameters. For larger setups where networkd has to create a lot of (virtual)
devices the default buffer size (currently 128MB) is not enough.
</para>
<para>
On a machine with &gt;100 virtual interfaces (e.g., wireguard tunnels, VLANs, …), that all have to
be brought up during system startup, the receive buffer size will spike for a brief period.
Eventually some of the message will be dropped since there is not enough (permitted) buffer
space available.
</para>
<para>
By having <literal>systemd-networkd</literal> start with a netlink socket created by
<literal>systemd</literal> we can configure the <literal>ReceiveBufferSize=</literal> parameter
in the socket options (i.e. <literal>systemd.sockets.systemd-networkd.socketOptions.ReceiveBufferSize</literal>)
without recompiling <literal>systemd-networkd</literal>.
</para>
<para>
Since the actual memory requirements depend on hardware, timing, exact
configurations etc. it isn't currently possible to infer a good default
from within the NixOS module system. Administrators are advised to
monitor the logs of <literal>systemd-networkd</literal> for <literal>rtnl: kernel receive buffer
overrun</literal> spam and increase the memory limit as they see fit.
</para>
<para>
Note: Increasing the <literal>ReceiveBufferSize=</literal> doesn't allocate any memory. It just increases
the upper bound on the kernel side. The memory allocation depends on the amount of messages that are
queued on the kernel side of the netlink socket.
</para>
</listitem>
<listitem>
<para>
Specifying <link linkend="opt-services.dovecot2.mailboxes">mailboxes</link> in the <package>dovecot2</package> module
as a list is deprecated and will break eval in 21.03. Instead, an attribute-set should be specified where the <literal>name</literal>
should be the key of the attribute.
</para>
<para>
This means that a configuration like this
<programlisting>{
<link linkend="opt-services.dovecot2.mailboxes">services.dovecot2.mailboxes</link> = [
{ name = "Junk";
auto = "create";
}
];
}</programlisting>
should now look like this:
<programlisting>{
<link linkend="opt-services.dovecot2.mailboxes">services.dovecot2.mailboxes</link> = {
Junk.auto = "create";
};
}</programlisting>
</para>
</listitem>
<listitem>
<para>
<package>netbeans</package> was upgraded to 12.0 and now defaults to OpenJDK 11. This might cause problems if your projects depend on packages that were removed in Java 11.
</para>
</listitem>
<listitem>
<para>
<package>nextcloud</package> has been updated to <link xlink:href="https://nextcloud.com/blog/nextcloud-hub-brings-productivity-to-home-office/">v19</link>.
</para>
<para>
If you have an existing installation, please make sure that you're on
<package>nextcloud18</package> before upgrading to <package>nextcloud19</package>
since Nextcloud doesn't support upgrades across multiple major versions.
</para>
<para>
The <literal>nixos-run-vms</literal> script now deletes the
previous run machines states on test startup. You can use the
<literal>--keep-vm-state</literal> flag to match the previous
behaviour and keep the same VM state between different test runs.
</para>
</listitem>
<listitem>
<para>
The <link linkend="opt-nix.buildMachines">nix.buildMachines</link> option is now type-checked.
There are no functional changes, however this may require updating some configurations to use correct types for all attributes.
</para>
</listitem>
</itemizedlist>
</section>
</section>

View File

@ -39,7 +39,7 @@
, name ? "nixos-disk-image"
, # Disk image format, one of qcow2, qcow2-compressed, vpc, raw.
, # Disk image format, one of qcow2, qcow2-compressed, vdi, vpc, raw.
format ? "raw"
}:
@ -57,6 +57,7 @@ let format' = format; in let
filename = "nixos." + {
qcow2 = "qcow2";
vdi = "vdi";
vpc = "vhd";
raw = "img";
}.${format};

View File

@ -17,7 +17,7 @@
, e2fsprogs
, libfaketime
, perl
, lkl
, fakeroot
}:
let
@ -26,7 +26,7 @@ in
pkgs.stdenv.mkDerivation {
name = "ext4-fs.img${lib.optionalString compressImage ".zst"}";
nativeBuildInputs = [ e2fsprogs.bin libfaketime perl lkl ]
nativeBuildInputs = [ e2fsprogs.bin libfaketime perl fakeroot ]
++ lib.optional compressImage zstd;
buildCommand =
@ -37,32 +37,31 @@ pkgs.stdenv.mkDerivation {
${populateImageCommands}
)
# Add the closures of the top-level store objects.
storePaths=$(cat ${sdClosureInfo}/store-paths)
echo "Preparing store paths for image..."
# Create nix/store before copying path
mkdir -p ./rootImage/nix/store
xargs -I % cp -a --reflink=auto % -t ./rootImage/nix/store/ < ${sdClosureInfo}/store-paths
(
GLOBIGNORE=".:.."
shopt -u dotglob
cp -a --reflink=auto ./files/* -t ./rootImage/
)
# Also include a manifest of the closures in a format suitable for nix-store --load-db
cp ${sdClosureInfo}/registration ./rootImage/nix-path-registration
# Make a crude approximation of the size of the target image.
# If the script starts failing, increase the fudge factors here.
numInodes=$(find $storePaths ./files | wc -l)
numDataBlocks=$(du -s -c -B 4096 --apparent-size $storePaths ./files | tail -1 | awk '{ print int($1 * 1.03) }')
numInodes=$(find ./rootImage | wc -l)
numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
echo "Creating an EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
truncate -s $bytes $img
faketime -f "1970-01-01 00:00:01" mkfs.ext4 -L ${volumeLabel} -U ${uuid} $img
# Also include a manifest of the closures in a format suitable for nix-store --load-db.
cp ${sdClosureInfo}/registration nix-path-registration
cptofs -t ext4 -i $img nix-path-registration /
# Create nix/store before copying paths
faketime -f "1970-01-01 00:00:01" mkdir -p nix/store
cptofs -t ext4 -i $img nix /
echo "copying store paths to image..."
cptofs -t ext4 -i $img $storePaths /nix/store/
echo "copying files to image..."
cptofs -t ext4 -i $img ./files/* /
faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext4 -L ${volumeLabel} -U ${uuid} -d ./rootImage $img
export EXT2FS_NO_MTAB_OK=yes
# I have ended up with corrupted images sometimes, I suspect that happens when the build machine's disk gets full during the build.

View File

@ -35,7 +35,7 @@
isohybridMbrImage ? ""
, # Whether to compress the resulting ISO image with zstd.
compressImage ? false
compressImage ? false, zstd
, # The volume ID.
volumeID ? ""

View File

@ -129,7 +129,7 @@ fi
if test -n "$compressImage"; then
echo "Compressing image..."
zstd -T$NIX_BUILD_CORES $out/iso/$isoName
zstd -T$NIX_BUILD_CORES --rm $out/iso/$isoName
fi
mkdir -p $out/nix-support

View File

@ -3,7 +3,10 @@ from contextlib import contextmanager, _GeneratorContextManager
from queue import Queue, Empty
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
from xml.sax.saxutils import XMLGenerator
import queue
import io
import _thread
import argparse
import atexit
import base64
import codecs
@ -671,6 +674,22 @@ class Machine:
with self.nested("waiting for {} to appear on screen".format(regex)):
retry(screen_matches)
def wait_for_console_text(self, regex: str) -> None:
self.log("waiting for {} to appear on console".format(regex))
# Buffer the console output, this is needed
# to match multiline regexes.
console = io.StringIO()
while True:
try:
console.write(self.last_lines.get())
except queue.Empty:
self.sleep(1)
continue
console.seek(0)
matches = re.search(regex, console.read())
if matches is not None:
return
def send_key(self, key: str) -> None:
key = CHAR_TO_KEY.get(key, key)
self.send_monitor_command("sendkey {}".format(key))
@ -734,11 +753,16 @@ class Machine:
self.monitor, _ = self.monitor_socket.accept()
self.shell, _ = self.shell_socket.accept()
# Store last serial console lines for use
# of wait_for_console_text
self.last_lines: Queue = Queue()
def process_serial_output() -> None:
assert self.process.stdout is not None
for _line in self.process.stdout:
# Ignore undecodable bytes that may occur in boot menus
line = _line.decode(errors="ignore").replace("\r", "").rstrip()
self.last_lines.put(line)
eprint("{} # {}".format(self.name, line))
self.logger.enqueue({"msg": line, "machine": self.name})
@ -751,6 +775,11 @@ class Machine:
self.log("QEMU running (pid {})".format(self.pid))
def cleanup_statedir(self) -> None:
self.log("delete the VM state directory")
if os.path.isfile(self.state_dir):
shutil.rmtree(self.state_dir)
def shutdown(self) -> None:
if not self.booted:
return
@ -889,6 +918,15 @@ def subtest(name: str) -> Iterator[None]:
if __name__ == "__main__":
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument(
"-K",
"--keep-vm-state",
help="re-use a VM state coming from a previous run",
action="store_true",
)
(cli_args, vm_scripts) = arg_parser.parse_known_args()
log = Logger()
vlan_nrs = list(dict.fromkeys(os.environ.get("VLANS", "").split()))
@ -896,8 +934,10 @@ if __name__ == "__main__":
for nr, vde_socket, _, _ in vde_sockets:
os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
vm_scripts = sys.argv[1:]
machines = [create_machine({"startCommand": s}) for s in vm_scripts]
for machine in machines:
if not cli_args.keep_vm_state:
machine.cleanup_statedir()
machine_eval = [
"{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
]
@ -911,7 +951,6 @@ if __name__ == "__main__":
continue
log.log("killing {} (pid {})".format(machine.name, machine.pid))
machine.process.kill()
for _, _, process, _ in vde_sockets:
process.terminate()
log.close()

View File

@ -114,7 +114,7 @@ rec {
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
# Generate onvenience wrappers for running the test driver
# Generate convenience wrappers for running the test driver
# interactively with the specified network, and for starting the
# VMs from the command line.
driver = let warn = if skipLint then lib.warn "Linting is disabled!" else lib.id; in warn (runCommand testDriverName

View File

@ -278,7 +278,14 @@ in
(mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
];
] ++ lib.forEach [ "enable" "substitutions" "preset" ]
(opt: lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
The fonts.fontconfig.ultimate module and configuration is obsolete.
The repository has since been archived and activity has ceased.
https://github.com/bohoomil/fontconfig-ultimate/issues/171.
No action should be needed for font configuration, as the fonts.fontconfig
module is already used by default.
'');
options = {

View File

@ -68,7 +68,8 @@ with lib;
config = {
environment.systemPackages =
optional (config.i18n.supportedLocales != []) config.i18n.glibcLocales;
# We increase the priority a little, so that plain glibc in systemPackages can't win.
optional (config.i18n.supportedLocales != []) (lib.setPrio (-1) config.i18n.glibcLocales);
environment.sessionVariables =
{ LANG = config.i18n.defaultLocale;

View File

@ -27,6 +27,15 @@ let
hashedPasswordDescription = ''
To generate hashed password install <literal>mkpasswd</literal>
package and run <literal>mkpasswd -m sha-512</literal>.
For password-less logins without password prompt, use
the empty string <literal>""</literal>.
For logins with a fixed password (including the empty-string password with
prompt), use one of the un-hashed password options instead, such as
<option>users.users.&lt;name?&gt;.password</option>.
Such unprotected logins should only be used for e.g. bootable live systems.
'';
userOpts = { name, config, ... }: {
@ -600,6 +609,38 @@ in {
}
];
warnings =
builtins.filter (x: x != null) (
flip mapAttrsToList cfg.users (name: user:
# This regex matches a subset of the Modular Crypto Format (MCF)[1]
# informal standard. Since this depends largely on the OS or the
# specific implementation of crypt(3) we only support the (sane)
# schemes implemented by glibc and BSDs. In particular the original
# DES hash is excluded since, having no structure, it would validate
# common mistakes like typing the plaintext password.
#
# [1]: https://en.wikipedia.org/wiki/Crypt_(C)
let
sep = "\\$";
base64 = "[a-zA-Z0-9./]+";
id = "[a-z0-9-]+";
value = "[a-zA-Z0-9/+.-]+";
options = "${id}(=${value})?(,${id}=${value})*";
scheme = "${id}(${sep}${options})?";
content = "${base64}${sep}${base64}";
mcf = "^${sep}${scheme}${sep}${content}$";
in
if (user.hashedPassword != null
&& builtins.match mcf user.hashedPassword == null)
then
''
The password hash of user "${name}" may be invalid. You must set a
valid hash or the user will be locked out of their account. Please
check the value of option `users.users."${name}".hashedPassword`.
''
else null
));
};
}

View File

@ -22,11 +22,22 @@ in {
example = literalExample "pkgs.device-tree_rpi";
type = types.path;
description = ''
The package containing the base device-tree (.dtb) to boot. Contains
The path containing the base device-tree (.dtb) to boot. Contains
device trees bundled with the Linux kernel by default.
'';
};
name = mkOption {
default = null;
example = "some-dtb.dtb";
type = types.nullOr types.str;
description = ''
The name of an explicit dtb to be loaded, relative to the dtb base.
Useful in extlinux scenarios if the bootloader doesn't pick the
right .dtb file from FDTDIR.
'';
};
overlays = mkOption {
default = [];
example = literalExample

View File

@ -84,7 +84,7 @@ in {
model = mkOption {
type = types.str;
example = literalExample ''
gutenprint.''${lib.version.majorMinor (lib.getVersion pkgs.cups)}://brother-hl-5140/expert
gutenprint.''${lib.versions.majorMinor (lib.getVersion pkgs.gutenprint)}://brother-hl-5140/expert
'';
description = ''
Location of the ppd driver file for the printer.

View File

@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-aarch64.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
let
extlinux-conf-builder =
import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
pkgs = pkgs.buildPackages;
};
in
{
imports = [
../../profiles/base.nix
@ -56,7 +50,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};

View File

@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
let
extlinux-conf-builder =
import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
pkgs = pkgs.buildPackages;
};
in
{
imports = [
../../profiles/base.nix
@ -53,7 +47,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};

View File

@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
let
extlinux-conf-builder =
import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
pkgs = pkgs.buildPackages;
};
in
{
imports = [
../../profiles/base.nix
@ -42,7 +36,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};

View File

@ -18,6 +18,7 @@
sdImage = {
firmwareSize = 128;
firmwarePartitionName = "NIXOS_BOOT";
# This is a hack to avoid replicating config.txt from boot.loader.raspberryPi
populateFirmwareCommands =
"${config.system.build.installBootLoader} ${config.system.build.toplevel} -d ./firmware";
@ -25,6 +26,12 @@
populateRootCommands = "";
};
fileSystems."/boot/firmware" = {
# This effectively "renames" the loaOf entry set in sd-image.nix
mountPoint = "/boot";
neededForBoot = true;
};
# the installation media is also the installation target,
# so we don't want to provide the installation configuration.nix.
installer.cloneConfig = false;

View File

@ -63,6 +63,14 @@ in
'';
};
firmwarePartitionName = mkOption {
type = types.str;
default = "FIRMWARE";
description = ''
Name of the filesystem which holds the boot firmware.
'';
};
rootPartitionUUID = mkOption {
type = types.nullOr types.str;
default = null;
@ -91,7 +99,7 @@ in
};
populateRootCommands = mkOption {
example = literalExample "''\${extlinux-conf-builder} -t 3 -c \${config.system.build.toplevel} -d ./files/boot''";
example = literalExample "''\${config.boot.loader.generic-extlinux-compatible.populateCmd} -c \${config.system.build.toplevel} -d ./files/boot''";
description = ''
Shell commands to populate the ./files directory.
All files in that directory are copied to the
@ -114,7 +122,7 @@ in
config = {
fileSystems = {
"/boot/firmware" = {
device = "/dev/disk/by-label/FIRMWARE";
device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
fsType = "vfat";
# Alternatively, this could be removed from the configuration.
# The filesystem is not needed at runtime, it could be treated
@ -178,7 +186,7 @@ in
# Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
truncate -s $((SECTORS * 512)) firmware_part.img
faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n FIRMWARE firmware_part.img
faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n ${config.sdImage.firmwarePartitionName} firmware_part.img
# Populate the files intended for /boot/firmware
mkdir firmware
@ -190,7 +198,7 @@ in
fsck.vfat -vn firmware_part.img
dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
if test -n "$compressImage"; then
zstd -T$NIX_BUILD_CORES $img
zstd -T$NIX_BUILD_CORES --rm $img
fi
'';
}) {};

View File

@ -628,6 +628,7 @@ EOF
write_file($fn, <<EOF);
@configuration@
EOF
print STDERR "For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware"
} else {
print STDERR "warning: not overwriting existing $fn\n";
}

View File

@ -71,6 +71,17 @@ if ! test -e "$mountPoint"; then
exit 1
fi
# Verify permissions are okay-enough
checkPath="$(realpath "$mountPoint")"
while [[ "$checkPath" != "/" ]]; do
mode="$(stat -c '%a' "$checkPath")"
if [[ "${mode: -1}" -lt "5" ]]; then
echo "path $checkPath should have permissions 755, but had permissions $mode. Consider running 'chmod o+rx $checkPath'."
exit 1
fi
checkPath="$(dirname "$checkPath")"
done
# Get the path of the NixOS configuration file.
if [[ -z $NIXOS_CONFIG ]]; then
NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix

View File

@ -102,6 +102,16 @@ in
'';
};
man.generateCaches = mkOption {
type = types.bool;
default = false;
description = ''
Whether to generate the manual page index caches using
<literal>mandb(8)</literal>. This allows searching for a page or
keyword using utilities like <literal>apropos(1)</literal>.
'';
};
info.enable = mkOption {
type = types.bool;
default = true;
@ -187,7 +197,33 @@ in
environment.systemPackages = [ pkgs.man-db ];
environment.pathsToLink = [ "/share/man" ];
environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman";
environment.etc."man.conf".source = "${pkgs.man-db}/etc/man_db.conf";
environment.etc."man_db.conf".text =
let
manualPages = pkgs.buildEnv {
name = "man-paths";
paths = config.environment.systemPackages;
pathsToLink = [ "/share/man" ];
extraOutputsToInstall = ["man"];
ignoreCollisions = true;
};
manualCache = pkgs.runCommandLocal "man-cache" { }
''
echo "MANDB_MAP ${manualPages}/share/man $out" > man.conf
${pkgs.man-db}/bin/mandb -C man.conf -psc
'';
in
''
# Manual pages paths for NixOS
MANPATH_MAP /run/current-system/sw/bin /run/current-system/sw/share/man
MANPATH_MAP /run/wrappers/bin /run/current-system/sw/share/man
${optionalString cfg.man.generateCaches ''
# Generated manual pages cache for NixOS (immutable)
MANDB_MAP /run/current-system/sw/share/man ${manualCache}
''}
# Manual pages caches for NixOS
MANDB_MAP /run/current-system/sw/share/man /var/cache/man/nixos
'';
})
(mkIf cfg.info.enable {

View File

@ -239,7 +239,6 @@ in
shout = 206;
gateone = 207;
namecoin = 208;
dnschain = 209;
#lxd = 210; # unused
kibana = 211;
xtreemfs = 212;
@ -549,7 +548,6 @@ in
#shout = 206; #unused
gateone = 207;
namecoin = 208;
#dnschain = 209; #unused
lxd = 210; # unused
#kibana = 211;
xtreemfs = 212;

View File

@ -126,6 +126,7 @@
./programs/gpaste.nix
./programs/gnupg.nix
./programs/gphoto2.nix
./programs/hamster.nix
./programs/iftop.nix
./programs/iotop.nix
./programs/java.nix
@ -334,6 +335,7 @@
./services/games/minecraft-server.nix
./services/games/minetest-server.nix
./services/games/openarena.nix
./services/games/teeworlds.nix
./services/games/terraria.nix
./services/hardware/acpid.nix
./services/hardware/actkbd.nix
@ -361,7 +363,6 @@
./services/hardware/throttled.nix
./services/hardware/trezord.nix
./services/hardware/triggerhappy.nix
./services/hardware/u2f.nix
./services/hardware/udev.nix
./services/hardware/udisks2.nix
./services/hardware/upower.nix
@ -588,6 +589,7 @@
./services/networking/autossh.nix
./services/networking/bird.nix
./services/networking/bitlbee.nix
./services/networking/blockbook-frontend.nix
./services/networking/charybdis.nix
./services/networking/cjdns.nix
./services/networking/cntlm.nix
@ -601,7 +603,6 @@
./services/networking/dhcpcd.nix
./services/networking/dhcpd.nix
./services/networking/dnscache.nix
./services/networking/dnschain.nix
./services/networking/dnscrypt-proxy2.nix
./services/networking/dnscrypt-wrapper.nix
./services/networking/dnsdist.nix
@ -624,6 +625,7 @@
./services/networking/gdomap.nix
./services/networking/git-daemon.nix
./services/networking/gnunet.nix
./services/networking/go-neb.nix
./services/networking/go-shadowsocks2.nix
./services/networking/gogoclient.nix
./services/networking/gvpe.nix
@ -684,6 +686,7 @@
./services/networking/ocserv.nix
./services/networking/ofono.nix
./services/networking/oidentd.nix
./services/networking/onedrive.nix
./services/networking/openfire.nix
./services/networking/openvpn.nix
./services/networking/ostinato.nix
@ -756,6 +759,7 @@
./services/networking/v2ray.nix
./services/networking/vsftpd.nix
./services/networking/wakeonlan.nix
./services/networking/wasabibackend.nix
./services/networking/websockify.nix
./services/networking/wg-quick.nix
./services/networking/wicd.nix
@ -829,6 +833,7 @@
./services/web-apps/atlassian/crowd.nix
./services/web-apps/atlassian/jira.nix
./services/web-apps/codimd.nix
./services/web-apps/convos.nix
./services/web-apps/cryptpad.nix
./services/web-apps/documize.nix
./services/web-apps/dokuwiki.nix
@ -933,6 +938,7 @@
./system/boot/grow-partition.nix
./system/boot/initrd-network.nix
./system/boot/initrd-ssh.nix
./system/boot/initrd-openvpn.nix
./system/boot/kernel.nix
./system/boot/kexec.nix
./system/boot/loader/efi.nix

View File

@ -102,6 +102,9 @@ in
programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
# Required for man completions
documentation.man.generateCaches = true;
environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit;
environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit;
environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit;

View File

@ -0,0 +1,15 @@
{ config, lib, pkgs, ... }:
with lib;
{
meta.maintainers = pkgs.hamster.meta.maintainers;
options.programs.hamster.enable =
mkEnableOption "Whether to enable hamster time tracking.";
config = lib.mkIf config.programs.hamster.enable {
environment.systemPackages = [ pkgs.hamster ];
services.dbus.packages = [ pkgs.hamster ];
};
}

View File

@ -21,9 +21,11 @@ in
(mkRenamedOptionModule [ "networking" "defaultMailServer" "useTLS" ] [ "services" "ssmtp" "useTLS" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "useSTARTTLS" ] [ "services" "ssmtp" "useSTARTTLS" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "authUser" ] [ "services" "ssmtp" "authUser" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "authPass" ] [ "services" "ssmtp" "authPass" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "authPassFile" ] [ "services" "ssmtp" "authPassFile" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "setSendmail" ] [ "services" "ssmtp" "setSendmail" ])
(mkRemovedOptionModule [ "networking" "defaultMailServer" "authPass" ] "authPass has been removed since it leaks the clear-text password into the world-readable store. Use authPassFile instead and make sure it's not a store path")
(mkRemovedOptionModule [ "services" "ssmtp" "authPass" ] "authPass has been removed since it leaks the clear-text password into the world-readable store. Use authPassFile instead and make sure it's not a store path")
];
options = {
@ -45,6 +47,21 @@ in
'';
};
settings = mkOption {
type = with types; attrsOf (oneOf [ bool str ]);
default = {};
description = ''
<citerefentry><refentrytitle>ssmtp</refentrytitle><manvolnum>5</manvolnum></citerefentry> configuration. Refer
to <link xlink:href="https://linux.die.net/man/5/ssmtp.conf"/> for details on supported values.
'';
example = literalExample ''
{
Debug = true;
FromLineOverride = false;
}
'';
};
hostName = mkOption {
type = types.str;
example = "mail.example.org";
@ -101,18 +118,6 @@ in
'';
};
authPass = mkOption {
type = types.str;
default = "";
example = "correctHorseBatteryStaple";
description = ''
Password used for SMTP auth. (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)
It's recommended to use <option>authPassFile</option>
which takes precedence over <option>authPass</option>.
'';
};
authPassFile = mkOption {
type = types.nullOr types.str;
default = null;
@ -121,11 +126,6 @@ in
Path to a file that contains the password used for SMTP auth. The file
should not contain a trailing newline, if the password does not contain one.
This file should be readable by the users that need to execute ssmtp.
<option>authPassFile</option> takes precedence over <option>authPass</option>.
Warning: when <option>authPass</option> is non-empty <option>authPassFile</option>
defaults to a file in the WORLD-READABLE Nix store containing that password.
'';
};
@ -142,25 +142,28 @@ in
config = mkIf cfg.enable {
services.ssmtp.authPassFile = mkIf (cfg.authPass != "")
(mkDefault (toString (pkgs.writeTextFile {
name = "ssmtp-authpass";
text = cfg.authPass;
})));
services.ssmtp.settings = mkMerge [
({
MailHub = cfg.hostName;
FromLineOverride = mkDefault true;
UseTLS = cfg.useTLS;
UseSTARTTLS = cfg.useSTARTTLS;
})
(mkIf (cfg.root != "") { root = cfg.root; })
(mkIf (cfg.domain != "") { rewriteDomain = cfg.domain; })
(mkIf (cfg.authUser != "") { AuthUser = cfg.authUser; })
(mkIf (cfg.authPassFile != null) { AuthPassFile = cfg.authPassFile; })
];
environment.etc."ssmtp/ssmtp.conf".text =
let yesNo = yes : if yes then "YES" else "NO"; in
''
MailHub=${cfg.hostName}
FromLineOverride=YES
${optionalString (cfg.root != "") "root=${cfg.root}"}
${optionalString (cfg.domain != "") "rewriteDomain=${cfg.domain}"}
UseTLS=${yesNo cfg.useTLS}
UseSTARTTLS=${yesNo cfg.useSTARTTLS}
#Debug=YES
${optionalString (cfg.authUser != "") "AuthUser=${cfg.authUser}"}
${optionalString (cfg.authPassFile != null) "AuthPassFile=${cfg.authPassFile}"}
'';
environment.etc."ssmtp/ssmtp.conf".source =
let
toStr = value:
if value == true then "YES"
else if value == false then "NO"
else builtins.toString value
;
in
pkgs.writeText "ssmtp.conf" (concatStringsSep "\n" (mapAttrsToList (key: value: "${key}=${toStr value}") cfg.settings));
environment.systemPackages = [pkgs.ssmtp];

View File

@ -55,6 +55,12 @@ with lib;
prey-bash-client is deprecated upstream
'')
(mkRemovedOptionModule ["hardware" "u2f" ] ''
The U2F modules module was removed, as all it did was adding the
udev rules from libu2f-host to the system. Udev gained native support
to handle FIDO security tokens, so this isn't necessary anymore.
'')
# Do NOT add any option renames here, see top of the file
];
}

View File

@ -302,6 +302,11 @@ in
lpath = "acme/${cert}";
apath = "/var/lib/${lpath}";
spath = "/var/lib/acme/.lego/${cert}";
keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
requestedDomains = pipe ([ data.domain ] ++ (attrNames data.extraDomains)) [
(domains: sort builtins.lessThan domains)
(domains: concatStringsSep "," domains)
];
fileMode = if data.allowKeysForGroup then "640" else "600";
globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
@ -316,6 +321,7 @@ in
certOpts ++ data.extraLegoRenewFlags);
acmeService = {
description = "Renew ACME Certificate for ${cert}";
path = with pkgs; [ openssl ];
after = [ "network.target" "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = mkIf (!config.boot.isContainer) [ "multi-user.target" ];
@ -332,11 +338,18 @@ in
ExecStart = pkgs.writeScript "acme-start" ''
#!${pkgs.runtimeShell} -e
test -L ${spath}/accounts -o -d ${spath}/accounts || ln -s ../accounts ${spath}/accounts
${pkgs.lego}/bin/lego ${renewOpts} || ${pkgs.lego}/bin/lego ${runOpts}
LEGO_ARGS=(${runOpts})
if [ -e ${spath}/certificates/${keyName}.crt ]; then
REQUESTED_DOMAINS="${requestedDomains}"
EXISTING_DOMAINS="$(openssl x509 -in ${spath}/certificates/${keyName}.crt -noout -ext subjectAltName | tail -n1 | sed -e 's/ *DNS://g')"
if [ "''${REQUESTED_DOMAINS}" == "''${EXISTING_DOMAINS}" ]; then
LEGO_ARGS=(${renewOpts})
fi
fi
${pkgs.lego}/bin/lego ''${LEGO_ARGS[@]}
'';
ExecStartPost =
let
keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
script = pkgs.writeScript "acme-post-start" ''
#!${pkgs.runtimeShell} -e
cd ${apath}

View File

@ -436,6 +436,8 @@ let
"session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
${optionalString config.security.pam.enableEcryptfs
"session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
${optionalString cfg.pamMount
"session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString use_ldap
"session optional ${pam_ldap}/lib/security/pam_ldap.so"}
${optionalString config.services.sssd.enable
@ -452,8 +454,6 @@ let
"session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"}
${optionalString (cfg.showMotd && config.users.motd != null)
"session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"}
${optionalString cfg.pamMount
"session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString (cfg.enableAppArmor && config.security.apparmor.enable)
"session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"}
${optionalString (cfg.enableKwallet)

View File

@ -173,7 +173,9 @@ in
config = mkIf cfg.enable {
security.sudo.extraRules = [
# We `mkOrder 600` so that the default rule shows up first, but there is
# still enough room for a user to `mkBefore` it.
security.sudo.extraRules = mkOrder 600 [
{ groups = [ "wheel" ];
commands = [ { command = "ALL"; options = (if cfg.wheelNeedsPassword then [ "SETENV" ] else [ "NOPASSWD" "SETENV" ]); } ];
}

View File

@ -21,6 +21,12 @@ let
${optionalString (cfg.network.listenAddress != "any") ''bind_to_address "${cfg.network.listenAddress}"''}
${optionalString (cfg.network.port != 6600) ''port "${toString cfg.network.port}"''}
${optionalString (cfg.fluidsynth) ''
decoder {
plugin "fluidsynth"
soundfont "${pkgs.soundfont-fluid}/share/soundfonts/FluidR3_GM2-2.sf2"
}
''}
${cfg.extraConfig}
'';
@ -133,6 +139,14 @@ in {
parameter is omitted from the configuration.
'';
};
fluidsynth = mkOption {
type = types.bool;
default = false;
description = ''
If set, add fluidsynth soundfont and configure the plugin.
'';
};
};
};

View File

@ -67,7 +67,7 @@ in
type = types.bool;
default = false;
description = ''
Wether to enable the slurm control daemon.
Whether to enable the slurm control daemon.
Note that the standard authentication method is "munge".
The "munge" service needs to be provided with a password file in order for
slurm to work properly (see <literal>services.munge.password</literal>).
@ -135,7 +135,7 @@ in
type = types.bool;
default = false;
description = ''
Wether to provide a slurm.conf file.
Whether to provide a slurm.conf file.
Enable this option if you do not run a slurm daemon on this host
(i.e. <literal>server.enable</literal> and <literal>client.enable</literal> are <literal>false</literal>)
but you still want to run slurm commands from this host.

View File

@ -25,7 +25,7 @@ let
change_source = [ ${concatStringsSep "," cfg.changeSource} ],
schedulers = [ ${concatStringsSep "," cfg.schedulers} ],
builders = [ ${concatStringsSep "," cfg.builders} ],
status = [ ${concatStringsSep "," cfg.status} ],
services = [ ${concatStringsSep "," cfg.reporters} ],
)
for step in [ ${concatStringsSep "," cfg.factorySteps} ]:
factory.addStep(step)
@ -119,10 +119,10 @@ in {
default = [ "worker.Worker('example-worker', 'pass')" ];
};
status = mkOption {
reporters = mkOption {
default = [];
type = types.listOf types.str;
description = "List of status notification endpoints.";
description = "List of reporter objects used to present build status to various users.";
};
user = mkOption {
@ -276,6 +276,10 @@ in {
imports = [
(mkRenamedOptionModule [ "services" "buildbot-master" "bpPort" ] [ "services" "buildbot-master" "pbPort" ])
(mkRemovedOptionModule [ "services" "buildbot-master" "status" ] ''
Since Buildbot 0.9.0, status targets are deprecated and ignored.
Review your configuration and migrate to reporters (available at services.buildbot-master.reporters).
'')
];
meta.maintainers = with lib.maintainers; [ nand0p mic92 ];

View File

@ -1,14 +1,16 @@
{ config, lib, pkgs, ... }:
with builtins;
with lib;
let
cfg = config.services.gitlab-runner;
hasDocker = config.virtualisation.docker.enable;
hashedServices = with builtins; (mapAttrs' (name: service: nameValuePair
"${name}_${config.networking.hostName}_${
hashedServices = mapAttrs'
(name: service: nameValuePair
"${name}_${config.networking.hostName}_${
substring 0 12
(hashString "md5" (unsafeDiscardStringContext (toJSON service)))}"
service)
cfg.services);
cfg.services;
configPath = "$HOME/.gitlab-runner/config.toml";
configureScript = pkgs.writeShellScriptBin "gitlab-runner-configure" (
if (cfg.configFile != null) then ''
@ -76,7 +78,7 @@ let
++ map (v: "--docker-allowed-images ${escapeShellArg v}") service.dockerAllowedImages
++ map (v: "--docker-allowed-services ${escapeShellArg v}") service.dockerAllowedServices
)
))} && sleep 1
))} && sleep 1 || exit 1
fi
'') hashedServices)}
@ -89,8 +91,17 @@ let
# update global options
remarshal --if toml --of json ${configPath} \
| jq -cM '.check_interval = ${toString cfg.checkInterval} |
.concurrent = ${toString cfg.concurrent}' \
| jq -cM ${escapeShellArg (concatStringsSep " | " [
".check_interval = ${toJSON cfg.checkInterval}"
".concurrent = ${toJSON cfg.concurrent}"
".sentry_dsn = ${toJSON cfg.sentryDSN}"
".listen_address = ${toJSON cfg.prometheusListenAddress}"
".session_server.listen_address = ${toJSON cfg.sessionServer.listenAddress}"
".session_server.advertise_address = ${toJSON cfg.sessionServer.advertiseAddress}"
".session_server.session_timeout = ${toJSON cfg.sessionServer.sessionTimeout}"
"del(.[] | nulls)"
"del(.session_server[] | nulls)"
])} \
| remarshal --if json --of toml \
| sponge ${configPath}
@ -141,6 +152,66 @@ in
0 does not mean unlimited.
'';
};
sentryDSN = mkOption {
type = types.nullOr types.str;
default = null;
example = "https://public:private@host:port/1";
description = ''
Data Source Name for tracking of all system level errors to Sentry.
'';
};
prometheusListenAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "localhost:8080";
description = ''
Address (&lt;host&gt;:&lt;port&gt;) on which the Prometheus metrics HTTP server
should be listening.
'';
};
sessionServer = mkOption {
type = types.submodule {
options = {
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "0.0.0.0:8093";
description = ''
An internal URL to be used for the session server.
'';
};
advertiseAddress = mkOption {
type = types.nullOr types.str;
default = null;
example = "runner-host-name.tld:8093";
description = ''
The URL that the Runner will expose to GitLab to be used
to access the session server.
Fallbacks to <option>listenAddress</option> if not defined.
'';
};
sessionTimeout = mkOption {
type = types.int;
default = 1800;
description = ''
How long in seconds the session can stay active after
the job completes (which will block the job from finishing).
'';
};
};
};
default = { };
example = literalExample ''
{
listenAddress = "0.0.0.0:8093";
}
'';
description = ''
The session server allows the user to interact with jobs
that the Runner is responsible for. A good example of this is the
<link xlink:href="https://docs.gitlab.com/ee/ci/interactive_web_terminal/index.html">interactive web terminal</link>.
'';
};
gracefulTermination = mkOption {
type = types.bool;
default = false;

View File

@ -334,7 +334,8 @@ in
environment.etc."my.cnf".source = cfg.configFile;
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
"z '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
];
systemd.services.mysql = let
@ -357,21 +358,17 @@ in
preStart = if isMariaDB then ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions}
touch /tmp/mysql_init
touch ${cfg.dataDir}/mysql_init
fi
'' else ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
touch /tmp/mysql_init
touch ${cfg.dataDir}/mysql_init
fi
'';
serviceConfig = {
User = cfg.user;
Group = "mysql";
Type = if hasNotify then "notify" else "simple";
RuntimeDirectory = "mysqld";
RuntimeDirectoryMode = "0755";
Restart = "on-abort";
RestartSec = "5s";
# The last two environment variables are used for starting Galera clusters
@ -398,7 +395,7 @@ in
done
''}
if [ -f /tmp/mysql_init ]
if [ -f ${cfg.dataDir}/mysql_init ]
then
${concatMapStrings (database: ''
# Create initial databases
@ -452,7 +449,7 @@ in
cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N
''}
rm /tmp/mysql_init
rm ${cfg.dataDir}/mysql_init
fi
${optionalString (cfg.ensureDatabases != []) ''
@ -476,6 +473,35 @@ in
# ensureDatbases & ensureUsers depends on this script being run as root
# when the user has secured their mysql install
"+${setupScript}";
# User and group
User = cfg.user;
Group = "mysql";
# Runtime directory and mode
RuntimeDirectory = "mysqld";
RuntimeDirectoryMode = "0755";
# Access write directories
ReadWritePaths = [ cfg.dataDir ];
# Capabilities
CapabilityBoundingSet = "";
# Security
NoNewPrivileges = true;
# Sandboxing
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
LockPersonality = true;
MemoryDenyWriteExecute = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
PrivateMounts = true;
# System Call Filtering
SystemCallArchitectures = "native";
};
};

View File

@ -5,14 +5,14 @@ with lib;
let
cfg = config.services.openldap;
openldap = pkgs.openldap;
openldap = cfg.package;
dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents;
configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas ''
include ${pkgs.openldap.out}/etc/schema/core.schema
include ${pkgs.openldap.out}/etc/schema/cosine.schema
include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema
include ${pkgs.openldap.out}/etc/schema/nis.schema
include ${openldap.out}/etc/schema/core.schema
include ${openldap.out}/etc/schema/cosine.schema
include ${openldap.out}/etc/schema/inetorgperson.schema
include ${openldap.out}/etc/schema/nis.schema
'') + ''
${cfg.extraConfig}
database ${cfg.database}
@ -46,6 +46,18 @@ in
";
};
package = mkOption {
type = types.package;
default = pkgs.openldap;
description = ''
OpenLDAP package to use.
This can be used to, for example, set an OpenLDAP package
with custom overrides to enable modules or other
functionality.
'';
};
user = mkOption {
type = types.str;
default = "openldap";
@ -152,10 +164,10 @@ in
";
example = literalExample ''
'''
include ${pkgs.openldap.out}/etc/schema/core.schema
include ${pkgs.openldap.out}/etc/schema/cosine.schema
include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema
include ${pkgs.openldap.out}/etc/schema/nis.schema
include ${openldap.out}/etc/schema/core.schema
include ${openldap.out}/etc/schema/cosine.schema
include ${openldap.out}/etc/schema/inetorgperson.schema
include ${openldap.out}/etc/schema/nis.schema
database bdb
suffix dc=example,dc=org
@ -232,7 +244,7 @@ in
};
meta = {
maintainers = lib.maintainers.mic92;
maintainers = [ lib.maintainers.mic92 ];
};

View File

@ -218,6 +218,7 @@ in
description = "Redis database user";
isSystemUser = true;
};
users.groups.redis = {};
environment.systemPackages = [ cfg.package ];
@ -240,6 +241,7 @@ in
StateDirectory = "redis";
Type = "notify";
User = "redis";
Group = "redis";
};
};
};

View File

@ -0,0 +1,119 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.teeworlds;
register = cfg.register;
teeworldsConf = pkgs.writeText "teeworlds.cfg" ''
sv_port ${toString cfg.port}
sv_register ${if cfg.register then "1" else "0"}
${optionalString (cfg.name != null) "sv_name ${cfg.name}"}
${optionalString (cfg.motd != null) "sv_motd ${cfg.motd}"}
${optionalString (cfg.password != null) "password ${cfg.password}"}
${optionalString (cfg.rconPassword != null) "sv_rcon_password ${cfg.rconPassword}"}
${concatStringsSep "\n" cfg.extraOptions}
'';
in
{
options = {
services.teeworlds = {
enable = mkEnableOption "Teeworlds Server";
openPorts = mkOption {
type = types.bool;
default = false;
description = "Whether to open firewall ports for Teeworlds";
};
name = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Name of the server. Defaults to 'unnamed server'.
'';
};
register = mkOption {
type = types.bool;
example = true;
default = false;
description = ''
Whether the server registers as public server in the global server list. This is disabled by default because of privacy.
'';
};
motd = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Set the server message of the day text.
'';
};
password = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Password to connect to the server.
'';
};
rconPassword = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Password to access the remote console. If not set, a randomly generated one is displayed in the server log.
'';
};
port = mkOption {
type = types.int;
default = 8303;
description = ''
Port the server will listen on.
'';
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra configuration lines for the <filename>teeworlds.cfg</filename>. See <link xlink:href="https://www.teeworlds.com/?page=docs&amp;wiki=server_settings">Teeworlds Documentation</link>.
'';
example = [ "sv_map dm1" "sv_gametype dm" ];
};
};
};
config = mkIf cfg.enable {
networking.firewall = mkIf cfg.openPorts {
allowedUDPPorts = [ cfg.port ];
};
systemd.services.teeworlds = {
description = "Teeworlds Server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
DynamicUser = true;
ExecStart = "${pkgs.teeworlds}/bin/teeworlds_srv -f ${teeworldsConf}";
# Hardening
CapabilityBoundingSet = false;
PrivateDevices = true;
PrivateUsers = true;
ProtectHome = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
SystemCallArchitectures = "native";
};
};
};
}

View File

@ -6,6 +6,23 @@ with lib;
let
cfg = config.services.fwupd;
customEtc = {
"fwupd/daemon.conf" = {
source = pkgs.writeText "daemon.conf" ''
[fwupd]
BlacklistDevices=${lib.concatStringsSep ";" cfg.blacklistDevices}
BlacklistPlugins=${lib.concatStringsSep ";" cfg.blacklistPlugins}
'';
};
"fwupd/uefi.conf" = {
source = pkgs.writeText "uefi.conf" ''
[uefi]
OverrideESPMountPoint=${config.boot.loader.efi.efiSysMountPoint}
'';
};
};
originalEtc =
let
mkEtcFile = n: nameValuePair n { source = "${cfg.package}/etc/${n}"; };
@ -96,22 +113,8 @@ in {
environment.systemPackages = [ cfg.package ];
environment.etc = {
"fwupd/daemon.conf" = {
source = pkgs.writeText "daemon.conf" ''
[fwupd]
BlacklistDevices=${lib.concatStringsSep ";" cfg.blacklistDevices}
BlacklistPlugins=${lib.concatStringsSep ";" cfg.blacklistPlugins}
'';
};
"fwupd/uefi.conf" = {
source = pkgs.writeText "uefi.conf" ''
[uefi]
OverrideESPMountPoint=${config.boot.loader.efi.efiSysMountPoint}
'';
};
} // originalEtc // extraTrustedKeys // testRemote;
# customEtc overrides some files from the package
environment.etc = originalEtc // customEtc // extraTrustedKeys // testRemote;
services.dbus.packages = [ cfg.package ];

View File

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.hardware.u2f;
in {
options = {
hardware.u2f = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable U2F hardware support.
'';
};
};
};
config = mkIf cfg.enable {
services.udev.packages = [ pkgs.libu2f-host ];
};
}

View File

@ -1,18 +1,35 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.undervolt;
in {
cliArgs = lib.cli.toGNUCommandLineShell {} {
inherit (cfg)
verbose
temp
;
# `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
#
# Core or Cache offsets have no effect. It is not possible to set different offsets for
# CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
# both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
core = cfg.coreOffset;
cache = cfg.coreOffset;
gpu = cfg.gpuOffset;
uncore = cfg.uncoreOffset;
analogio = cfg.analogioOffset;
temp-bat = cfg.tempBat;
temp-ac = cfg.tempAc;
};
in
{
options.services.undervolt = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to undervolt intel cpus.
'';
};
enable = mkEnableOption ''
Undervolting service for Intel CPUs.
Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk!
'';
verbose = mkOption {
type = types.bool;
@ -32,58 +49,58 @@ in {
};
coreOffset = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The amount of voltage to offset the CPU cores by. Accepts a floating point number.
The amount of voltage in mV to offset the CPU cores by.
'';
};
gpuOffset = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The amount of voltage to offset the GPU by. Accepts a floating point number.
The amount of voltage in mV to offset the GPU by.
'';
};
uncoreOffset = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The amount of voltage to offset uncore by. Accepts a floating point number.
The amount of voltage in mV to offset uncore by.
'';
};
analogioOffset = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The amount of voltage to offset analogio by. Accepts a floating point number.
The amount of voltage in mV to offset analogio by.
'';
};
temp = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The temperature target. Accepts a floating point number.
The temperature target in Celsius degrees.
'';
};
tempAc = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The temperature target on AC power. Accepts a floating point number.
The temperature target on AC power in Celsius degrees.
'';
};
tempBat = mkOption {
type = types.nullOr types.str;
type = types.nullOr types.int;
default = null;
description = ''
The temperature target on battery power. Accepts a floating point number.
The temperature target on battery power in Celsius degrees.
'';
};
};
@ -100,24 +117,7 @@ in {
serviceConfig = {
Type = "oneshot";
Restart = "no";
# `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
#
# Core or Cache offsets have no effect. It is not possible to set different offsets for
# CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
# both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
ExecStart = ''
${pkgs.undervolt}/bin/undervolt \
${optionalString cfg.verbose "--verbose"} \
${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \
${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \
${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \
${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \
${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \
${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \
${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \
${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"}
'';
ExecStart = "${pkgs.undervolt}/bin/undervolt ${cliArgs}";
};
};

View File

@ -125,6 +125,8 @@ let
mailboxConfig = mailbox: ''
mailbox "${mailbox.name}" {
auto = ${toString mailbox.auto}
'' + optionalString (mailbox.autoexpunge != null) ''
autoexpunge = ${mailbox.autoexpunge}
'' + optionalString (mailbox.specialUse != null) ''
special_use = \${toString mailbox.specialUse}
'' + "}";
@ -132,8 +134,9 @@ let
mailboxes = { ... }: {
options = {
name = mkOption {
type = types.strMatching ''[^"]+'';
type = types.nullOr (types.strMatching ''[^"]+'');
example = "Spam";
default = null;
description = "The name of the mailbox.";
};
auto = mkOption {
@ -148,6 +151,15 @@ let
example = "Junk";
description = "Null if no special use flag is set. Other than that every use flag mentioned in the RFC is valid.";
};
autoexpunge = mkOption {
type = types.nullOr types.str;
default = null;
example = "60d";
description = ''
To automatically remove all email from the mailbox which is older than the
specified time.
'';
};
};
};
in
@ -323,9 +335,24 @@ in
};
mailboxes = mkOption {
type = types.listOf (types.submodule mailboxes);
default = [];
example = [ { name = "Spam"; specialUse = "Junk"; auto = "create"; } ];
type = with types; let m = submodule mailboxes; in either (listOf m) (attrsOf m);
default = {};
apply = x:
if isList x then warn "Declaring `services.dovecot2.mailboxes' as a list is deprecated and will break eval in 21.03!" x
else mapAttrsToList (name: value:
if value.name != null
then throw ''
When specifying dovecot2 mailboxes as attributes, declaring
a `name'-attribute is prohibited! The name ${value.name} should
be the attribute key!
''
else value // { inherit name; }
) x;
example = literalExample ''
{
Spam = { specialUse = "Junk"; auto = "create"; };
}
'';
description = "Configure mailboxes and auto create or subscribe them.";
};

View File

@ -6,42 +6,46 @@ let
cfg = config.services.mailman;
pythonEnv = pkgs.python3.withPackages (ps:
[ps.mailman ps.mailman-web]
++ lib.optional cfg.hyperkitty.enable ps.mailman-hyperkitty
++ cfg.extraPythonPackages);
# This deliberately doesn't use recursiveUpdate so users can
# override the defaults.
settings = {
webSettings = {
DEFAULT_FROM_EMAIL = cfg.siteOwner;
SERVER_EMAIL = cfg.siteOwner;
ALLOWED_HOSTS = [ "localhost" "127.0.0.1" ] ++ cfg.webHosts;
COMPRESS_OFFLINE = true;
STATIC_ROOT = "/var/lib/mailman-web/static";
STATIC_ROOT = "/var/lib/mailman-web-static";
MEDIA_ROOT = "/var/lib/mailman-web/media";
LOGGING = {
version = 1;
disable_existing_loggers = true;
handlers.console.class = "logging.StreamHandler";
loggers.django = {
handlers = [ "console" ];
level = "INFO";
};
};
HAYSTACK_CONNECTIONS.default = {
ENGINE = "haystack.backends.whoosh_backend.WhooshEngine";
PATH = "/var/lib/mailman-web/fulltext-index";
};
} // cfg.webSettings;
settingsJSON = pkgs.writeText "settings.json" (builtins.toJSON settings);
webSettingsJSON = pkgs.writeText "settings.json" (builtins.toJSON webSettings);
mailmanCfg = ''
[mailman]
site_owner: ${cfg.siteOwner}
layout: fhs
[paths.fhs]
bin_dir: ${pkgs.python3Packages.mailman}/bin
var_dir: /var/lib/mailman
queue_dir: $var_dir/queue
template_dir: $var_dir/templates
log_dir: $var_dir/log
lock_dir: $var_dir/lock
etc_dir: /etc
ext_dir: $etc_dir/mailman.d
pid_file: /run/mailman/master.pid
'' + optionalString cfg.hyperkitty.enable ''
[archiver.hyperkitty]
class: mailman_hyperkitty.Archiver
enable: yes
configuration: /var/lib/mailman/mailman-hyperkitty.cfg
# TODO: Should this be RFC42-ised so that users can set additional options without modifying the module?
mtaConfig = pkgs.writeText "mailman-postfix.cfg" ''
[postfix]
postmap_command: ${pkgs.postfix}/bin/postmap
transport_file_type: hash
'';
mailmanCfg = lib.generators.toINI {} cfg.settings;
mailmanHyperkittyCfg = pkgs.writeText "mailman-hyperkitty.cfg" ''
[general]
# This is your HyperKitty installation, preferably on the localhost. This
@ -84,7 +88,7 @@ in {
type = types.package;
default = pkgs.mailman;
defaultText = "pkgs.mailman";
example = "pkgs.mailman.override { archivers = []; }";
example = literalExample "pkgs.mailman.override { archivers = []; }";
description = "Mailman package to use";
};
@ -98,18 +102,6 @@ in {
'';
};
webRoot = mkOption {
type = types.path;
default = "${pkgs.mailman-web}/${pkgs.python3.sitePackages}";
defaultText = "\${pkgs.mailman-web}/\${pkgs.python3.sitePackages}";
description = ''
The web root for the Hyperkity + Postorius apps provided by Mailman.
This variable can be set, of course, but it mainly exists so that site
admins can refer to it in their own hand-written web server
configuration files.
'';
};
webHosts = mkOption {
type = types.listOf types.str;
default = [];
@ -124,7 +116,7 @@ in {
webUser = mkOption {
type = types.str;
default = config.services.httpd.user;
default = "mailman-web";
description = ''
User to run mailman-web as
'';
@ -138,6 +130,22 @@ in {
'';
};
serve = {
enable = mkEnableOption "Automatic nginx and uwsgi setup for mailman-web";
};
extraPythonPackages = mkOption {
description = "Packages to add to the python environment used by mailman and mailman-web";
type = types.listOf types.package;
default = [];
};
settings = mkOption {
description = "Settings for mailman.cfg";
type = types.attrsOf (types.attrsOf types.str);
default = {};
};
hyperkitty = {
enable = mkEnableOption "the Hyperkitty archiver for Mailman";
@ -158,6 +166,35 @@ in {
config = mkIf cfg.enable {
services.mailman.settings = {
mailman.site_owner = lib.mkDefault cfg.siteOwner;
mailman.layout = "fhs";
"paths.fhs" = {
bin_dir = "${pkgs.python3Packages.mailman}/bin";
var_dir = "/var/lib/mailman";
queue_dir = "$var_dir/queue";
template_dir = "$var_dir/templates";
log_dir = "/var/log/mailman";
lock_dir = "$var_dir/lock";
etc_dir = "/etc";
ext_dir = "$etc_dir/mailman.d";
pid_file = "/run/mailman/master.pid";
};
mta.configuration = lib.mkDefault "${mtaConfig}";
"archiver.hyperkitty" = lib.mkIf cfg.hyperkitty.enable {
class = "mailman_hyperkitty.Archiver";
enable = "yes";
configuration = "/var/lib/mailman/mailman-hyperkitty.cfg";
};
} // (let
loggerNames = ["root" "archiver" "bounce" "config" "database" "debug" "error" "fromusenet" "http" "locks" "mischief" "plugins" "runner" "smtp"];
loggerSectionNames = map (n: "logging.${n}") loggerNames;
in lib.genAttrs loggerSectionNames(name: { handler = "stderr"; })
);
assertions = let
inherit (config.services) postfix;
@ -183,7 +220,17 @@ in {
(requirePostfixHash [ "config" "local_recipient_maps" ] "postfix_lmtp")
];
users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; };
users.users.mailman = {
description = "GNU Mailman";
isSystemUser = true;
group = "mailman";
};
users.users.mailman-web = lib.mkIf (cfg.webUser == "mailman-web") {
description = "GNU Mailman web interface";
isSystemUser = true;
group = "mailman";
};
users.groups.mailman = {};
environment.etc."mailman.cfg".text = mailmanCfg;
@ -198,14 +245,35 @@ in {
import json
with open('${settingsJSON}') as f:
with open('${webSettingsJSON}') as f:
globals().update(json.load(f))
with open('/var/lib/mailman-web/settings_local.json') as f:
globals().update(json.load(f))
'';
environment.systemPackages = [ cfg.package ] ++ (with pkgs; [ mailman-web ]);
services.nginx = mkIf cfg.serve.enable {
enable = mkDefault true;
virtualHosts."${lib.head cfg.webHosts}" = {
serverAliases = cfg.webHosts;
locations = {
"/".extraConfig = "uwsgi_pass unix:/run/mailman-web.socket;";
"/static/".alias = webSettings.STATIC_ROOT + "/";
};
};
};
environment.systemPackages = [ (pkgs.buildEnv {
name = "mailman-tools";
# We don't want to pollute the system PATH with a python
# interpreter etc. so let's pick only the stuff we actually
# want from pythonEnv
pathsToLink = ["/bin"];
paths = [pythonEnv];
postBuild = ''
find $out/bin/ -mindepth 1 -not -name "mailman*" -delete
'';
}) ];
services.postfix = {
recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP
@ -214,181 +282,156 @@ in {
};
};
systemd.services.mailman = {
description = "GNU Mailman Master Process";
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."mailman.cfg".source ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/mailman start";
ExecStop = "${cfg.package}/bin/mailman stop";
User = "mailman";
Type = "forking";
RuntimeDirectory = "mailman";
PIDFile = "/run/mailman/master.pid";
};
systemd.sockets.mailman-uwsgi = lib.mkIf cfg.serve.enable {
wantedBy = ["sockets.target"];
before = ["nginx.service"];
socketConfig.ListenStream = "/run/mailman-web.socket";
};
systemd.services.mailman-settings = {
description = "Generate settings files (including secrets) for Mailman";
before = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
requiredBy = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
path = with pkgs; [ jq ];
script = ''
mailmanDir=/var/lib/mailman
mailmanWebDir=/var/lib/mailman-web
mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg
mailmanWebCfg=$mailmanWebDir/settings_local.json
install -m 0700 -o mailman -g nogroup -d $mailmanDir
install -m 0700 -o ${cfg.webUser} -g nogroup -d $mailmanWebDir
if [ ! -e $mailmanWebCfg ]; then
hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
mailmanWebCfgTmp=$(mktemp)
jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
--arg archiver_key "$hyperkittyApiKey" \
--arg secret_key "$secretKey" \
>"$mailmanWebCfgTmp"
chown ${cfg.webUser} "$mailmanWebCfgTmp"
mv -n "$mailmanWebCfgTmp" $mailmanWebCfg
fi
hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY $mailmanWebCfg)"
mailmanCfgTmp=$(mktemp)
sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp"
chown mailman "$mailmanCfgTmp"
mv "$mailmanCfgTmp" $mailmanCfg
'';
serviceConfig = {
Type = "oneshot";
# RemainAfterExit makes restartIfChanged work for this service, so
# downstream services will get updated automatically when things like
# services.mailman.hyperkitty.baseUrl change. Otherwise users have to
# restart things manually, which is confusing.
RemainAfterExit = "yes";
systemd.services = {
mailman = {
description = "GNU Mailman Master Process";
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."mailman.cfg".source ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pythonEnv}/bin/mailman start";
ExecStop = "${pythonEnv}/bin/mailman stop";
User = "mailman";
Group = "mailman";
Type = "forking";
RuntimeDirectory = "mailman";
LogsDirectory = "mailman";
PIDFile = "/run/mailman/master.pid";
};
};
};
systemd.services.mailman-web = {
description = "Init Postorius DB";
before = [ "httpd.service" "uwsgi.service" ];
requiredBy = [ "httpd.service" "uwsgi.service" ];
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
script = ''
${pkgs.mailman-web}/bin/mailman-web migrate
rm -rf static
${pkgs.mailman-web}/bin/mailman-web collectstatic
${pkgs.mailman-web}/bin/mailman-web compress
'';
serviceConfig = {
User = cfg.webUser;
Type = "oneshot";
# Similar to mailman-settings.service, this makes restartTriggers work
# properly for this service.
RemainAfterExit = "yes";
WorkingDirectory = "/var/lib/mailman-web";
mailman-settings = {
description = "Generate settings files (including secrets) for Mailman";
before = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
requiredBy = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
path = with pkgs; [ jq ];
script = ''
mailmanDir=/var/lib/mailman
mailmanWebDir=/var/lib/mailman-web
mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg
mailmanWebCfg=$mailmanWebDir/settings_local.json
install -m 0775 -o mailman -g mailman -d /var/lib/mailman-web-static
install -m 0770 -o mailman -g mailman -d $mailmanDir
install -m 0770 -o ${cfg.webUser} -g mailman -d $mailmanWebDir
if [ ! -e $mailmanWebCfg ]; then
hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
mailmanWebCfgTmp=$(mktemp)
jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
--arg archiver_key "$hyperkittyApiKey" \
--arg secret_key "$secretKey" \
>"$mailmanWebCfgTmp"
chown root:mailman "$mailmanWebCfgTmp"
chmod 440 "$mailmanWebCfgTmp"
mv -n "$mailmanWebCfgTmp" "$mailmanWebCfg"
fi
hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY "$mailmanWebCfg")"
mailmanCfgTmp=$(mktemp)
sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp"
chown mailman:mailman "$mailmanCfgTmp"
mv "$mailmanCfgTmp" "$mailmanCfg"
'';
};
};
systemd.services.mailman-daily = {
description = "Trigger daily Mailman events";
startAt = "daily";
restartTriggers = [ config.environment.etc."mailman.cfg".source ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/mailman digests --send";
User = "mailman";
mailman-web-setup = {
description = "Prepare mailman-web files and database";
before = [ "uwsgi.service" "mailman-uwsgi.service" ];
requiredBy = [ "mailman-uwsgi.service" ];
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
script = ''
[[ -e "${webSettings.STATIC_ROOT}" ]] && find "${webSettings.STATIC_ROOT}/" -mindepth 1 -delete
${pythonEnv}/bin/mailman-web migrate
${pythonEnv}/bin/mailman-web collectstatic
${pythonEnv}/bin/mailman-web compress
'';
serviceConfig = {
User = cfg.webUser;
Group = "mailman";
Type = "oneshot";
WorkingDirectory = "/var/lib/mailman-web";
};
};
};
systemd.services.hyperkitty = {
inherit (cfg.hyperkitty) enable;
description = "GNU Hyperkitty QCluster Process";
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
wantedBy = [ "mailman.service" "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web qcluster";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
mailman-uwsgi = mkIf cfg.serve.enable (let
uwsgiConfig.uwsgi = {
type = "normal";
plugins = ["python3"];
home = pythonEnv;
module = "mailman_web.wsgi";
};
uwsgiConfigFile = pkgs.writeText "uwsgi-mailman.json" (builtins.toJSON uwsgiConfig);
in {
wantedBy = ["multi-user.target"];
requires = ["mailman-uwsgi.socket" "mailman-web-setup.service"];
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
# Since the mailman-web settings.py obstinately creates a logs
# dir in the cwd, change to the (writable) runtime directory before
# starting uwsgi.
ExecStart = "${pkgs.coreutils}/bin/env -C $RUNTIME_DIRECTORY ${pkgs.uwsgi.override { plugins = ["python3"]; }}/bin/uwsgi --json ${uwsgiConfigFile}";
User = cfg.webUser;
Group = "mailman";
RuntimeDirectory = "mailman-uwsgi";
};
});
mailman-daily = {
description = "Trigger daily Mailman events";
startAt = "daily";
restartTriggers = [ config.environment.etc."mailman.cfg".source ];
serviceConfig = {
ExecStart = "${pythonEnv}/bin/mailman digests --send";
User = "mailman";
Group = "mailman";
};
};
};
systemd.services.hyperkitty-minutely = {
inherit (cfg.hyperkitty) enable;
description = "Trigger minutely Hyperkitty events";
startAt = "minutely";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs minutely";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
hyperkitty = lib.mkIf cfg.hyperkitty.enable {
description = "GNU Hyperkitty QCluster Process";
after = [ "network.target" ];
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
wantedBy = [ "mailman.service" "multi-user.target" ];
serviceConfig = {
ExecStart = "${pythonEnv}/bin/mailman-web qcluster";
User = cfg.webUser;
Group = "mailman";
WorkingDirectory = "/var/lib/mailman-web";
};
};
};
systemd.services.hyperkitty-quarter-hourly = {
inherit (cfg.hyperkitty) enable;
description = "Trigger quarter-hourly Hyperkitty events";
startAt = "*:00/15";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs quarter_hourly";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
};
};
systemd.services.hyperkitty-hourly = {
inherit (cfg.hyperkitty) enable;
description = "Trigger hourly Hyperkitty events";
startAt = "hourly";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs hourly";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
};
};
systemd.services.hyperkitty-daily = {
inherit (cfg.hyperkitty) enable;
description = "Trigger daily Hyperkitty events";
startAt = "daily";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs daily";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
};
};
systemd.services.hyperkitty-weekly = {
inherit (cfg.hyperkitty) enable;
description = "Trigger weekly Hyperkitty events";
startAt = "weekly";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs weekly";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
};
};
systemd.services.hyperkitty-yearly = {
inherit (cfg.hyperkitty) enable;
description = "Trigger yearly Hyperkitty events";
startAt = "yearly";
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs yearly";
User = cfg.webUser;
WorkingDirectory = "/var/lib/mailman-web";
};
};
} // flip lib.mapAttrs' {
"minutely" = "minutely";
"quarter_hourly" = "*:00/15";
"hourly" = "hourly";
"daily" = "daily";
"weekly" = "weekly";
"yearly" = "yearly";
} (name: startAt:
lib.nameValuePair "hyperkitty-${name}" (lib.mkIf cfg.hyperkitty.enable {
description = "Trigger ${name} Hyperkitty events";
inherit startAt;
restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
serviceConfig = {
ExecStart = "${pythonEnv}/bin/mailman-web runjobs minutely";
User = cfg.webUser;
Group = "mailman";
WorkingDirectory = "/var/lib/mailman-web";
};
}));
};
meta = {
maintainers = with lib.maintainers; [ lheckemann ];
doc = ./mailman.xml;
};
}

View File

@ -0,0 +1,59 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="module-services-mailman">
<title>Mailman</title>
<para>
<link xlink:href="https://www.list.org">Mailman</link> is free
software for managing electronic mail discussion and e-newsletter
lists. Mailman and its web interface can be configured using the
corresponding NixOS module. Note that this service is best used with
an existing, securely configured Postfix setup, as it does not automatically configure this.
</para>
<section xml:id="module-services-mailman-basic-usage">
<title>Basic usage</title>
<para>
For a basic configuration, the following settings are suggested:
<programlisting>{ config, ... }: {
services.postfix = {
enable = true;
relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem";
sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem";
config = {
transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
};
};
services.mailman = {
<link linkend="opt-services.mailman.enable">enable</link> = true;
<link linkend="opt-services.mailman.serve.enable">serve.enable</link> = true;
<link linkend="opt-services.mailman.hyperkitty.enable">hyperkitty.enable</link> = true;
<link linkend="opt-services.mailman.hyperkitty.enable">webHosts</link> = ["lists.example.org"];
<link linkend="opt-services.mailman.hyperkitty.enable">siteOwner</link> = "mailman@example.org";
};
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">services.nginx.virtualHosts."lists.example.org".enableACME</link> = true;
<link linkend="opt-services.mailman.hyperkitty.enable">networking.firewall.allowedTCPPorts</link> = [ 25 80 443 ];
}</programlisting>
</para>
<para>
DNS records will also be required:
<itemizedlist>
<listitem><para><literal>AAAA</literal> and <literal>A</literal> records pointing to the host in question, in order for browsers to be able to discover the address of the web server;</para></listitem>
<listitem><para>An <literal>MX</literal> record pointing to a domain name at which the host is reachable, in order for other mail servers to be able to deliver emails to the mailing lists it hosts.</para></listitem>
</itemizedlist>
</para>
<para>
After this has been done and appropriate DNS records have been
set up, the Postorius mailing list manager and the Hyperkitty
archive browser will be available at
https://lists.example.org/. Note that this setup is not
sufficient to deliver emails to most email providers nor to
avoid spam -- a number of additional measures for authenticating
incoming and outgoing mails, such as SPF, DMARC and DKIM are
necessary, but outside the scope of the Mailman module.
</para>
</section>
</chapter>

View File

@ -17,6 +17,10 @@ in {
###### interface
imports = [
(mkRenamedOptionModule [ "services" "opensmtpd" "addSendmailToSystemPath" ] [ "services" "opensmtpd" "setSendmail" ])
];
options = {
services.opensmtpd = {
@ -34,13 +38,10 @@ in {
description = "The OpenSMTPD package to use.";
};
addSendmailToSystemPath = mkOption {
setSendmail = mkOption {
type = types.bool;
default = true;
description = ''
Whether to add OpenSMTPD's sendmail binary to the
system path or not.
'';
description = "Whether to set the system sendmail to OpenSMTPD's.";
};
extraServerArgs = mkOption {
@ -82,7 +83,7 @@ in {
###### implementation
config = mkIf cfg.enable {
config = mkIf cfg.enable rec {
users.groups = {
smtpd.gid = config.ids.gids.smtpd;
smtpq.gid = config.ids.gids.smtpq;
@ -101,6 +102,14 @@ in {
};
};
security.wrappers.smtpctl = {
group = "smtpq";
setgid = true;
source = "${cfg.package}/bin/smtpctl";
};
services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail security.wrappers.smtpctl;
systemd.tmpfiles.rules = [
"d /var/spool/smtpd 711 root - - -"
"d /var/spool/smtpd/offline 770 root smtpq - -"
@ -119,7 +128,5 @@ in {
serviceConfig.ExecStart = "${cfg.package}/sbin/smtpd -d -f ${conf} ${args}";
environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
};
environment.systemPackages = mkIf cfg.addSendmailToSystemPath [ sendmail ];
};
}

View File

@ -280,6 +280,17 @@ in
description = "Whether to enable smtp submission.";
};
enableSubmissions = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable smtp submission via smtps.
According to RFC 8314 this should be preferred
over STARTTLS for submission of messages by end user clients.
'';
};
submissionOptions = mkOption {
type = types.attrs;
default = {
@ -298,6 +309,29 @@ in
description = "Options for the submission config in master.cf";
};
submissionsOptions = mkOption {
type = types.attrs;
default = {
smtpd_sasl_auth_enable = "yes";
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
milter_macro_daemon_name = "ORIGINATING";
};
example = {
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 via smtps in master.cf.
smtpd_tls_security_level will be set to encrypt, if it is missing
or has one of the values "may" or "none".
smtpd_tls_wrappermode with value "yes" will be added automatically.
'';
};
setSendmail = mkOption {
type = types.bool;
default = true;
@ -878,6 +912,23 @@ in
command = "smtp";
args = [ "-o" "smtp_fallback_relay=" ];
};
} // optionalAttrs cfg.enableSubmissions {
submissions = {
type = "inet";
private = false;
command = "smtpd";
args = let
mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
adjustSmtpTlsSecurityLevel = !(cfg.submissionsOptions ? smtpd_tls_security_level) ||
cfg.submissionsOptions.smtpd_tls_security_level == "none" ||
cfg.submissionsOptions.smtpd_tls_security_level == "may";
submissionsOptions = cfg.submissionsOptions // {
smtpd_tls_wrappermode = "yes";
} // optionalAttrs adjustSmtpTlsSecurityLevel {
smtpd_tls_security_level = "encrypt";
};
in concatLists (mapAttrsToList mkKeyVal submissionsOptions);
};
};
}

View File

@ -240,6 +240,7 @@ in {
'');
serviceConfig = {
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = "hass";
Group = "hass";
Restart = "on-failure";

View File

@ -9,6 +9,9 @@ let
logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
pluginsEnv = cfg.package.python.buildEnv.override {
extraLibs = cfg.plugins;
};
configFile = pkgs.writeText "homeserver.yaml" ''
${optionalString (cfg.tls_certificate_path != null) ''
tls_certificate_path: "${cfg.tls_certificate_path}"
@ -125,6 +128,14 @@ in {
Overridable attribute of the matrix synapse server package to use.
'';
};
plugins = mkOption {
type = types.listOf types.package;
default = [ ];
defaultText = "with config.services.matrix-synapse.package.plugins [ matrix-synapse-ldap3 matrix-synapse-pam ]";
description = ''
List of additional Matrix plugins to make available.
'';
};
no_tls = mkOption {
type = types.bool;
default = false;
@ -686,6 +697,7 @@ in {
--keys-directory ${cfg.dataDir} \
--generate-keys
'';
environment.PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ];
serviceConfig = {
Type = "notify";
User = "matrix-synapse";
@ -715,5 +727,6 @@ in {
];
meta.doc = ./matrix-synapse.xml;
meta.maintainers = teams.matrix.members;
}

View File

@ -193,50 +193,111 @@ in
};
buildMachines = mkOption {
type = types.listOf types.attrs;
type = types.listOf (types.submodule ({
options = {
hostName = mkOption {
type = types.str;
example = "nixbuilder.example.org";
description = ''
The hostname of the build machine.
'';
};
system = mkOption {
type = types.nullOr types.str;
default = null;
example = "x86_64-linux";
description = ''
The system type the build machine can execute derivations on.
Either this attribute or <varname>systems</varname> must be
present, where <varname>system</varname> takes precedence if
both are set.
'';
};
systems = mkOption {
type = types.listOf types.str;
default = [];
example = [ "x86_64-linux" "aarch64-linux" ];
description = ''
The system types the build machine can execute derivations on.
Either this attribute or <varname>system</varname> must be
present, where <varname>system</varname> takes precedence if
both are set.
'';
};
sshUser = mkOption {
type = types.nullOr types.str;
default = null;
example = "builder";
description = ''
The username to log in as on the remote host. This user must be
able to log in and run nix commands non-interactively. It must
also be privileged to build derivations, so must be included in
<option>nix.trustedUsers</option>.
'';
};
sshKey = mkOption {
type = types.nullOr types.str;
default = null;
example = "/root/.ssh/id_buildhost_builduser";
description = ''
The path to the SSH private key with which to authenticate on
the build machine. The private key must not have a passphrase.
If null, the building user (root on NixOS machines) must have an
appropriate ssh configuration to log in non-interactively.
Note that for security reasons, this path must point to a file
in the local filesystem, *not* to the nix store.
'';
};
maxJobs = mkOption {
type = types.int;
default = 1;
description = ''
The number of concurrent jobs the build machine supports. The
build machine will enforce its own limits, but this allows hydra
to schedule better since there is no work-stealing between build
machines.
'';
};
speedFactor = mkOption {
type = types.int;
default = 1;
description = ''
The relative speed of this builder. This is an arbitrary integer
that indicates the speed of this builder, relative to other
builders. Higher is faster.
'';
};
mandatoryFeatures = mkOption {
type = types.listOf types.str;
default = [];
example = [ "big-parallel" ];
description = ''
A list of features mandatory for this builder. The builder will
be ignored for derivations that don't require all features in
this list. All mandatory features are automatically included in
<varname>supportedFeatures</varname>.
'';
};
supportedFeatures = mkOption {
type = types.listOf types.str;
default = [];
example = [ "kvm" "big-parallel" ];
description = ''
A list of features supported by this builder. The builder will
be ignored for derivations that require features not in this
list.
'';
};
};
}));
default = [];
example = literalExample ''
[ { hostName = "voila.labs.cs.uu.nl";
sshUser = "nix";
sshKey = "/root/.ssh/id_buildfarm";
system = "powerpc-darwin";
maxJobs = 1;
}
{ hostName = "linux64.example.org";
sshUser = "buildfarm";
sshKey = "/root/.ssh/id_buildfarm";
system = "x86_64-linux";
maxJobs = 2;
speedFactor = 2;
supportedFeatures = [ "kvm" ];
mandatoryFeatures = [ "perf" ];
}
]
'';
description = ''
This option lists the machines to be used if distributed
builds are enabled (see
<option>nix.distributedBuilds</option>). Nix will perform
derivations on those machines via SSH by copying the inputs
to the Nix store on the remote machine, starting the build,
then copying the output back to the local Nix store. Each
element of the list should be an attribute set containing
the machine's host name (<varname>hostname</varname>), the
user name to be used for the SSH connection
(<varname>sshUser</varname>), the Nix system type
(<varname>system</varname>, e.g.,
<literal>"i686-linux"</literal>), the maximum number of
jobs to be run in parallel on that machine
(<varname>maxJobs</varname>), the path to the SSH private
key to be used to connect (<varname>sshKey</varname>), a
list of supported features of the machine
(<varname>supportedFeatures</varname>) and a list of
mandatory features of the machine
(<varname>mandatoryFeatures</varname>). The SSH private key
should not have a passphrase, and the corresponding public
key should be added to
<filename>~<replaceable>sshUser</replaceable>/authorized_keys</filename>
on the remote machine.
This option lists the machines to be used if distributed builds are
enabled (see <option>nix.distributedBuilds</option>).
Nix will perform derivations on those machines via SSH by copying the
inputs to the Nix store on the remote machine, starting the build,
then copying the output back to the local Nix store.
'';
};
@ -461,14 +522,14 @@ in
{ enable = cfg.buildMachines != [];
text =
concatMapStrings (machine:
"${if machine ? sshUser then "${machine.sshUser}@" else ""}${machine.hostName} "
+ machine.system or (concatStringsSep "," machine.systems)
+ " ${machine.sshKey or "-"} ${toString machine.maxJobs or 1} "
+ toString (machine.speedFactor or 1)
"${if machine.sshUser != null then "${machine.sshUser}@" else ""}${machine.hostName} "
+ (if machine.system != null then machine.system else concatStringsSep "," machine.systems)
+ " ${if machine.sshKey != null then machine.sshKey else "-"} ${toString machine.maxJobs} "
+ toString (machine.speedFactor)
+ " "
+ concatStringsSep "," (machine.mandatoryFeatures or [] ++ machine.supportedFeatures or [])
+ concatStringsSep "," (machine.mandatoryFeatures ++ machine.supportedFeatures)
+ " "
+ concatStringsSep "," machine.mandatoryFeatures or []
+ concatStringsSep "," machine.mandatoryFeatures
+ "\n"
) cfg.buildMachines;
};

View File

@ -21,6 +21,7 @@ let
# `serviceOpts.script` or `serviceOpts.serviceConfig.ExecStart`
exporterOpts = genAttrs [
"apcupsd"
"bind"
"blackbox"
"collectd"
@ -28,6 +29,8 @@ let
"dovecot"
"fritzbox"
"json"
"keylight"
"lnd"
"mail"
"mikrotik"
"minio"
@ -36,6 +39,7 @@ let
"node"
"postfix"
"postgres"
"redis"
"rspamd"
"snmp"
"surfboard"
@ -168,15 +172,6 @@ in
(opt: lib.mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] ''
The prometheus exporters are now configured using `services.prometheus.exporters'.
See the 18.03 release notes for more information.
'' ))
++ (lib.forEach [ "enable" "substitutions" "preset" ]
(opt: lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
The fonts.fontconfig.ultimate module and configuration is obsolete.
The repository has since been archived and activity has ceased.
https://github.com/bohoomil/fontconfig-ultimate/issues/171.
No action should be needed for font configuration, as the fonts.fontconfig
module is already used by default.
'' ));
options.services.prometheus.exporters = mkOption {

View File

@ -0,0 +1,38 @@
{ config, lib, pkgs, options }:
with lib;
let
cfg = config.services.prometheus.exporters.apcupsd;
in
{
port = 9162;
extraOpts = {
apcupsdAddress = mkOption {
type = types.str;
default = ":3551";
description = ''
Address of the apcupsd Network Information Server (NIS).
'';
};
apcupsdNetwork = mkOption {
type = types.enum ["tcp" "tcp4" "tcp6"];
default = "tcp";
description = ''
Network of the apcupsd Network Information Server (NIS): one of "tcp", "tcp4", or "tcp6".
'';
};
};
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-apcupsd-exporter}/bin/apcupsd_exporter \
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
-apcupsd.addr ${cfg.apcupsdAddress} \
-apcupsd.network ${cfg.apcupsdNetwork} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View File

@ -0,0 +1,19 @@
{ config, lib, pkgs, options }:
with lib;
let
cfg = config.services.prometheus.exporters.keylight;
in
{
port = 9288;
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-keylight-exporter}/bin/keylight_exporter \
-metrics.addr ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View File

@ -0,0 +1,46 @@
{ config, lib, pkgs, options }:
with lib;
let
cfg = config.services.prometheus.exporters.lnd;
in
{
port = 9092;
extraOpts = {
lndHost = mkOption {
type = types.str;
default = "localhost:10009";
description = ''
lnd instance gRPC address:port.
'';
};
lndTlsPath = mkOption {
type = types.path;
description = ''
Path to lnd TLS certificate.
'';
};
lndMacaroonDir = mkOption {
type = types.path;
description = ''
Path to lnd macaroons.
'';
};
};
serviceOpts.serviceConfig = {
ExecStart = ''
${pkgs.prometheus-lnd-exporter}/bin/lndmon \
--prometheus.listenaddr=${cfg.listenAddress}:${toString cfg.port} \
--prometheus.logdir=/var/log/prometheus-lnd-exporter \
--lnd.host=${cfg.lndHost} \
--lnd.tlspath=${cfg.lndTlsPath} \
--lnd.macaroondir=${cfg.lndMacaroonDir} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
LogsDirectory = "prometheus-lnd-exporter";
ReadOnlyPaths = [ cfg.lndTlsPath cfg.lndMacaroonDir ];
};
}

View File

@ -0,0 +1,19 @@
{ config, lib, pkgs, options }:
with lib;
let
cfg = config.services.prometheus.exporters.redis;
in
{
port = 9121;
serviceOpts = {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-redis-exporter}/bin/redis_exporter \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
};
}

View File

@ -32,7 +32,10 @@ in {
environment.systemPackages = [ pkgs.tuptime ];
users.users.tuptime.description = "tuptime database owner";
users = {
groups._tuptime.members = [ "_tuptime" ];
users._tuptime.description = "tuptime database owner";
};
systemd = {
services = {
@ -45,7 +48,7 @@ in {
serviceConfig = {
StateDirectory = "tuptime";
Type = "oneshot";
User = "tuptime";
User = "_tuptime";
RemainAfterExit = true;
ExecStart = "${pkgs.tuptime}/bin/tuptime -x";
ExecStop = "${pkgs.tuptime}/bin/tuptime -xg";
@ -57,7 +60,7 @@ in {
serviceConfig = {
StateDirectory = "tuptime";
Type = "oneshot";
User = "tuptime";
User = "_tuptime";
ExecStart = "${pkgs.tuptime}/bin/tuptime -x";
};
};

View File

@ -1,69 +1,30 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, options, ... }:
with lib;
let
inherit (pkgs) ipfs runCommand makeWrapper;
cfg = config.services.ipfs;
opt = options.services.ipfs;
ipfsFlags = toString ([
(optionalString cfg.autoMount "--mount")
#(optionalString cfg.autoMigrate "--migrate")
(optionalString cfg.enableGC "--enable-gc")
(optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false")
(optionalString (cfg.defaultMode == "offline") "--offline")
(optionalString (cfg.defaultMode == "norouting") "--routing=none")
] ++ cfg.extraFlags);
defaultDataDir = if versionAtLeast config.system.stateVersion "17.09" then
"/var/lib/ipfs" else
"/var/lib/ipfs/.ipfs";
splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw);
# Wrapping the ipfs binary with the environment variable IPFS_PATH set to dataDir because we can't set it in the user environment
wrapped = runCommand "ipfs" { buildInputs = [ makeWrapper ]; preferLocalBuild = true; } ''
mkdir -p "$out/bin"
makeWrapper "${ipfs}/bin/ipfs" "$out/bin/ipfs" \
--set IPFS_PATH ${cfg.dataDir} \
--prefix PATH : /run/wrappers/bin
'';
multiaddrToListenStream = addrRaw: let
addr = splitMulitaddr addrRaw;
s = builtins.elemAt addr;
in if s 0 == "ip4" && s 2 == "tcp"
then "${s 1}:${s 3}"
else if s 0 == "ip6" && s 2 == "tcp"
then "[${s 1}]:${s 3}"
else if s 0 == "unix"
then "/${lib.concatStringsSep "/" (lib.tail addr)}"
else null; # not valid for listen stream, skip
commonEnv = {
environment.IPFS_PATH = cfg.dataDir;
path = [ wrapped ];
serviceConfig.User = cfg.user;
serviceConfig.Group = cfg.group;
};
baseService = recursiveUpdate commonEnv {
wants = [ "ipfs-init.service" ];
# NB: migration must be performed prior to pre-start, else we get the failure message!
preStart = optionalString cfg.autoMount ''
ipfs --local config Mounts.FuseAllowOther --json true
ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir}
ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir}
'' + concatStringsSep "\n" (collect
isString
(mapAttrsRecursive
(path: value:
# Using heredoc below so that the value is never improperly quoted
''
read value <<EOF
${builtins.toJSON value}
EOF
ipfs --local config --json "${concatStringsSep "." path}" "$value"
'')
({ Addresses.API = cfg.apiAddress;
Addresses.Gateway = cfg.gatewayAddress;
Addresses.Swarm = cfg.swarmAddress;
} //
cfg.extraConfig))
);
serviceConfig = {
ExecStart = "${wrapped}/bin/ipfs daemon ${ipfsFlags}";
Restart = "on-failure";
RestartSec = 1;
} // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; };
};
in {
###### interface
@ -88,7 +49,9 @@ in {
dataDir = mkOption {
type = types.str;
default = defaultDataDir;
default = if versionAtLeast config.system.stateVersion "17.09"
then "/var/lib/ipfs"
else "/var/lib/ipfs/.ipfs";
description = "The data dir for IPFS";
};
@ -98,18 +61,6 @@ in {
description = "systemd service that is enabled by default";
};
/*
autoMigrate = mkOption {
type = types.bool;
default = false;
description = ''
Whether IPFS should try to migrate the file system automatically.
The daemon will need to be able to download a binary from https://ipfs.io to perform the migration.
'';
};
*/
autoMount = mkOption {
type = types.bool;
default = false;
@ -142,7 +93,10 @@ in {
swarmAddress = mkOption {
type = types.listOf types.str;
default = [ "/ip4/0.0.0.0/tcp/4001" "/ip6/::/tcp/4001" ];
default = [
"/ip4/0.0.0.0/tcp/4001"
"/ip6/::/tcp/4001"
];
description = "Where IPFS listens for incoming p2p connections";
};
@ -199,13 +153,21 @@ in {
example = 64*1024;
};
startWhenNeeded = mkOption {
type = types.bool;
default = false;
description = "Whether to use socket activation to start IPFS when needed.";
};
};
};
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ wrapped ];
environment.systemPackages = [ pkgs.ipfs ];
environment.variables.IPFS_PATH = cfg.dataDir;
programs.fuse = mkIf cfg.autoMount {
userAllowOther = true;
};
@ -234,10 +196,14 @@ in {
"d '${cfg.ipnsMountDir}' - ${cfg.user} ${cfg.group} - -"
];
systemd.services.ipfs-init = recursiveUpdate commonEnv {
systemd.packages = [ pkgs.ipfs ];
systemd.services.ipfs-init = {
description = "IPFS Initializer";
before = [ "ipfs.service" "ipfs-offline.service" "ipfs-norouting.service" ];
environment.IPFS_PATH = cfg.dataDir;
path = [ pkgs.ipfs ];
script = ''
if [[ ! -f ${cfg.dataDir}/config ]]; then
@ -251,34 +217,67 @@ in {
fi
'';
wantedBy = [ "default.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = cfg.user;
Group = cfg.group;
};
};
# TODO These 3 definitions possibly be further abstracted through use of a function
# like: mutexServices "ipfs" [ "", "offline", "norouting" ] { ... shared conf here ... }
systemd.services.ipfs = {
path = [ "/run/wrappers" pkgs.ipfs ];
environment.IPFS_PATH = cfg.dataDir;
systemd.services.ipfs = recursiveUpdate baseService {
description = "IPFS Daemon";
wantedBy = mkIf (cfg.defaultMode == "online") [ "multi-user.target" ];
after = [ "network.target" "ipfs-init.service" ];
conflicts = [ "ipfs-offline.service" "ipfs-norouting.service"];
wants = [ "ipfs-init.service" ];
after = [ "ipfs-init.service" ];
preStart = optionalString cfg.autoMount ''
ipfs --local config Mounts.FuseAllowOther --json true
ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir}
ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir}
'' + concatStringsSep "\n" (collect
isString
(mapAttrsRecursive
(path: value:
# Using heredoc below so that the value is never improperly quoted
''
read value <<EOF
${builtins.toJSON value}
EOF
ipfs --local config --json "${concatStringsSep "." path}" "$value"
'')
({ Addresses.API = cfg.apiAddress;
Addresses.Gateway = cfg.gatewayAddress;
Addresses.Swarm = cfg.swarmAddress;
} //
cfg.extraConfig))
);
serviceConfig = {
ExecStart = ["" "${pkgs.ipfs}/bin/ipfs daemon ${ipfsFlags}"];
User = cfg.user;
Group = cfg.group;
} // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; };
} // optionalAttrs (!cfg.startWhenNeeded) {
wantedBy = [ "default.target" ];
};
systemd.services.ipfs-offline = recursiveUpdate baseService {
description = "IPFS Daemon (offline mode)";
wantedBy = mkIf (cfg.defaultMode == "offline") [ "multi-user.target" ];
after = [ "ipfs-init.service" ];
conflicts = [ "ipfs.service" "ipfs-norouting.service"];
systemd.sockets.ipfs-gateway = {
wantedBy = [ "sockets.target" ];
socketConfig.ListenStream = let
fromCfg = multiaddrToListenStream cfg.gatewayAddress;
in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
};
systemd.services.ipfs-norouting = recursiveUpdate baseService {
description = "IPFS Daemon (no routing mode)";
wantedBy = mkIf (cfg.defaultMode == "norouting") [ "multi-user.target" ];
after = [ "ipfs-init.service" ];
conflicts = [ "ipfs.service" "ipfs-offline.service"];
systemd.sockets.ipfs-api = {
wantedBy = [ "sockets.target" ];
# We also include "%t/ipfs.sock" because tere is no way to put the "%t"
# in the multiaddr.
socketConfig.ListenStream = let
fromCfg = multiaddrToListenStream cfg.apiAddress;
in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg;
};
};

View File

@ -124,7 +124,7 @@ in {
<literal>"iponly"</literal>: specifies no authentication. ACLs authorization is used.
</para></listitem>
<listitem><para>
<literal>"strong"</literal>: authentication by username/password. If user is not registered his access is denied regardless of ACLs.
<literal>"strong"</literal>: authentication by username/password. If user is not registered their access is denied regardless of ACLs.
</para></listitem>
</itemizedlist>

View File

@ -0,0 +1,272 @@
{ config, lib, pkgs, ... }:
with lib;
let
eachBlockbook = config.services.blockbook-frontend;
blockbookOpts = { config, lib, name, ...}: {
options = {
enable = mkEnableOption "blockbook-frontend application.";
package = mkOption {
type = types.package;
default = pkgs.blockbook;
description = "Which blockbook package to use.";
};
user = mkOption {
type = types.str;
default = "blockbook-frontend-${name}";
description = "The user as which to run blockbook-frontend-${name}.";
};
group = mkOption {
type = types.str;
default = "${config.user}";
description = "The group as which to run blockbook-frontend-${name}.";
};
certFile = mkOption {
type = types.nullOr types.path;
default = null;
example = "/etc/secrets/blockbook-frontend-${name}/certFile";
description = ''
To enable SSL, specify path to the name of certificate files without extension.
Expecting <filename>certFile.crt</filename> and <filename>certFile.key</filename>.
'';
};
configFile = mkOption {
type = with types; nullOr path;
default = null;
example = "${config.dataDir}/config.json";
description = "Location of the blockbook configuration file.";
};
coinName = mkOption {
type = types.str;
default = "Bitcoin";
example = "Bitcoin";
description = ''
See <link xlink:href="https://github.com/trezor/blockbook/blob/master/bchain/coins/blockchain.go#L61"/>
for current of coins supported in master (Note: may differ from release).
'';
};
cssDir = mkOption {
type = types.path;
default = "${config.package}/share/css/";
example = "${config.dataDir}/static/css/";
description = ''
Location of the dir with <filename>main.css</filename> CSS file.
By default, the one shipped with the package is used.
'';
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/blockbook-frontend-${name}";
description = "Location of blockbook-frontend-${name} data directory.";
};
debug = mkOption {
type = types.bool;
default = false;
description = "Debug mode, return more verbose errors, reload templates on each request.";
};
internal = mkOption {
type = types.nullOr types.str;
default = ":9030";
example = ":9030";
description = "Internal http server binding <literal>[address]:port</literal>.";
};
messageQueueBinding = mkOption {
type = types.str;
default = "tcp://127.0.0.1:38330";
example = "tcp://127.0.0.1:38330";
description = "Message Queue Binding <literal>address:port</literal>.";
};
public = mkOption {
type = types.nullOr types.str;
default = ":9130";
example = ":9130";
description = "Public http server binding <literal>[address]:port</literal>.";
};
rpc = {
url = mkOption {
type = types.str;
default = "http://127.0.0.1";
description = "URL for JSON-RPC connections.";
};
port = mkOption {
type = types.port;
default = 8030;
description = "Port for JSON-RPC connections.";
};
user = mkOption {
type = types.str;
default = "rpc";
example = "rpc";
description = "Username for JSON-RPC connections.";
};
password = mkOption {
type = types.str;
default = "rpc";
example = "rpc";
description = ''
RPC password for JSON-RPC connections.
Warning: this is stored in cleartext in the Nix store!!!
Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed.
'';
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing password of the RPC user.
Note: This options is ignored when <literal>configFile</literal> is used.
'';
};
};
sync = mkOption {
type = types.bool;
default = true;
description = "Synchronizes until tip, if together with zeromq, keeps index synchronized.";
};
templateDir = mkOption {
type = types.path;
default = "${config.package}/share/templates/";
example = "${config.dataDir}/templates/static/";
description = "Location of the HTML templates. By default, ones shipped with the package are used.";
};
extraConfig = mkOption {
type = types.attrs;
default = {};
example = literalExample '' {
alternative_estimate_fee = "whatthefee-disabled";
alternative_estimate_fee_params = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}";
fiat_rates = "coingecko";
fiat_rates_params = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}";
coin_shortcut = "BTC";
coin_label = "Bitcoin";
xpub_magic = 76067358;
xpub_magic_segwit_p2sh = 77429938;
xpub_magic_segwit_native = 78792518;
}'';
description = ''
Additional configurations to be appended to <filename>coin.conf</filename>.
Overrides any already defined configuration options.
See <link xlink:href="https://github.com/trezor/blockbook/tree/master/configs/coins"/>
for current configuration options supported in master (Note: may differ from release).
'';
};
extraCmdLineOptions = mkOption {
type = types.listOf types.str;
default = [];
example = [ "-workers=1" "-dbcache=0" "-logtosderr" ];
description = ''
Extra command line options to pass to Blockbook.
Run blockbook --help to list all available options.
'';
};
};
};
in
{
# interface
options = {
services.blockbook-frontend = mkOption {
type = types.attrsOf (types.submodule blockbookOpts);
default = {};
description = "Specification of one or more blockbook-frontend instances.";
};
};
# implementation
config = mkIf (eachBlockbook != {}) {
systemd.services = mapAttrs' (blockbookName: cfg: (
nameValuePair "blockbook-frontend-${blockbookName}" (
let
configFile = if cfg.configFile != null then cfg.configFile else
pkgs.writeText "config.conf" (builtins.toJSON ( {
coin_name = "${cfg.coinName}";
rpc_user = "${cfg.rpc.user}";
rpc_pass = "${cfg.rpc.password}";
rpc_url = "${cfg.rpc.url}:${toString cfg.rpc.port}";
message_queue_binding = "${cfg.messageQueueBinding}";
} // cfg.extraConfig)
);
in {
description = "blockbook-frontend-${blockbookName} daemon";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
ln -sf ${cfg.templateDir} ${cfg.dataDir}/static/
ln -sf ${cfg.cssDir} ${cfg.dataDir}/static/
${optionalString (cfg.rpc.passwordFile != null && cfg.configFile == null) ''
CONFIGTMP=$(mktemp)
${pkgs.jq}/bin/jq ".rpc_pass = \"$(cat ${cfg.rpc.passwordFile})\"" ${configFile} > $CONFIGTMP
mv $CONFIGTMP ${cfg.dataDir}/${blockbookName}-config.json
''}
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
ExecStart = ''
${cfg.package}/bin/blockbook \
${if (cfg.rpc.passwordFile != null && cfg.configFile == null) then
"-blockchaincfg=${cfg.dataDir}/${blockbookName}-config.json"
else
"-blockchaincfg=${configFile}"
} \
-datadir=${cfg.dataDir} \
${optionalString (cfg.sync != false) "-sync"} \
${optionalString (cfg.certFile != null) "-certfile=${toString cfg.certFile}"} \
${optionalString (cfg.debug != false) "-debug"} \
${optionalString (cfg.internal != null) "-internal=${toString cfg.internal}"} \
${optionalString (cfg.public != null) "-public=${toString cfg.public}"} \
${toString cfg.extraCmdLineOptions}
'';
Restart = "on-failure";
WorkingDirectory = cfg.dataDir;
LimitNOFILE = 65536;
};
}
) )) eachBlockbook;
systemd.tmpfiles.rules = flatten (mapAttrsToList (blockbookName: cfg: [
"d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
"d ${cfg.dataDir}/static 0750 ${cfg.user} ${cfg.group} - -"
]) eachBlockbook);
users.users = mapAttrs' (blockbookName: cfg: (
nameValuePair "blockbook-frontend-${blockbookName}" {
name = cfg.user;
group = cfg.group;
home = cfg.dataDir;
isSystemUser = true;
})) eachBlockbook;
users.groups = mapAttrs' (instanceName: cfg: (
nameValuePair "${cfg.group}" { })) eachBlockbook;
};
}

View File

@ -4,14 +4,50 @@ with lib;
let
cfg = config.services.corerad;
writeTOML = name: x:
pkgs.runCommandNoCCLocal name {
passAsFile = ["config"];
config = builtins.toJSON x;
buildInputs = [ pkgs.go-toml ];
} "jsontoml < $configPath > $out";
in {
meta = {
maintainers = with maintainers; [ mdlayher ];
};
meta.maintainers = with maintainers; [ mdlayher ];
options.services.corerad = {
enable = mkEnableOption "CoreRAD IPv6 NDP RA daemon";
settings = mkOption {
type = types.uniq types.attrs;
example = literalExample ''
{
interfaces = [
# eth0 is an upstream interface monitoring for IPv6 router advertisements.
{
name = "eth0";
monitor = true;
}
# eth1 is a downstream interface advertising IPv6 prefixes for SLAAC.
{
name = "eth1";
advertise = true;
prefix = [{ prefix = "::/64"; }];
}
];
# Optionally enable Prometheus metrics.
debug = {
address = "localhost:9430";
prometheus = true;
};
}
'';
description = ''
Configuration for CoreRAD, see <link xlink:href="https://github.com/mdlayher/corerad/blob/master/internal/config/default.toml"/>
for supported values. Ignored if configFile is set.
'';
};
configFile = mkOption {
type = types.path;
example = literalExample "\"\${pkgs.corerad}/etc/corerad/corerad.toml\"";
@ -27,6 +63,9 @@ in {
};
config = mkIf cfg.enable {
# Prefer the config file over settings if both are set.
services.corerad.configFile = mkDefault (writeTOML "corerad.toml" cfg.settings);
systemd.services.corerad = {
description = "CoreRAD IPv6 NDP RA daemon";
after = [ "network.target" ];
@ -38,6 +77,8 @@ in {
AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW";
NoNewPrivileges = true;
DynamicUser = true;
Type = "notify";
NotifyAccess = "main";
ExecStart = "${getBin cfg.package}/bin/corerad -c=${cfg.configFile}";
Restart = "on-failure";
};

View File

@ -1,184 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfgs = config.services;
cfg = cfgs.dnschain;
dataDir = "/var/lib/dnschain";
username = "dnschain";
configFile = pkgs.writeText "dnschain.conf" ''
[log]
level = info
[dns]
host = ${cfg.dns.address}
port = ${toString cfg.dns.port}
oldDNSMethod = NO_OLD_DNS
externalIP = ${cfg.dns.externalAddress}
[http]
host = ${cfg.api.hostname}
port = ${toString cfg.api.port}
tlsPort = ${toString cfg.api.tlsPort}
${cfg.extraConfig}
'';
in
{
###### interface
options = {
services.dnschain = {
enable = mkEnableOption ''
DNSChain, a blockchain based DNS + HTTP server.
To resolve .bit domains set <literal>services.namecoind.enable = true;</literal>
and an RPC username/password.
'';
dns.address = mkOption {
type = types.str;
default = "127.0.0.1";
description = ''
The IP address the DNSChain resolver will bind to.
Leave this unchanged if you do not wish to directly expose the resolver.
'';
};
dns.externalAddress = mkOption {
type = types.str;
default = cfg.dns.address;
description = ''
The IP address used by clients to reach the resolver and the value of
the <literal>namecoin.dns</literal> record. Set this in case the bind address
is not the actual IP address (e.g. the machine is behind a NAT).
'';
};
dns.port = mkOption {
type = types.int;
default = 5333;
description = ''
The port the DNSChain resolver will bind to.
'';
};
api.hostname = mkOption {
type = types.str;
default = "0.0.0.0";
description = ''
The hostname (or IP address) the DNSChain API server will bind to.
'';
};
api.port = mkOption {
type = types.int;
default = 8080;
description = ''
The port the DNSChain API server (HTTP) will bind to.
'';
};
api.tlsPort = mkOption {
type = types.int;
default = 4433;
description = ''
The port the DNSChain API server (HTTPS) will bind to.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
example = ''
[log]
level = debug
'';
description = ''
Additional options that will be appended to the configuration file.
'';
};
};
services.dnsmasq.resolveDNSChainQueries = mkOption {
type = types.bool;
default = false;
description = ''
Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
'';
};
services.pdns-recursor.resolveDNSChainQueries = mkOption {
type = types.bool;
default = false;
description = ''
Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
'';
};
};
###### implementation
config = mkIf cfg.enable {
services.dnsmasq.servers = optionals cfgs.dnsmasq.resolveDNSChainQueries
[ "/.bit/127.0.0.1#${toString cfg.dns.port}"
"/.dns/127.0.0.1#${toString cfg.dns.port}"
];
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
forwardZonesRecurse =
{ bit = "127.0.0.1:${toString cfg.dns.port}";
dns = "127.0.0.1:${toString cfg.dns.port}";
};
luaConfig =''
addNTA("bit", "namecoin doesn't support DNSSEC")
addNTA("dns", "namecoin doesn't support DNSSEC")
'';
};
users.users.${username} = {
description = "DNSChain daemon user";
home = dataDir;
createHome = true;
uid = config.ids.uids.dnschain;
extraGroups = optional cfgs.namecoind.enable "namecoin";
};
systemd.services.dnschain = {
description = "DNSChain daemon";
after = optional cfgs.namecoind.enable "namecoind.target";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = "dnschain";
Restart = "on-failure";
ExecStart = "${pkgs.nodePackages.dnschain}/bin/dnschain";
};
preStart = ''
# Link configuration file into dnschain home directory
configPath=${dataDir}/.dnschain/dnschain.conf
mkdir -p ${dataDir}/.dnschain
if [ "$(realpath $configPath)" != "${configFile}" ]; then
rm -f $configPath
ln -s ${configFile} $configPath
fi
'';
};
};
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
}

View File

@ -0,0 +1,53 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.go-neb;
configFile = pkgs.writeText "config.yml" (builtins.toJSON cfg.config);
in {
options.services.go-neb = {
enable = mkEnableOption "Extensible matrix bot written in Go";
bindAddress = mkOption {
type = types.str;
description = "Port (and optionally address) to listen on.";
default = ":4050";
};
baseUrl = mkOption {
type = types.str;
description = "Public-facing endpoint that can receive webhooks.";
};
config = mkOption {
type = types.uniq types.attrs;
description = ''
Your <filename>config.yaml</filename> as a Nix attribute set.
See <link xlink:href="https://github.com/matrix-org/go-neb/blob/master/config.sample.yaml">config.sample.yaml</link>
for possible options.
'';
};
};
config = mkIf cfg.enable {
systemd.services.go-neb = {
description = "Extensible matrix bot written in Go";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = {
BASE_URL = cfg.baseUrl;
BIND_ADDRESS = cfg.bindAddress;
CONFIG_FILE = configFile;
};
serviceConfig = {
ExecStart = "${pkgs.go-neb}/bin/go-neb";
DynamicUser = true;
};
};
};
meta.maintainers = with maintainers; [ hexa maralorn ];
}

View File

@ -149,11 +149,6 @@ in
config = mkIf cfg.enable {
services.dnschain.extraConfig = ''
[namecoin]
config = ${configFile}
'';
users.users.namecoin = {
uid = config.ids.uids.namecoin;
description = "Namecoin daemon user";

View File

@ -11,8 +11,6 @@ let
# build nsd with the options needed for the given config
nsdPkg = pkgs.nsd.override {
configFile = "${configFile}/nsd.conf";
bind8Stats = cfg.bind8Stats;
ipv6 = cfg.ipv6;
ratelimit = cfg.ratelimit.enable;
@ -897,7 +895,10 @@ in
+ "want, please enable 'services.nsd.rootServer'.";
};
environment.systemPackages = [ nsdPkg ];
environment = {
systemPackages = [ nsdPkg ];
etc."nsd/nsd.conf".source = "${configFile}/nsd.conf";
};
users.groups.${username}.gid = config.ids.gids.nsd;

View File

@ -0,0 +1,72 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.onedrive;
onedriveLauncher = pkgs.writeShellScriptBin
"onedrive-launcher"
''
# XDG_CONFIG_HOME is not recognized in the environment here.
if [ -f $HOME/.config/onedrive-launcher ]
then
# Hopefully using underscore boundary helps locate variables
for _onedrive_config_dirname_ in $(cat $HOME/.config/onedrive-launcher | grep -v '[ \t]*#' )
do
systemctl --user start onedrive@$_onedrive_config_dirname_
done
else
systemctl --user start onedrive@onedrive
fi
''
;
in {
### Documentation
# meta.doc = ./onedrive.xml;
### Interface
options.services.onedrive = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable OneDrive service";
};
package = lib.mkOption {
type = lib.types.package;
default = pkgs.onedrive;
defaultText = "pkgs.onedrive";
example = lib.literalExample "pkgs.onedrive";
description = ''
OneDrive package to use.
'';
};
};
### Implementation
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
systemd.user.services."onedrive@" = {
description = "Onedrive sync service";
serviceConfig = {
Type = "simple";
ExecStart = ''
${cfg.package}/bin/onedrive --monitor --verbose --confdir=%h/.config/%i
'';
Restart="on-failure";
RestartSec=3;
RestartPreventExitStatus=3;
};
};
systemd.user.services.onedrive-launcher = {
wantedBy = [ "default.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${onedriveLauncher}/bin/onedrive-launcher";
};
};
};
}

View File

@ -0,0 +1,34 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="onedrive">
<title>Microsoft OneDrive</title>
<para>
Microsoft Onedrive is a popular cloud file-hosting service, used by 85% of Fortune 500 companies. NixOS uses a popular OneDrive client for Linux maintained by github user abraunegg. The Linux client is excellent and allows customization of which files or paths to download, not much unlike the default Windows OneDrive client by Microsoft itself. The client allows syncing with multiple onedrive accounts at the same time, of any type- OneDrive personal, OneDrive business, Office365 and Sharepoint libraries, without any additional charge.
</para>
<para>
For more information, guides and documentation, see <link xlink:href="https://abraunegg.github.io/"/>.
</para>
<para>
To enable OneDrive support, add the following to your <filename>configuration.nix</filename>:
<programlisting>
<xref linkend="opt-services.onedrive.enable"/> = true;
</programlisting>
This installs the <literal>onedrive</literal> package and a service <literal>onedriveLauncher</literal> which will instantiate a <literal>onedrive</literal> service for all your OneDrive accounts. Follow the steps in documentation of the onedrive client to setup your accounts. To use the service with multiple accounts, create a file named <filename>onedrive-launcher</filename> in <filename>~/.config</filename> and add the filename of the config directory, relative to <filename>~/.config</filename>. For example, if you have two OneDrive accounts with configs in <filename>~/.config/onedrive_bob_work</filename> and <filename>~/.config/onedrive_bob_personal</filename>, add the following lines:
<programlisting>
onedrive_bob_work
# Not in use:
# onedrive_bob_office365
onedrive_bob_personal
</programlisting>
No such file needs to be created if you are using only a single OneDrive account with config in the default location <filename>~/.config/onedrive</filename>, in the absence of <filename>~/.config/onedrive-launcher</filename>, only a single service is instantiated, with default config path.
</para>
<para>
If you wish to use a custom OneDrive package, say from another channel, add the following line:
<programlisting>
<xref linkend="opt-services.onedrive.package"/> = pkgs.unstable.onedrive;
</programlisting>
</para>
</chapter>

View File

@ -8,8 +8,10 @@ let
confFile = pkgs.writeText "radicale.conf" cfg.config;
# This enables us to default to version 2 while still not breaking configurations of people with version 1
defaultPackage = if versionAtLeast config.system.stateVersion "17.09" then {
defaultPackage = if versionAtLeast config.system.stateVersion "20.09" then {
pkg = pkgs.radicale3;
text = "pkgs.radicale3";
} else if versionAtLeast config.system.stateVersion "17.09" then {
pkg = pkgs.radicale2;
text = "pkgs.radicale2";
} else {
@ -35,8 +37,9 @@ in
defaultText = defaultPackage.text;
description = ''
Radicale package to use. This defaults to version 1.x if
<literal>system.stateVersion &lt; 17.09</literal> and version 2.x
otherwise.
<literal>system.stateVersion &lt; 17.09</literal>, version 2.x if
<literal>17.09 system.stateVersion &lt; 20.09</literal>, and
version 3.x otherwise.
'';
};

View File

@ -109,8 +109,8 @@ in
httpListenAddr = mkOption {
type = types.str;
default = "0.0.0.0";
example = "1.2.3.4";
default = "[::1]";
example = "0.0.0.0";
description = ''
HTTP address to bind to.
'';
@ -206,16 +206,16 @@ in
If you would like to be able to modify the contents of this
directories, it is recommended that you make your user a
member of the <literal>resilio</literal> group.
member of the <literal>rslsync</literal> group.
Directories in this list should be in the
<literal>resilio</literal> group, and that group must have
<literal>rslsync</literal> group, and that group must have
write access to the directory. It is also recommended that
<literal>chmod g+s</literal> is applied to the directory
so that any sub directories created will also belong to
the <literal>resilio</literal> group. Also,
<literal>setfacl -d -m group:resilio:rwx</literal> and
<literal>setfacl -m group:resilio:rwx</literal> should also
the <literal>rslsync</literal> group. Also,
<literal>setfacl -d -m group:rslsync:rwx</literal> and
<literal>setfacl -m group:rslsync:rwx</literal> should also
be applied so that the sub directories are writable by
the group.
'';

View File

@ -15,7 +15,11 @@ let
listen:
(
{ host: "${cfg.listenAddress}"; port: "${toString cfg.port}"; }
${
concatMapStringsSep ",\n"
(addr: ''{ host: "${addr}"; port: "${toString cfg.port}"; }'')
cfg.listenAddresses
}
);
${cfg.appendConfig}
@ -33,6 +37,10 @@ let
'';
in
{
imports = [
(mkRenamedOptionModule [ "services" "sslh" "listenAddress" ] [ "services" "sslh" "listenAddresses" ])
];
options = {
services.sslh = {
enable = mkEnableOption "sslh";
@ -55,10 +63,10 @@ in
description = "Will the services behind sslh (Apache, sshd and so on) see the external IP and ports as if the external world connected directly to them";
};
listenAddress = mkOption {
type = types.str;
default = "0.0.0.0";
description = "Listening address or hostname.";
listenAddresses = mkOption {
type = types.coercedTo types.str singleton (types.listOf types.str);
default = [ "0.0.0.0" "[::]" ];
description = "Listening addresses or hostnames.";
};
port = mkOption {

View File

@ -0,0 +1,158 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.wasabibackend;
inherit (lib) mkEnableOption mkIf mkOption optionalAttrs optionalString types;
confOptions = {
BitcoinRpcConnectionString = "${cfg.rpc.user}:${cfg.rpc.password}";
} // optionalAttrs (cfg.network == "mainnet") {
Network = "Main";
MainNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
MainNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
} // optionalAttrs (cfg.network == "testnet") {
Network = "TestNet";
TestNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
TestNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
} // optionalAttrs (cfg.network == "regtest") {
Network = "RegTest";
RegTestBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
RegTestBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
};
configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions);
in {
options = {
services.wasabibackend = {
enable = mkEnableOption "Wasabi backend service";
dataDir = mkOption {
type = types.path;
default = "/var/lib/wasabibackend";
description = "The data directory for the Wasabi backend node.";
};
customConfigFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "Defines the path to a custom configuration file that is copied to the user's directory. Overrides any config options.";
};
network = mkOption {
type = types.enum [ "mainnet" "testnet" "regtest" ];
default = "mainnet";
description = "The network to use for the Wasabi backend service.";
};
endpoint = {
ip = mkOption {
type = types.str;
default = "127.0.0.1";
description = "IP address for P2P connection to bitcoind.";
};
port = mkOption {
type = types.port;
default = 8333;
description = "Port for P2P connection to bitcoind.";
};
};
rpc = {
ip = mkOption {
type = types.str;
default = "127.0.0.1";
description = "IP address for RPC connection to bitcoind.";
};
port = mkOption {
type = types.port;
default = 8332;
description = "Port for RPC connection to bitcoind.";
};
user = mkOption {
type = types.str;
default = "bitcoin";
description = "RPC user for the bitcoin endpoint.";
};
password = mkOption {
type = types.str;
default = "password";
description = "RPC password for the bitcoin endpoint. Warning: this is stored in cleartext in the Nix store! Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed.";
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = "File that contains the password of the RPC user.";
};
};
user = mkOption {
type = types.str;
default = "wasabibackend";
description = "The user as which to run the wasabibackend node.";
};
group = mkOption {
type = types.str;
default = cfg.user;
description = "The group as which to run the wasabibackend node.";
};
};
};
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
];
systemd.services.wasabibackend = {
description = "wasabibackend server";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
environment = {
DOTNET_PRINT_TELEMETRY_MESSAGE = "false";
DOTNET_CLI_TELEMETRY_OPTOUT = "true";
};
preStart = ''
mkdir -p ${cfg.dataDir}/.walletwasabi/backend
${if cfg.customConfigFile != null then ''
cp -v ${cfg.customConfigFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
'' else ''
cp -v ${configFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
${optionalString (cfg.rpc.passwordFile != null) ''
CONFIGTMP=$(mktemp)
cat ${cfg.dataDir}/.walletwasabi/backend/Config.json | ${pkgs.jq}/bin/jq --arg rpconnection "${cfg.rpc.user}:$(cat "${cfg.rpc.passwordFile}")" '. + { BitcoinRpcConnectionString: $rpconnection }' > $CONFIGTMP
mv $CONFIGTMP ${cfg.dataDir}/.walletwasabi/backend/Config.json
''}
''}
chmod ug+w ${cfg.dataDir}/.walletwasabi/backend/Config.json
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
ExecStart = "${pkgs.wasabibackend}/bin/WasabiBackend";
ProtectSystem = "full";
};
};
users.users.${cfg.user} = {
name = cfg.user;
group = cfg.group;
description = "wasabibackend daemon user";
home = cfg.dataDir;
isSystemUser = true;
};
users.groups.${cfg.group} = {};
};
}

View File

@ -122,7 +122,7 @@ in
ExecStart = ''
${cfg.package}/bin/xandikos \
--directory /var/lib/xandikos \
--listen_address ${cfg.address} \
--listen-address ${cfg.address} \
--port ${toString cfg.port} \
--route-prefix ${cfg.routePrefix} \
${lib.concatStringsSep " " cfg.extraOptions}

View File

@ -4,12 +4,21 @@ with lib;
let
cfg = config.services.nginx.sso;
pkg = getBin pkgs.nginx-sso;
pkg = getBin cfg.package;
configYml = pkgs.writeText "nginx-sso.yml" (builtins.toJSON cfg.configuration);
in {
options.services.nginx.sso = {
enable = mkEnableOption "nginx-sso service";
package = mkOption {
type = types.package;
default = pkgs.nginx-sso;
defaultText = "pkgs.nginx-sso";
description = ''
The nginx-sso package that should be used.
'';
};
configuration = mkOption {
type = types.attrsOf types.unspecified;
default = {};

View File

@ -107,6 +107,7 @@ in
++ cfg.lockOn.extraTargets;
before = optional cfg.lockOn.suspend "systemd-suspend.service"
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
++ optional (cfg.lockOn.hibernate || cfg.lockOn.suspend) "systemd-suspend-then-hibernate.service"
++ cfg.lockOn.extraTargets;
serviceConfig = {
Type = "forking";

View File

@ -159,7 +159,7 @@ in
type = types.bool;
default = false;
description = ''
Wheter to enable Tor control socket. Control socket is created
Whether to enable Tor control socket. Control socket is created
in <literal>${torRunDirectory}/control</literal>
'';
};

View File

@ -179,6 +179,8 @@ in
${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
${getLib pkgs.gcc.cc.lib}/lib/libstdc++.so.* mr,
${getLib pkgs.gcc.cc.lib}/lib/libgcc_s.so.* mr,
@{PROC}/sys/kernel/random/uuid r,
@{PROC}/sys/vm/overcommit_memory r,

View File

@ -93,7 +93,7 @@ in
type = types.bool;
default = true;
description = ''
Wheter to enable HSTS if HTTPS is also enabled.
Whether to enable HSTS if HTTPS is also enabled.
'';
};
maxAgeSeconds = mkOption {
@ -385,7 +385,7 @@ in
type = types.bool;
default = true;
description = ''
Wether to enable email registration.
Whether to enable email registration.
'';
};
allowGravatar = mkOption {

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