Merge branch 'master' into flip-map-foreach
This commit is contained in:
commit
7585496eff
|
@ -107,8 +107,8 @@
|
|||
# Eclipse
|
||||
/pkgs/applications/editors/eclipse @rycee
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/issues/31401
|
||||
/lib/licenses.nix @ghost
|
||||
# Licenses
|
||||
/lib/licenses.nix @alyssais
|
||||
|
||||
# Qt / KDE
|
||||
/pkgs/applications/kde @ttuegel
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
custom: https://nixos.org/nixos/foundation.html
|
|
@ -8,5 +8,4 @@
|
|||
|
||||
## Technical details
|
||||
|
||||
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the
|
||||
results.
|
||||
Please run `nix run nixpkgs.nix-info -c nix-info -m` and paste the result.
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: '0.kind: bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
**Metadata**
|
||||
Please run `nix run nixpkgs.nix-info -c nix-info -m` and paste the result.
|
||||
|
||||
Maintainer information:
|
||||
```yaml
|
||||
# a list of nixpkgs attributes affected by the problem
|
||||
attribute:
|
||||
# a list of nixos modules affected by the problem
|
||||
module:
|
||||
```
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
name: Packaging requests
|
||||
about: For packages that are missing
|
||||
title: ''
|
||||
labels: '0.kind: packaging request'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Project description**
|
||||
_describe the project a little_
|
||||
|
||||
**Metadata**
|
||||
|
||||
* homepage URL:
|
||||
* source URL:
|
||||
* license: mit, bsd, gpl2+ , ...
|
||||
* platforms: unix, linux, darwin, ...
|
|
@ -18,4 +18,6 @@
|
|||
- [ ] Ensured that relevant documentation is up to date
|
||||
- [ ] Fits [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md).
|
||||
|
||||
---
|
||||
###### Notify maintainers
|
||||
|
||||
cc @
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[<img src="https://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />](https://nixos.org/nixos)
|
||||
|
||||
[![Code Triagers Badge](https://www.codetriage.com/nixos/nixpkgs/badges/users.svg)](https://www.codetriage.com/nixos/nixpkgs)
|
||||
[![Open Collective supporters](https://opencollective.com/nixos/tiers/supporter/badge.svg?label=Supporter&color=brightgreen)](https://opencollective.com/nixos)
|
||||
|
||||
Nixpkgs is a collection of packages for the [Nix](https://nixos.org/nix/) package
|
||||
manager. It is periodically built and tested by the [Hydra](https://hydra.nixos.org/)
|
||||
|
|
|
@ -10,7 +10,7 @@ stdenv.mkDerivation {
|
|||
name = "...";
|
||||
src = fetchurl { ... };
|
||||
|
||||
buildInputs = [ jdk ant ];
|
||||
nativeBuildInputs = [ jdk ant ];
|
||||
|
||||
buildPhase = "ant";
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ stdenv.mkDerivation {
|
|||
<filename>foo.jar</filename> in its <filename>share/java</filename>
|
||||
directory, and another package declares the attribute
|
||||
<programlisting>
|
||||
buildInputs = [ jdk libfoo ];
|
||||
buildInputs = [ libfoo ];
|
||||
nativeBuildInputs = [ jdk ];
|
||||
</programlisting>
|
||||
then <envar>CLASSPATH</envar> will be set to
|
||||
<filename>/nix/store/...-libfoo/share/java/foo.jar</filename>.
|
||||
|
@ -46,7 +47,7 @@ buildInputs = [ jdk libfoo ];
|
|||
script to run it using the OpenJRE. You can use
|
||||
<literal>makeWrapper</literal> for this:
|
||||
<programlisting>
|
||||
buildInputs = [ makeWrapper ];
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
||||
installPhase =
|
||||
''
|
||||
|
@ -76,7 +77,7 @@ installPhase =
|
|||
It is possible to use a different Java compiler than <command>javac</command>
|
||||
from the OpenJDK. For instance, to use the GNU Java Compiler:
|
||||
<programlisting>
|
||||
buildInputs = [ gcj ant ];
|
||||
nativeBuildInputs = [ gcj ant ];
|
||||
</programlisting>
|
||||
Here, Ant will automatically use <command>gij</command> (the GNU Java
|
||||
Runtime) instead of the OpenJRE.
|
||||
|
|
|
@ -603,6 +603,7 @@ All parameters from `stdenv.mkDerivation` function are still supported. The foll
|
|||
* `preShellHook`: Hook to execute commands before `shellHook`.
|
||||
* `postShellHook`: Hook to execute commands after `shellHook`.
|
||||
* `removeBinByteCode ? true`: Remove bytecode from `/bin`. Bytecode is only created when the filenames end with `.py`.
|
||||
* `setupPyGlobalFlags ? []`: List of flags passed to `setup.py` command.
|
||||
* `setupPyBuildFlags ? []`: List of flags passed to `setup.py build_ext` command.
|
||||
|
||||
The `stdenv.mkDerivation` function accepts various parameters for describing build inputs (see "Specifying dependencies"). The following are of special
|
||||
|
|
|
@ -4,71 +4,173 @@
|
|||
<title>Qt</title>
|
||||
|
||||
<para>
|
||||
Qt is a comprehensive desktop and mobile application development toolkit for
|
||||
C++. Legacy support is available for Qt 3 and Qt 4, but all current
|
||||
development uses Qt 5. The Qt 5 packages in Nixpkgs are updated frequently to
|
||||
take advantage of new features, but older versions are typically retained
|
||||
until their support window ends. The most important consideration in
|
||||
packaging Qt-based software is ensuring that each package and all its
|
||||
dependencies use the same version of Qt 5; this consideration motivates most
|
||||
of the tools described below.
|
||||
This section describes the differences between Nix expressions for Qt
|
||||
libraries and applications and Nix expressions for other C++ software. Some
|
||||
knowledge of the latter is assumed. There are primarily two problems which
|
||||
the Qt infrastructure is designed to address: ensuring consistent versioning
|
||||
of all dependencies and finding dependencies at runtime.
|
||||
</para>
|
||||
|
||||
<section xml:id="ssec-qt-libraries">
|
||||
<title>Packaging Libraries for Nixpkgs</title>
|
||||
<example xml:id='qt-default-nix'>
|
||||
<title>Nix expression for a Qt package (<filename>default.nix</filename>)</title>
|
||||
<programlisting>
|
||||
{ mkDerivation, lib, qtbase }: <co xml:id='qt-default-nix-co-1' />
|
||||
|
||||
<para>
|
||||
Whenever possible, libraries that use Qt 5 should be built with each
|
||||
available version. Packages providing libraries should be added to the
|
||||
top-level function <varname>mkLibsForQt5</varname>, which is used to build a
|
||||
set of libraries for every Qt 5 version. A special
|
||||
<varname>callPackage</varname> function is used in this scope to ensure that
|
||||
the entire dependency tree uses the same Qt 5 version. Import dependencies
|
||||
unqualified, i.e., <literal>qtbase</literal> not
|
||||
<literal>qt5.qtbase</literal>. <emphasis>Do not</emphasis> import a package
|
||||
set such as <literal>qt5</literal> or <literal>libsForQt5</literal>.
|
||||
</para>
|
||||
mkDerivation { <co xml:id='qt-default-nix-co-2' />
|
||||
pname = "myapp";
|
||||
version = "1.0";
|
||||
|
||||
<para>
|
||||
If a library does not support a particular version of Qt 5, it is best to
|
||||
mark it as broken by setting its <literal>meta.broken</literal> attribute. A
|
||||
package may be marked broken for certain versions by testing the
|
||||
<literal>qtbase.version</literal> attribute, which will always give the
|
||||
current Qt 5 version.
|
||||
</para>
|
||||
</section>
|
||||
buildInputs = [ qtbase ]; <co xml:id='qt-default-nix-co-3' />
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
|
||||
<section xml:id="ssec-qt-applications">
|
||||
<title>Packaging Applications for Nixpkgs</title>
|
||||
<calloutlist>
|
||||
<callout arearefs='qt-default-nix-co-1'>
|
||||
<para>
|
||||
Import <literal>mkDerivation</literal> and Qt (such as
|
||||
<literal>qtbase</literal> modules directly. <emphasis>Do not</emphasis>
|
||||
import Qt package sets; the Qt versions of dependencies may not be
|
||||
coherent, causing build and runtime failures.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs='qt-default-nix-co-2'>
|
||||
<para>
|
||||
Use <literal>mkDerivation</literal> instead of
|
||||
<literal>stdenv.mkDerivation</literal>. <literal>mkDerivation</literal>
|
||||
is a wrapper around <literal>stdenv.mkDerivation</literal> which
|
||||
applies some Qt-specific settings.
|
||||
This deriver accepts the same arguments as
|
||||
<literal>stdenv.mkDerivation</literal>; refer to
|
||||
<xref linkend='chap-stdenv' /> for details.
|
||||
</para>
|
||||
<para>
|
||||
To use another deriver instead of
|
||||
<literal>stdenv.mkDerivation</literal>, use
|
||||
<literal>mkDerivationWith</literal>:
|
||||
<programlisting>
|
||||
mkDerivationWith myDeriver {
|
||||
# ...
|
||||
}
|
||||
</programlisting>
|
||||
If you cannot use <literal>mkDerivationWith</literal>, please refer to
|
||||
<xref linkend='qt-runtime-dependencies' />.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs='qt-default-nix-co-3'>
|
||||
<para>
|
||||
<literal>mkDerivation</literal> accepts the same arguments as
|
||||
<literal>stdenv.mkDerivation</literal>, such as
|
||||
<literal>buildInputs</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
|
||||
<para>
|
||||
Call your application expression using
|
||||
<literal>libsForQt5.callPackage</literal> instead of
|
||||
<literal>callPackage</literal>. Import dependencies unqualified, i.e.,
|
||||
<literal>qtbase</literal> not <literal>qt5.qtbase</literal>. <emphasis>Do
|
||||
not</emphasis> import a package set such as <literal>qt5</literal> or
|
||||
<literal>libsForQt5</literal>.
|
||||
</para>
|
||||
<formalpara xml:id='qt-runtime-dependencies'>
|
||||
<title>Locating runtime dependencies</title>
|
||||
<para>
|
||||
Qt applications need to be wrapped to find runtime dependencies. If you
|
||||
cannot use <literal>mkDerivation</literal> or
|
||||
<literal>mkDerivationWith</literal> above, include
|
||||
<literal>wrapQtAppsHook</literal> in <literal>nativeBuildInputs</literal>:
|
||||
<programlisting>
|
||||
stdenv.mkDerivation {
|
||||
# ...
|
||||
|
||||
<para>
|
||||
Qt 5 maintains strict backward compatibility, so it is generally best to
|
||||
build an application package against the latest version using the
|
||||
<varname>libsForQt5</varname> library set. In case a package does not build
|
||||
with the latest Qt version, it is possible to pick a set pinned to a
|
||||
particular version, e.g. <varname>libsForQt55</varname> for Qt 5.5, if that
|
||||
is the latest version the package supports. If a package must be pinned to
|
||||
an older Qt version, be sure to file a bug upstream; because Qt is strictly
|
||||
backwards-compatible, any incompatibility is by definition a bug in the
|
||||
application.
|
||||
</para>
|
||||
nativeBuildInputs = [ wrapQtAppsHook ];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<para>
|
||||
Entries added to <literal>qtWrapperArgs</literal> are used to modify the
|
||||
wrappers created by <literal>wrapQtAppsHook</literal>. The entries are
|
||||
passed as arguments to <xref linkend='fun-wrapProgram' />.
|
||||
<programlisting>
|
||||
mkDerivation {
|
||||
# ...
|
||||
|
||||
qtWrapperArgs = [ ''--prefix PATH : /path/to/bin'' ];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Set <literal>dontWrapQtApps</literal> to stop applications from being
|
||||
wrapped automatically. It is required to wrap applications manually with
|
||||
<literal>wrapQtApp</literal>, using the syntax of
|
||||
<xref linkend='fun-wrapProgram' />:
|
||||
<programlisting>
|
||||
mkDerivation {
|
||||
# ...
|
||||
|
||||
dontWrapQtApps = true;
|
||||
preFixup = ''
|
||||
wrapQtApp "$out/bin/myapp" --prefix PATH : /path/to/bin
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Libraries are built with every available version of Qt. Use the <literal>meta.broken</literal>
|
||||
attribute to disable the package for unsupported Qt versions:
|
||||
<programlisting>
|
||||
mkDerivation {
|
||||
# ...
|
||||
|
||||
# Disable this library with Qt < 5.9.0
|
||||
meta.broken = builtins.compareVersions qtbase.version "5.9.0" < 0;
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<formalpara>
|
||||
<title>Adding a library to Nixpkgs</title>
|
||||
<para>
|
||||
Add a Qt library to <filename>all-packages.nix</filename> by adding it to the
|
||||
collection inside <literal>mkLibsForQt5</literal>. This ensures that the
|
||||
library is built with every available version of Qt as needed.
|
||||
<example xml:id='qt-library-all-packages-nix'>
|
||||
<title>Adding a Qt library to <filename>all-packages.nix</filename></title>
|
||||
<programlisting>
|
||||
{
|
||||
# ...
|
||||
|
||||
mkLibsForQt5 = self: with self; {
|
||||
# ...
|
||||
|
||||
mylib = callPackage ../path/to/mylib {};
|
||||
};
|
||||
|
||||
# ...
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<formalpara>
|
||||
<title>Adding an application to Nixpkgs</title>
|
||||
<para>
|
||||
Add a Qt application to <filename>all-packages.nix</filename> using
|
||||
<literal>libsForQt5.callPackage</literal> instead of the usual
|
||||
<literal>callPackage</literal>. The former ensures that all dependencies
|
||||
are built with the same version of Qt.
|
||||
<example xml:id='qt-application-all-packages-nix'>
|
||||
<title>Adding a Qt application to <filename>all-packages.nix</filename></title>
|
||||
<programlisting>
|
||||
{
|
||||
# ...
|
||||
|
||||
myapp = libsForQt5.callPackage ../path/to/myapp/ {};
|
||||
|
||||
# ...
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</formalpara>
|
||||
|
||||
<para>
|
||||
When testing applications in Nixpkgs, it is a common practice to build the
|
||||
package with <literal>nix-build</literal> and run it using the created
|
||||
symbolic link. This will not work with Qt applications, however, because
|
||||
they have many hard runtime requirements that can only be guaranteed if the
|
||||
package is actually installed. To test a Qt application, install it with
|
||||
<literal>nix-env</literal> or run it inside <literal>nix-shell</literal>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -21,7 +21,7 @@ At the moment we support three different methods for managing plugins:
|
|||
|
||||
Adding custom .vimrc lines can be done using the following code:
|
||||
|
||||
```
|
||||
```nix
|
||||
vim_configurable.customize {
|
||||
# `name` specifies the name of the executable and package
|
||||
name = "vim-with-plugins";
|
||||
|
@ -32,11 +32,11 @@ vim_configurable.customize {
|
|||
}
|
||||
```
|
||||
|
||||
This configuration is used when vim is invoked with the command specified as name, in this case `vim-with-plugins`.
|
||||
This configuration is used when Vim is invoked with the command specified as name, in this case `vim-with-plugins`.
|
||||
|
||||
For Neovim the `configure` argument can be overridden to achieve the same:
|
||||
|
||||
```
|
||||
```nix
|
||||
neovim.override {
|
||||
configure = {
|
||||
customRC = ''
|
||||
|
@ -46,10 +46,10 @@ neovim.override {
|
|||
}
|
||||
```
|
||||
|
||||
If you want to use `neovim-qt` as a graphical editor, you can configure it by overriding neovim in an overlay
|
||||
or passing it an overridden neovimn:
|
||||
If you want to use `neovim-qt` as a graphical editor, you can configure it by overriding Neovim in an overlay
|
||||
or passing it an overridden Neovimn:
|
||||
|
||||
```
|
||||
```nix
|
||||
neovim-qt.override {
|
||||
neovim = neovim.override {
|
||||
configure = {
|
||||
|
@ -63,16 +63,16 @@ neovim-qt.override {
|
|||
|
||||
## Managing plugins with Vim packages
|
||||
|
||||
To store you plugins in Vim packages (the native vim plugin manager, see `:help packages`) the following example can be used:
|
||||
To store you plugins in Vim packages (the native Vim plugin manager, see `:help packages`) the following example can be used:
|
||||
|
||||
```
|
||||
```nix
|
||||
vim_configurable.customize {
|
||||
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
|
||||
# loaded on launch
|
||||
start = [ youcompleteme fugitive ];
|
||||
# manually loadable by calling `:packadd $plugin-name`
|
||||
# however, if a vim plugin has a dependency that is not explicitly listed in
|
||||
# opt that dependency will always be added to start to avoid confusion.
|
||||
# however, if a Vim plugin has a dependency that is not explicitly listed in
|
||||
# opt that dependency will always be added to start to avoid confusion.
|
||||
opt = [ phpCompletion elm-vim ];
|
||||
# To automatically load a plugin when opening a filetype, add vimrc lines like:
|
||||
# autocmd FileType php :packadd phpCompletion
|
||||
|
@ -83,7 +83,7 @@ vim_configurable.customize {
|
|||
`myVimPackage` is an arbitrary name for the generated package. You can choose any name you like.
|
||||
For Neovim the syntax is:
|
||||
|
||||
```
|
||||
```nix
|
||||
neovim.override {
|
||||
configure = {
|
||||
customRC = ''
|
||||
|
@ -92,7 +92,7 @@ neovim.override {
|
|||
packages.myVimPackage = with pkgs.vimPlugins; {
|
||||
# see examples below how to use custom packages
|
||||
start = [ ];
|
||||
# If a vim plugin has a dependency that is not explicitly listed in
|
||||
# If a Vim plugin has a dependency that is not explicitly listed in
|
||||
# opt that dependency will always be added to start to avoid confusion.
|
||||
opt = [ ];
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ neovim.override {
|
|||
|
||||
The resulting package can be added to `packageOverrides` in `~/.nixpkgs/config.nix` to make it installable:
|
||||
|
||||
```
|
||||
```nix
|
||||
{
|
||||
packageOverrides = pkgs: with pkgs; {
|
||||
myVim = vim_configurable.customize {
|
||||
|
@ -126,7 +126,7 @@ After that you can install your special grafted `myVim` or `myNeovim` packages.
|
|||
To use [vim-plug](https://github.com/junegunn/vim-plug) to manage your Vim
|
||||
plugins the following example can be used:
|
||||
|
||||
```
|
||||
```nix
|
||||
vim_configurable.customize {
|
||||
vimrcConfig.packages.myVimPackage = with pkgs.vimPlugins; {
|
||||
# loaded on launch
|
||||
|
@ -137,7 +137,7 @@ vim_configurable.customize {
|
|||
|
||||
For Neovim the syntax is:
|
||||
|
||||
```
|
||||
```nix
|
||||
neovim.override {
|
||||
configure = {
|
||||
customRC = ''
|
||||
|
@ -161,89 +161,112 @@ assuming that "using latest version" is ok most of the time.
|
|||
|
||||
First create a vim-scripts file having one plugin name per line. Example:
|
||||
|
||||
"tlib"
|
||||
{'name': 'vim-addon-sql'}
|
||||
{'filetype_regex': '\%(vim)$', 'names': ['reload', 'vim-dev-plugin']}
|
||||
```
|
||||
"tlib"
|
||||
{'name': 'vim-addon-sql'}
|
||||
{'filetype_regex': '\%(vim)$', 'names': ['reload', 'vim-dev-plugin']}
|
||||
```
|
||||
|
||||
Such vim-scripts file can be read by VAM as well like this:
|
||||
|
||||
call vam#Scripts(expand('~/.vim-scripts'), {})
|
||||
```vim
|
||||
call vam#Scripts(expand('~/.vim-scripts'), {})
|
||||
```
|
||||
|
||||
Create a default.nix file:
|
||||
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
nixpkgs.vim_configurable.customize { name = "vim"; vimrcConfig.vam.pluginDictionaries = [ "vim-addon-vim2nix" ]; }
|
||||
```nix
|
||||
{ nixpkgs ? import <nixpkgs> {}, compiler ? "ghc7102" }:
|
||||
nixpkgs.vim_configurable.customize { name = "vim"; vimrcConfig.vam.pluginDictionaries = [ "vim-addon-vim2nix" ]; }
|
||||
```
|
||||
|
||||
Create a generate.vim file:
|
||||
|
||||
ActivateAddons vim-addon-vim2nix
|
||||
let vim_scripts = "vim-scripts"
|
||||
call nix#ExportPluginsForNix({
|
||||
\ 'path_to_nixpkgs': eval('{"'.substitute(substitute(substitute($NIX_PATH, ':', ',', 'g'), '=',':', 'g'), '\([:,]\)', '"\1"',"g").'"}')["nixpkgs"],
|
||||
\ 'cache_file': '/tmp/vim2nix-cache',
|
||||
\ 'try_catch': 0,
|
||||
\ 'plugin_dictionaries': ["vim-addon-manager"]+map(readfile(vim_scripts), 'eval(v:val)')
|
||||
\ })
|
||||
```vim
|
||||
ActivateAddons vim-addon-vim2nix
|
||||
let vim_scripts = "vim-scripts"
|
||||
call nix#ExportPluginsForNix({
|
||||
\ 'path_to_nixpkgs': eval('{"'.substitute(substitute(substitute($NIX_PATH, ':', ',', 'g'), '=',':', 'g'), '\([:,]\)', '"\1"',"g").'"}')["nixpkgs"],
|
||||
\ 'cache_file': '/tmp/vim2nix-cache',
|
||||
\ 'try_catch': 0,
|
||||
\ 'plugin_dictionaries': ["vim-addon-manager"]+map(readfile(vim_scripts), 'eval(v:val)')
|
||||
\ })
|
||||
```
|
||||
|
||||
Then run
|
||||
|
||||
nix-shell -p vimUtils.vim_with_vim2nix --command "vim -c 'source generate.vim'"
|
||||
```bash
|
||||
nix-shell -p vimUtils.vim_with_vim2nix --command "vim -c 'source generate.vim'"
|
||||
```
|
||||
|
||||
You should get a Vim buffer with the nix derivations (output1) and vam.pluginDictionaries (output2).
|
||||
You can add your vim to your system's configuration file like this and start it by "vim-my":
|
||||
You can add your Vim to your system's configuration file like this and start it by "vim-my":
|
||||
|
||||
my-vim =
|
||||
let plugins = let inherit (vimUtils) buildVimPluginFrom2Nix; in {
|
||||
copy paste output1 here
|
||||
}; in vim_configurable.customize {
|
||||
name = "vim-my";
|
||||
```
|
||||
my-vim =
|
||||
let plugins = let inherit (vimUtils) buildVimPluginFrom2Nix; in {
|
||||
copy paste output1 here
|
||||
}; in vim_configurable.customize {
|
||||
name = "vim-my";
|
||||
|
||||
vimrcConfig.vam.knownPlugins = plugins; # optional
|
||||
vimrcConfig.vam.pluginDictionaries = [
|
||||
copy paste output2 here
|
||||
];
|
||||
|
||||
# Pathogen would be
|
||||
# vimrcConfig.pathogen.knownPlugins = plugins; # plugins
|
||||
# vimrcConfig.pathogen.pluginNames = ["tlib"];
|
||||
};
|
||||
vimrcConfig.vam.knownPlugins = plugins; # optional
|
||||
vimrcConfig.vam.pluginDictionaries = [
|
||||
copy paste output2 here
|
||||
];
|
||||
|
||||
# Pathogen would be
|
||||
# vimrcConfig.pathogen.knownPlugins = plugins; # plugins
|
||||
# vimrcConfig.pathogen.pluginNames = ["tlib"];
|
||||
};
|
||||
```
|
||||
|
||||
Sample output1:
|
||||
|
||||
"reload" = buildVimPluginFrom2Nix { # created by nix#NixDerivation
|
||||
name = "reload";
|
||||
src = fetchgit {
|
||||
url = "git://github.com/xolox/vim-reload";
|
||||
rev = "0a601a668727f5b675cb1ddc19f6861f3f7ab9e1";
|
||||
sha256 = "0vb832l9yxj919f5hfg6qj6bn9ni57gnjd3bj7zpq7d4iv2s4wdh";
|
||||
};
|
||||
dependencies = ["nim-misc"];
|
||||
```
|
||||
"reload" = buildVimPluginFrom2Nix { # created by nix#NixDerivation
|
||||
name = "reload";
|
||||
src = fetchgit {
|
||||
url = "git://github.com/xolox/vim-reload";
|
||||
rev = "0a601a668727f5b675cb1ddc19f6861f3f7ab9e1";
|
||||
sha256 = "0vb832l9yxj919f5hfg6qj6bn9ni57gnjd3bj7zpq7d4iv2s4wdh";
|
||||
};
|
||||
dependencies = ["nim-misc"];
|
||||
|
||||
};
|
||||
[...]
|
||||
};
|
||||
[...]
|
||||
```
|
||||
|
||||
Sample output2:
|
||||
|
||||
[
|
||||
''vim-addon-manager''
|
||||
''tlib''
|
||||
{ "name" = ''vim-addon-sql''; }
|
||||
{ "filetype_regex" = ''\%(vim)$$''; "names" = [ ''reload'' ''vim-dev-plugin'' ]; }
|
||||
]
|
||||
|
||||
```nix
|
||||
[
|
||||
''vim-addon-manager''
|
||||
''tlib''
|
||||
{ "name" = ''vim-addon-sql''; }
|
||||
{ "filetype_regex" = ''\%(vim)$$''; "names" = [ ''reload'' ''vim-dev-plugin'' ]; }
|
||||
]
|
||||
```
|
||||
|
||||
## Adding new plugins to nixpkgs
|
||||
|
||||
In `pkgs/misc/vim-plugins/vim-plugin-names` we store the plugin names
|
||||
for all vim plugins we automatically generate plugins for.
|
||||
The format of this file `github username/github repository`:
|
||||
For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
After adding your plugin to this file run the `./update.py` in the same folder.
|
||||
This will updated a file called `generated.nix` and make your plugin accessible in the
|
||||
`vimPlugins` attribute set (`vimPlugins.nerdtree` in our example).
|
||||
If additional steps to the build process of the plugin are required, add an
|
||||
override to the `pkgs/misc/vim-plugins/default.nix` in the same directory.
|
||||
Nix expressions for Vim plugins are stored in [pkgs/misc/vim-plugins](/pkgs/misc/vim-plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`./update.py`](/pkgs/misc/vim-plugins/update.py). This creates a [generated.nix](/pkgs/misc/vim-plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](/pkgs/misc/vim-plugins/vim-plugin-names). Plugins are listed in alphabetical order in `vim-plugin-names` using the format `[github username]/[repository]`. For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
|
||||
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](/pkgs/misc/vim-plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
|
||||
|
||||
```
|
||||
deoplete-fish = super.deoplete-fish.overrideAttrs(old: {
|
||||
dependencies = with super; [ deoplete-nvim vim-fish ];
|
||||
});
|
||||
```
|
||||
|
||||
Sometimes plugins require an override that must be changed when the plugin is updated. This can cause issues when Vim plugins are auto-updated but the associated override isn't updated. For these plugins, the override should be written so that it specifies all information required to install the plugin, and running `./update.py` doesn't change the derivation for the plugin. Manually updating the override is required to update these types of plugins. An example of such a plugin is `LanguageClient-neovim`.
|
||||
|
||||
To add a new plugin:
|
||||
|
||||
1. run `./update.py` and create a commit named "vimPlugins: Update",
|
||||
2. add the new plugin to [vim-plugin-names](/pkgs/misc/vim-plugins/vim-plugin-names) and add overrides if required to [overrides.nix](/pkgs/misc/vim-plugins/overrides.nix),
|
||||
3. run `./update.py` again and create a commit named "vimPlugins.[name]: init at [version]" (where `name` and `version` can be found in [generated.nix](/pkgs/misc/vim-plugins/generated.nix)), and
|
||||
4. create a pull request.
|
||||
|
||||
## Important repositories
|
||||
|
||||
|
@ -252,4 +275,3 @@ override to the `pkgs/misc/vim-plugins/default.nix` in the same directory.
|
|||
|
||||
- [vim2nix](https://github.com/MarcWeber/vim-addon-vim2nix) which generates the
|
||||
.nix code
|
||||
|
||||
|
|
|
@ -409,11 +409,19 @@ overrides = self: super: rec {
|
|||
</section>
|
||||
|
||||
<section xml:id="sec-citrix">
|
||||
<title>Citrix Receiver</title>
|
||||
<title>Citrix Receiver & Citrix Workspace App</title>
|
||||
|
||||
<para>
|
||||
The <link xlink:href="https://www.citrix.com/products/receiver/">Citrix
|
||||
Receiver</link> is a remote desktop viewer which provides access to
|
||||
<note>
|
||||
<para>
|
||||
Please note that the <literal>citrix_receiver</literal> package has been deprecated since its
|
||||
development was <link xlink:href="https://docs.citrix.com/en-us/citrix-workspace-app.html">discontinued by upstream</link>
|
||||
and will be replaced by <link xlink:href="https://www.citrix.com/products/workspace-app/">the citrix workspace app</link>.
|
||||
</para>
|
||||
</note>
|
||||
<link xlink:href="https://www.citrix.com/products/receiver/">Citrix Receiver</link> and
|
||||
<link xlink:href="https://www.citrix.com/products/workspace-app/">Citrix Workspace App</link>
|
||||
are a remote desktop viewers which provide access to
|
||||
<link xlink:href="https://www.citrix.com/products/xenapp-xendesktop/">XenDesktop</link>
|
||||
installations.
|
||||
</para>
|
||||
|
@ -423,30 +431,35 @@ overrides = self: super: rec {
|
|||
|
||||
<para>
|
||||
The tarball archive needs to be downloaded manually as the license
|
||||
agreements of the vendor need to be accepted first. This is available at
|
||||
the
|
||||
<link xlink:href="https://www.citrix.com/downloads/citrix-receiver/">download
|
||||
page at citrix.com</link>. Then run <literal>nix-prefetch-url
|
||||
file://$PWD/linuxx64-$version.tar.gz</literal>. With the archive available
|
||||
agreements of the vendor for
|
||||
<link xlink:href="https://www.citrix.com/downloads/citrix-receiver/">Citrix Receiver</link>
|
||||
or <link xlink:href="https://www.citrix.de/downloads/workspace-app/linux/workspace-app-for-linux-latest.html">Citrix Workspace</link>
|
||||
need to be accepted first.
|
||||
Then run <command>nix-prefetch-url file://$PWD/linuxx64-$version.tar.gz</command>.
|
||||
With the archive available
|
||||
in the store the package can be built and installed with Nix.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis>Note: it's recommended to install <literal>Citrix
|
||||
Receiver</literal> using <literal>nix-env -i</literal> or globally to
|
||||
ensure that the <literal>.desktop</literal> files are installed properly
|
||||
into <literal>$XDG_CONFIG_DIRS</literal>. Otherwise it won't be possible to
|
||||
open <literal>.ica</literal> files automatically from the browser to start
|
||||
a Citrix connection.</emphasis>
|
||||
</para>
|
||||
<warning>
|
||||
<title>Caution with <command>nix-shell</command> installs</title>
|
||||
<para>
|
||||
It's recommended to install <literal>Citrix Receiver</literal>
|
||||
and/or <literal>Citrix Workspace</literal> using
|
||||
<literal>nix-env -i</literal> or globally to
|
||||
ensure that the <literal>.desktop</literal> files are installed properly
|
||||
into <literal>$XDG_CONFIG_DIRS</literal>. Otherwise it won't be possible to
|
||||
open <literal>.ica</literal> files automatically from the browser to start
|
||||
a Citrix connection.
|
||||
</para>
|
||||
</warning>
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-citrix-custom-certs">
|
||||
<title>Custom certificates</title>
|
||||
|
||||
<para>
|
||||
The <literal>Citrix Receiver</literal> in <literal>nixpkgs</literal> trusts
|
||||
several certificates
|
||||
The <literal>Citrix Receiver</literal> and <literal>Citrix Workspace App</literal>
|
||||
in <literal>nixpkgs</literal> trust several certificates
|
||||
<link xlink:href="https://curl.haxx.se/docs/caextract.html">from the
|
||||
Mozilla database</link> by default. However several companies using Citrix
|
||||
might require their own corporate certificate. On distros with imperative
|
||||
|
@ -459,7 +472,7 @@ overrides = self: super: rec {
|
|||
<programlisting>
|
||||
<![CDATA[with import <nixpkgs> { config.allowUnfree = true; };
|
||||
let extraCerts = [ ./custom-cert-1.pem ./custom-cert-2.pem /* ... */ ]; in
|
||||
citrix_receiver.override {
|
||||
citrix_workspace.override { # the same applies for `citrix_receiver` if used.
|
||||
inherit extraCerts;
|
||||
}]]>
|
||||
</programlisting>
|
||||
|
|
|
@ -786,7 +786,7 @@ passthru.updateScript = [ ../../update.sh pname "--requested-release=unstable" ]
|
|||
set, the default value is used, which is <literal>$prePhases
|
||||
unpackPhase patchPhase $preConfigurePhases configurePhase
|
||||
$preBuildPhases buildPhase checkPhase $preInstallPhases installPhase
|
||||
fixupPhase $preDistPhases distPhase $postPhases</literal>.
|
||||
fixupPhase installCheckPhase $preDistPhases distPhase $postPhases</literal>.
|
||||
</para>
|
||||
<para>
|
||||
Usually, if you just want to add a few phases, it’s more convenient
|
||||
|
|
|
@ -53,12 +53,16 @@ rec {
|
|||
# Filter sources by a list of regular expressions.
|
||||
#
|
||||
# E.g. `src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]`
|
||||
sourceByRegex = src: regexes: cleanSourceWith {
|
||||
filter = (path: type:
|
||||
let relPath = lib.removePrefix (toString src + "/") (toString path);
|
||||
in lib.any (re: builtins.match re relPath != null) regexes);
|
||||
inherit src;
|
||||
};
|
||||
sourceByRegex = src: regexes:
|
||||
let
|
||||
isFiltered = src ? _isLibCleanSourceWith;
|
||||
origSrc = if isFiltered then src.origSrc else src;
|
||||
in lib.cleanSourceWith {
|
||||
filter = (path: type:
|
||||
let relPath = lib.removePrefix (toString origSrc + "/") (toString path);
|
||||
in lib.any (re: builtins.match re relPath != null) regexes);
|
||||
inherit src;
|
||||
};
|
||||
|
||||
# Get all files ending with the specified suffices from the given
|
||||
# directory or its descendants. E.g. `sourceFilesBySuffices ./dir
|
||||
|
|
|
@ -26,7 +26,7 @@ let
|
|||
|
||||
"riscv32-linux" "riscv64-linux"
|
||||
|
||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none"
|
||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none"
|
||||
];
|
||||
|
||||
allParsed = map parse.mkSystemFromString all;
|
||||
|
|
|
@ -97,6 +97,18 @@ rec {
|
|||
riscv64 = riscv "64";
|
||||
riscv32 = riscv "32";
|
||||
|
||||
riscv64-embedded = {
|
||||
config = "riscv64-none-elf";
|
||||
libc = "newlib";
|
||||
platform = platforms.riscv-multiplatform "64";
|
||||
};
|
||||
|
||||
riscv32-embedded = {
|
||||
config = "riscv32-none-elf";
|
||||
libc = "newlib";
|
||||
platform = platforms.riscv-multiplatform "32";
|
||||
};
|
||||
|
||||
msp430 = {
|
||||
config = "msp430-elf";
|
||||
libc = "newlib";
|
||||
|
|
|
@ -111,7 +111,7 @@ rec {
|
|||
name = "int";
|
||||
description = "signed integer";
|
||||
check = isInt;
|
||||
merge = mergeOneOption;
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
# Specialized subdomains of int
|
||||
|
@ -176,14 +176,14 @@ rec {
|
|||
name = "float";
|
||||
description = "floating point number";
|
||||
check = isFloat;
|
||||
merge = mergeOneOption;
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
str = mkOptionType {
|
||||
name = "str";
|
||||
description = "string";
|
||||
check = isString;
|
||||
merge = mergeOneOption;
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
strMatching = pattern: mkOptionType {
|
||||
|
@ -243,7 +243,7 @@ rec {
|
|||
name = "path";
|
||||
# Hacky: there is no ‘isPath’ primop.
|
||||
check = x: builtins.substring 0 1 (toString x) == "/";
|
||||
merge = mergeOneOption;
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
# drop this in the future:
|
||||
|
@ -415,7 +415,7 @@ rec {
|
|||
name = "enum";
|
||||
description = "one of ${concatMapStringsSep ", " show values}";
|
||||
check = flip elem values;
|
||||
merge = mergeOneOption;
|
||||
merge = mergeEqualOption;
|
||||
functor = (defaultFunctor name) // { payload = values; binOp = a: b: unique (a ++ b); };
|
||||
};
|
||||
|
||||
|
|
|
@ -250,6 +250,11 @@
|
|||
github = "akru";
|
||||
name = "Alexander Krupenkin ";
|
||||
};
|
||||
alexarice = {
|
||||
email = "alexrice999@hotmail.co.uk";
|
||||
github = "alexarice";
|
||||
name = "Alex Rice";
|
||||
};
|
||||
alexchapman = {
|
||||
email = "alex@farfromthere.net";
|
||||
github = "AJChapman";
|
||||
|
@ -328,6 +333,11 @@
|
|||
github = "andersk";
|
||||
name = "Anders Kaseorg";
|
||||
};
|
||||
anderslundstedt = {
|
||||
email = "git@anderslundstedt.se";
|
||||
github = "anderslundstedt";
|
||||
name = "Anders Lundstedt";
|
||||
};
|
||||
AndersonTorres = {
|
||||
email = "torres.anderson.85@protonmail.com";
|
||||
github = "AndersonTorres";
|
||||
|
@ -383,6 +393,11 @@
|
|||
github = "aneeshusa";
|
||||
name = "Aneesh Agrawal";
|
||||
};
|
||||
angristan = {
|
||||
email = "angristan@pm.me";
|
||||
github = "angristan";
|
||||
name = "Stanislas Lange";
|
||||
};
|
||||
ankhers = {
|
||||
email = "justin.k.wood@gmail.com";
|
||||
github = "ankhers";
|
||||
|
@ -537,6 +552,15 @@
|
|||
github = "averelld";
|
||||
name = "averelld";
|
||||
};
|
||||
avitex = {
|
||||
email = "theavitex@gmail.com";
|
||||
github = "avitex";
|
||||
name = "avitex";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x8B366C443CABE942";
|
||||
fingerprint = "271E 136C 178E 06FA EA4E B854 8B36 6C44 3CAB E942";
|
||||
}];
|
||||
};
|
||||
avnik = {
|
||||
email = "avn@avnik.info";
|
||||
github = "avnik";
|
||||
|
@ -1134,6 +1158,19 @@
|
|||
github = "cwoac";
|
||||
name = "Oliver Matthews";
|
||||
};
|
||||
cypherpunk2140 = {
|
||||
email = "stefan.mihaila@pm.me";
|
||||
github = "cypherpunk2140";
|
||||
name = "Ștefan D. Mihăilă";
|
||||
keys = [
|
||||
{ longkeyid = "rsa4096/6E68A39BF16A3ECB";
|
||||
fingerprint = "CBC9 C7CC 51F0 4A61 3901 C723 6E68 A39B F16A 3ECB";
|
||||
}
|
||||
{ longkeyid = "rsa4096/6220AD7846220A52";
|
||||
fingerprint = "7EAB 1447 5BBA 7DDE 7092 7276 6220 AD78 4622 0A52";
|
||||
}
|
||||
];
|
||||
};
|
||||
dalance = {
|
||||
email = "dalance@gmail.com";
|
||||
github = "dalance";
|
||||
|
@ -1223,6 +1260,11 @@
|
|||
github = "deepfire";
|
||||
name = "Kosyrev Serge";
|
||||
};
|
||||
delan = {
|
||||
name = "Delan Azabani";
|
||||
email = "delan@azabani.com";
|
||||
github = "delan";
|
||||
};
|
||||
delroth = {
|
||||
email = "delroth@gmail.com";
|
||||
github = "delroth";
|
||||
|
@ -2100,6 +2142,11 @@
|
|||
github = "henrytill";
|
||||
name = "Henry Till";
|
||||
};
|
||||
herberteuler = {
|
||||
email = "herberteuler@gmail.com";
|
||||
github = "herberteuler";
|
||||
name = "Guanpeng Xu";
|
||||
};
|
||||
hhm = {
|
||||
email = "heehooman+nixpkgs@gmail.com";
|
||||
github = "hhm0";
|
||||
|
@ -2114,6 +2161,11 @@
|
|||
github = "hlolli";
|
||||
name = "Hlodver Sigurdsson";
|
||||
};
|
||||
hugoreeves = {
|
||||
email = "hugolreeves@gmail.com";
|
||||
github = "hugoreeves";
|
||||
name = "Hugo Reeves";
|
||||
};
|
||||
hodapp = {
|
||||
email = "hodapp87@gmail.com";
|
||||
github = "Hodapp87";
|
||||
|
@ -2228,6 +2280,15 @@
|
|||
email = "tkatchev@gmail.com";
|
||||
name = "Ivan Tkatchev";
|
||||
};
|
||||
ivanbrennan = {
|
||||
email = "ivan.brennan@gmail.com";
|
||||
github = "ivanbrennan";
|
||||
name = "Ivan Brennan";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x79C3C47DC652EA54";
|
||||
fingerprint = "7311 2700 AB4F 4CDF C68C F6A5 79C3 C47D C652 EA54";
|
||||
}];
|
||||
};
|
||||
ivegotasthma = {
|
||||
email = "ivegotasthma@protonmail.com";
|
||||
github = "ivegotasthma";
|
||||
|
@ -2257,6 +2318,11 @@
|
|||
github = "j-keck";
|
||||
name = "Jürgen Keck";
|
||||
};
|
||||
j03 = {
|
||||
email = "github@johannesloetzsch.de";
|
||||
github = "johannesloetzsch";
|
||||
name = "Johannes Lötzsch";
|
||||
};
|
||||
jagajaga = {
|
||||
email = "ars.seroka@gmail.com";
|
||||
github = "jagajaga";
|
||||
|
@ -2445,6 +2511,11 @@
|
|||
email = "me@joelt.io";
|
||||
name = "Joel Taylor";
|
||||
};
|
||||
joepie91 = {
|
||||
email = "admin@cryto.net";
|
||||
name = "Sven Slootweg";
|
||||
github = "joepie91";
|
||||
};
|
||||
johanot = {
|
||||
email = "write@ownrisk.dk";
|
||||
github = "johanot";
|
||||
|
@ -2540,6 +2611,11 @@
|
|||
github = "jraygauthier";
|
||||
name = "Raymond Gauthier";
|
||||
};
|
||||
jtobin = {
|
||||
email = "jared@jtobin.io";
|
||||
github = "jtobin";
|
||||
name = "Jared Tobin";
|
||||
};
|
||||
jtojnar = {
|
||||
email = "jtojnar@gmail.com";
|
||||
github = "jtojnar";
|
||||
|
@ -2908,6 +2984,15 @@
|
|||
github = "listx";
|
||||
name = "Linus Arver";
|
||||
};
|
||||
livnev = {
|
||||
email = "lev@liv.nev.org.uk";
|
||||
github = "livnev";
|
||||
name = "Lev Livnev";
|
||||
keys = [{
|
||||
longkeyid = "rsa2048/0x68FF81E6A7850F49";
|
||||
fingerprint = "74F5 E5CC 19D3 B5CB 608F 6124 68FF 81E6 A785 0F49";
|
||||
}];
|
||||
};
|
||||
luis = {
|
||||
email = "luis.nixos@gmail.com";
|
||||
github = "Luis-Hebendanz";
|
||||
|
@ -3253,6 +3338,11 @@
|
|||
email = "softs@metabarcoding.org";
|
||||
name = "Celine Mercier";
|
||||
};
|
||||
metadark = {
|
||||
email = "kira.bruneau@gmail.com";
|
||||
name = "Kira Bruneau";
|
||||
github = "metadark";
|
||||
};
|
||||
mfossen = {
|
||||
email = "msfossen@gmail.com";
|
||||
github = "mfossen";
|
||||
|
@ -4123,10 +4213,19 @@
|
|||
github = "proglodyte";
|
||||
name = "Proglodyte";
|
||||
};
|
||||
protoben = {
|
||||
email = "protob3n@gmail.com";
|
||||
github = "protoben";
|
||||
name = "Ben Hamlin";
|
||||
};
|
||||
prusnak = {
|
||||
email = "stick@gk2.sk";
|
||||
email = "pavol@rusnak.io";
|
||||
github = "prusnak";
|
||||
name = "Pavol Rusnak";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x91F3B339B9A02A3D";
|
||||
fingerprint = "86E6 792F C27B FD47 8860 C110 91F3 B339 B9A0 2A3D";
|
||||
}];
|
||||
};
|
||||
pshendry = {
|
||||
email = "paul@pshendry.com";
|
||||
|
@ -4528,11 +4627,6 @@
|
|||
github = "rzetterberg";
|
||||
name = "Richard Zetterberg";
|
||||
};
|
||||
s1lvester = {
|
||||
email = "s1lvester@bockhacker.me";
|
||||
github = "s1lvester";
|
||||
name = "Markus Silvester";
|
||||
};
|
||||
samdroid-apps = {
|
||||
email = "sam@sam.today";
|
||||
github = "samdroid-apps";
|
||||
|
@ -4626,6 +4720,11 @@
|
|||
github = "scriptkiddi";
|
||||
name = "Fritz Otlinghaus";
|
||||
};
|
||||
scubed2 = {
|
||||
email = "scubed2@gmail.com";
|
||||
github = "scubed2";
|
||||
name = "Sterling Stein";
|
||||
};
|
||||
sdll = {
|
||||
email = "sasha.delly@gmail.com";
|
||||
github = "sdll";
|
||||
|
@ -4916,6 +5015,15 @@
|
|||
github = "sternenseemann";
|
||||
name = "Lukas Epple";
|
||||
};
|
||||
steshaw = {
|
||||
name = "Steven Shaw";
|
||||
email = "steven@steshaw.org";
|
||||
github = "steshaw";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x1D9A17DFD23DCB91";
|
||||
fingerprint = "0AFE 77F7 474D 1596 EE55 7A29 1D9A 17DF D23D CB91";
|
||||
}];
|
||||
};
|
||||
stesie = {
|
||||
email = "stesie@brokenpipe.de";
|
||||
github = "stesie";
|
||||
|
@ -5348,6 +5456,15 @@
|
|||
github = "twey";
|
||||
name = "James ‘Twey’ Kay";
|
||||
};
|
||||
twhitehead = {
|
||||
name = "Tyson Whitehead";
|
||||
email = "twhitehead@gmail.com";
|
||||
github = "twhitehead";
|
||||
keys = [{
|
||||
longkeyid = "rsa2048/0x594258F0389D2802";
|
||||
fingerprint = "E631 8869 586F 99B4 F6E6 D785 5942 58F0 389D 2802";
|
||||
}];
|
||||
};
|
||||
typetetris = {
|
||||
email = "ericwolf42@mail.com";
|
||||
github = "typetetris";
|
||||
|
@ -5536,6 +5653,11 @@
|
|||
github = "vskilet";
|
||||
name = "Victor SENE";
|
||||
};
|
||||
vyorkin = {
|
||||
email = "vasiliy.yorkin@gmail.com";
|
||||
github = "vyorkin";
|
||||
name = "Vasiliy Yorkin";
|
||||
};
|
||||
vyp = {
|
||||
email = "elisp.vim@gmail.com";
|
||||
github = "vyp";
|
||||
|
@ -5749,9 +5871,9 @@
|
|||
name = "Christian Zagrodnick";
|
||||
};
|
||||
zalakain = {
|
||||
email = "contact@unaizalakain.info";
|
||||
email = "ping@umazalakain.info";
|
||||
github = "umazalakain";
|
||||
name = "Unai Zalakain";
|
||||
name = "Uma Zalakain";
|
||||
};
|
||||
zaninime = {
|
||||
email = "francesco@zanini.me";
|
||||
|
@ -5822,4 +5944,14 @@
|
|||
github = "turboMaCk";
|
||||
name = "Marek Fajkus";
|
||||
};
|
||||
melling = {
|
||||
email = "mattmelling@fastmail.com";
|
||||
github = "mattmelling";
|
||||
name = "Matt Melling";
|
||||
};
|
||||
wd15 = {
|
||||
email = "daniel.wheeler2@gmail.com";
|
||||
github = "wd15";
|
||||
name = "Daniel Wheeler";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ in {
|
|||
|
||||
# forward all Matrix API calls to the synapse Matrix homeserver
|
||||
locations."/_matrix" = {
|
||||
proxyPass = "http://[::1]:8008/_matrix";
|
||||
proxyPass = "http://[::1]:8008"; # without a trailing /
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -125,10 +125,12 @@
|
|||
You will need to reboot after enabling this driver to prevent a clash with
|
||||
other kernel modules.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Note: for recent AMD GPUs you most likely want to keep either the defaults
|
||||
For recent AMD GPUs you most likely want to keep either the defaults
|
||||
or <literal>"amdgpu"</literal> (both free).
|
||||
</para>
|
||||
</note>
|
||||
</simplesect>
|
||||
<simplesect xml:id="sec-x11-touchpads">
|
||||
<title>Touchpads</title>
|
||||
|
@ -157,4 +159,134 @@
|
|||
versions.
|
||||
</para>
|
||||
</simplesect>
|
||||
<simplesect xml:id="custom-xkb-layouts">
|
||||
<title>Custom XKB layouts</title>
|
||||
<para>
|
||||
It is possible to install custom
|
||||
<link xlink:href="https://en.wikipedia.org/wiki/X_keyboard_extension">
|
||||
XKB
|
||||
</link>
|
||||
keyboard layouts using the option
|
||||
<option>
|
||||
<link linkend="opt-services.xserver.extraLayouts">
|
||||
services.xserver.extraLayouts
|
||||
</link>
|
||||
</option>.
|
||||
As a first example, we are going to create a layout based on the basic US
|
||||
layout, with an additional layer to type some greek symbols by pressing the
|
||||
right-alt key.
|
||||
</para>
|
||||
<para>
|
||||
To do this we are going to create a <literal>us-greek</literal> file
|
||||
with a <literal>xkb_symbols</literal> section.
|
||||
</para>
|
||||
<programlisting>
|
||||
xkb_symbols "us-greek"
|
||||
{
|
||||
include "us(basic)" // includes the base US keys
|
||||
include "level3(ralt_switch)" // configures right alt as a third level switch
|
||||
|
||||
key <LatA> { [ a, A, Greek_alpha ] };
|
||||
key <LatB> { [ b, B, Greek_beta ] };
|
||||
key <LatG> { [ g, G, Greek_gamma ] };
|
||||
key <LatD> { [ d, D, Greek_delta ] };
|
||||
key <LatZ> { [ z, Z, Greek_zeta ] };
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
To install the layout, the filepath, a description and the list of
|
||||
languages must be given:
|
||||
</para>
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.xserver.extraLayouts"/>.us-greek = {
|
||||
description = "US layout with alt-gr greek";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /path/to/us-greek;
|
||||
}
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
The name should match the one given to the
|
||||
<literal>xkb_symbols</literal> block.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
The layout should now be installed and ready to use: try it by
|
||||
running <literal>setxkbmap us-greek</literal> and type
|
||||
<literal><alt>+a</literal>. To change the default the usual
|
||||
<option>
|
||||
<link linkend="opt-services.xserver.layout">
|
||||
services.xserver.layout
|
||||
</link>
|
||||
</option>
|
||||
option can still be used.
|
||||
</para>
|
||||
<para>
|
||||
A layout can have several other components besides
|
||||
<literal>xkb_symbols</literal>, for example we will define new
|
||||
keycodes for some multimedia key and bind these to some symbol.
|
||||
</para>
|
||||
<para>
|
||||
Use the <emphasis>xev</emphasis> utility from
|
||||
<literal>pkgs.xorg.xev</literal> to find the codes of the keys of
|
||||
interest, then create a <literal>media-key</literal> file to hold
|
||||
the keycodes definitions
|
||||
</para>
|
||||
<programlisting>
|
||||
xkb_keycodes "media"
|
||||
{
|
||||
<volUp> = 123;
|
||||
<volDown> = 456;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Now use the newly define keycodes in <literal>media-sym</literal>:
|
||||
</para>
|
||||
<programlisting>
|
||||
xkb_symbols "media"
|
||||
{
|
||||
key.type = "ONE_LEVEL";
|
||||
key <volUp> { [ XF86AudioLowerVolume ] };
|
||||
key <volDown> { [ XF86AudioRaiseVolume ] };
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
As before, to install the layout do
|
||||
</para>
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.xserver.extraLayouts"/>.media = {
|
||||
description = "Multimedia keys remapping";
|
||||
languages = [ "eng" ];
|
||||
symbolsFile = /path/to/media-key;
|
||||
keycodesFile = /path/to/media-sym;
|
||||
};
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
The function <literal>pkgs.writeText <filename> <content>
|
||||
</literal> can be useful if you prefer to keep the layout definitions
|
||||
inside the NixOS configuration.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
Unfortunately, the Xorg server does not (currently) support setting a
|
||||
keymap directly but relies instead on XKB rules to select the matching
|
||||
components (keycodes, types, ...) of a layout. This means that components
|
||||
other than symbols won't be loaded by default. As a workaround, you
|
||||
can set the keymap using <literal>setxkbmap</literal> at the start of the
|
||||
session with:
|
||||
</para>
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.xserver.displayManager.sessionCommands"/> = "setxkbmap -keycodes media";
|
||||
</programlisting>
|
||||
<para>
|
||||
To learn how to write layouts take a look at the XKB
|
||||
<link xlink:href="https://www.x.org/releases/current/doc/xorg-docs/input/XKB-Enhancing.html#Defining_New_Layouts">
|
||||
documentation
|
||||
</link>. More example layouts can also be found
|
||||
<link xlink:href="https://wiki.archlinux.org/index.php/X_KeyBoard_extension#Basic_examples">
|
||||
here
|
||||
</link>.
|
||||
</para>
|
||||
</simplesect>
|
||||
</chapter>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<author><personname><firstname>Eelco</firstname><surname>Dolstra</surname></personname>
|
||||
<contrib>Author</contrib>
|
||||
</author>
|
||||
<copyright><year>2007-2018</year><holder>Eelco Dolstra</holder>
|
||||
<copyright><year>2007-2019</year><holder>Eelco Dolstra</holder>
|
||||
</copyright>
|
||||
</info>
|
||||
<xi:include href="man-configuration.xml" />
|
||||
|
|
|
@ -122,6 +122,19 @@
|
|||
</link>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
IPv6 Privacy Extensions are now enabled by default for undeclared
|
||||
interfaces. The previous behaviour was quite misleading — even though
|
||||
the default value for
|
||||
<option>networking.interfaces.*.preferTempAddress</option> was
|
||||
<literal>true</literal>, undeclared interfaces would not prefer temporary
|
||||
addresses. Now, interfaces not mentioned in the config will prefer
|
||||
temporary addresses. EUI64 addresses can still be set as preferred by
|
||||
explicitly setting the option to <literal>false</literal> for the
|
||||
interface in question.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Since Bittorrent Sync was superseded by Resilio Sync in 2016, the
|
||||
|
@ -136,10 +149,22 @@
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Several of the apache subservices have been replaced with full NixOS
|
||||
modules including LimeSurvey, WordPress, and Zabbix.
|
||||
These modules can be enabled using the <option>services.limesurvey.enable</option>,
|
||||
<option>services.wordpress.enable</option>, and <option>services.zabbixWeb.enable</option> options.
|
||||
The httpd service no longer attempts to start the postgresql service. If you have come to depend
|
||||
on this behaviour then you can preserve the behavior with the following configuration:
|
||||
<literal>systemd.services.httpd.after = [ "postgresql.service" ];</literal>
|
||||
</para>
|
||||
<para>
|
||||
The option <option>services.httpd.extraSubservices</option> has been
|
||||
marked as deprecated. You may still use this feature, but it will be
|
||||
removed in a future release of NixOS. You are encouraged to convert any
|
||||
httpd subservices you may have written to a full NixOS module.
|
||||
</para>
|
||||
<para>
|
||||
Most of the httpd subservices packaged with NixOS have been replaced with
|
||||
full NixOS modules including LimeSurvey, WordPress, and Zabbix. These
|
||||
modules can be enabled using the <option>services.limesurvey.enable</option>,
|
||||
<option>services.mediawiki.enable</option>, <option>services.wordpress.enable</option>,
|
||||
and <option>services.zabbixWeb.enable</option> options.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -182,6 +207,25 @@
|
|||
<xref linkend="opt-programs.zsh.loginShellInit" /> and <xref linkend="opt-programs.zsh.promptInit" /> may break if it relies on those options being set.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>prometheus-nginx-exporter</literal> package now uses the offical exporter provided by NGINX Inc.
|
||||
Its metrics are differently structured and are incompatible to the old ones. For information about the metrics,
|
||||
have a look at the <link xlink:href="https://github.com/nginxinc/nginx-prometheus-exporter">official repo</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Nodejs 8 is scheduled EOL under the lifetime of 19.09 and has been dropped.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
By default, prometheus exporters are now run with <literal>DynamicUser</literal> enabled.
|
||||
Exporters that need a real user, now run under a seperate user and group which follow the pattern <literal><exporter-name>-exporter</literal>, instead of the previous default <literal>nobody</literal> and <literal>nogroup</literal>.
|
||||
Only some exporters are affected by the latter, namely the exporters <literal>dovecot</literal>, <literal>node</literal>, <literal>postfix</literal> and <literal>varnish</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
@ -329,6 +373,20 @@
|
|||
from nixpkgs due to lack of maintainer.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>tomcat-connector</literal> <literal>httpd.extraSubservice</literal> has been removed from nixpkgs.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
It's now possible to change configuration in
|
||||
<link linkend="opt-services.nextcloud.enable">services.nextcloud</link> after the initial deploy
|
||||
since all config parameters are persisted in an additional config file generated by the module.
|
||||
Previously core configuration like database parameters were set using their imperative
|
||||
installer after creating <literal>/var/lib/nextcloud</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -31,9 +31,17 @@ sub new {
|
|||
|
||||
if (!$startCommand) {
|
||||
# !!! merge with qemu-vm.nix.
|
||||
my $netBackend = "-netdev user,id=net0";
|
||||
my $netFrontend = "-device virtio-net-pci,netdev=net0";
|
||||
|
||||
$netBackend .= "," . $args->{netBackendArgs}
|
||||
if defined $args->{netBackendArgs};
|
||||
|
||||
$netFrontend .= "," . $args->{netFrontendArgs}
|
||||
if defined $args->{netFrontendArgs};
|
||||
|
||||
$startCommand =
|
||||
"qemu-kvm -m 384 " .
|
||||
"-net nic,model=virtio \$QEMU_OPTS ";
|
||||
"qemu-kvm -m 384 $netBackend $netFrontend \$QEMU_OPTS ";
|
||||
|
||||
if (defined $args->{hda}) {
|
||||
if ($args->{hdaInterface} eq "scsi") {
|
||||
|
|
|
@ -7,16 +7,6 @@ with lib;
|
|||
let
|
||||
|
||||
cfg = config.networking;
|
||||
dnsmasqResolve = config.services.dnsmasq.enable &&
|
||||
config.services.dnsmasq.resolveLocalQueries;
|
||||
hasLocalResolver = config.services.bind.enable ||
|
||||
config.services.unbound.enable ||
|
||||
dnsmasqResolve;
|
||||
|
||||
resolvconfOptions = cfg.resolvconfOptions
|
||||
++ optional cfg.dnsSingleRequest "single-request"
|
||||
++ optional cfg.dnsExtensionMechanism "edns0";
|
||||
|
||||
|
||||
localhostMapped4 = cfg.hosts ? "127.0.0.1" && elem "localhost" cfg.hosts."127.0.0.1";
|
||||
localhostMapped6 = cfg.hosts ? "::1" && elem "localhost" cfg.hosts."::1";
|
||||
|
@ -64,48 +54,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
networking.dnsSingleRequest = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
|
||||
address queries at the same time, from the same port. Sometimes upstream
|
||||
routers will systemically drop the ipv4 queries. The symptom of this problem is
|
||||
that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
|
||||
workaround for this is to specify the option 'single-request' in
|
||||
/etc/resolv.conf. This option enables that.
|
||||
'';
|
||||
};
|
||||
|
||||
networking.dnsExtensionMechanism = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable the <code>edns0</code> option in <filename>resolv.conf</filename>. With
|
||||
that option set, <code>glibc</code> supports use of the extension mechanisms for
|
||||
DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
|
||||
which does not work without it.
|
||||
'';
|
||||
};
|
||||
|
||||
networking.extraResolvconfConf = lib.mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "libc=NO";
|
||||
description = ''
|
||||
Extra configuration to append to <filename>resolvconf.conf</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
networking.resolvconfOptions = lib.mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "ndots:1" "rotate" ];
|
||||
description = ''
|
||||
Set the options in <filename>/etc/resolv.conf</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
networking.timeServers = mkOption {
|
||||
default = [
|
||||
"0.nixos.pool.ntp.org"
|
||||
|
@ -240,35 +188,6 @@ in
|
|||
# /etc/host.conf: resolver configuration file
|
||||
"host.conf".text = cfg.hostConf;
|
||||
|
||||
# /etc/resolvconf.conf: Configuration for openresolv.
|
||||
"resolvconf.conf".text =
|
||||
''
|
||||
# This is the default, but we must set it here to prevent
|
||||
# a collision with an apparently unrelated environment
|
||||
# variable with the same name exported by dhcpcd.
|
||||
interface_order='lo lo[0-9]*'
|
||||
'' + optionalString config.services.nscd.enable ''
|
||||
# Invalidate the nscd cache whenever resolv.conf is
|
||||
# regenerated.
|
||||
libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
|
||||
'' + optionalString (length resolvconfOptions > 0) ''
|
||||
# Options as described in resolv.conf(5)
|
||||
resolv_conf_options='${concatStringsSep " " resolvconfOptions}'
|
||||
'' + optionalString hasLocalResolver ''
|
||||
# This hosts runs a full-blown DNS resolver.
|
||||
name_servers='127.0.0.1'
|
||||
'' + optionalString dnsmasqResolve ''
|
||||
dnsmasq_conf=/etc/dnsmasq-conf.conf
|
||||
dnsmasq_resolv=/etc/dnsmasq-resolv.conf
|
||||
'' + cfg.extraResolvconfConf + ''
|
||||
'';
|
||||
|
||||
} // optionalAttrs config.services.resolved.enable {
|
||||
# symlink the dynamic stub resolver of resolv.conf as recommended by upstream:
|
||||
# https://www.freedesktop.org/software/systemd/man/systemd-resolved.html#/etc/resolv.conf
|
||||
"resolv.conf".source = "/run/systemd/resolve/stub-resolv.conf";
|
||||
} // optionalAttrs (config.services.resolved.enable && dnsmasqResolve) {
|
||||
"dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf";
|
||||
} // optionalAttrs (pkgs.stdenv.hostPlatform.libc == "glibc") {
|
||||
# /etc/rpc: RPC program numbers.
|
||||
"rpc".source = pkgs.glibc.out + "/etc/rpc";
|
||||
|
@ -295,29 +214,6 @@ in
|
|||
# Install the proxy environment variables
|
||||
environment.sessionVariables = cfg.proxy.envVars;
|
||||
|
||||
# This is needed when /etc/resolv.conf is being overriden by networkd
|
||||
# and other configurations. If the file is destroyed by an environment
|
||||
# activation then it must be rebuilt so that applications which interface
|
||||
# with /etc/resolv.conf directly don't break.
|
||||
system.activationScripts.resolvconf = stringAfter [ "etc" "specialfs" "var" ]
|
||||
''
|
||||
# Systemd resolved controls its own resolv.conf
|
||||
rm -f /run/resolvconf/interfaces/systemd
|
||||
${optionalString config.services.resolved.enable ''
|
||||
rm -rf /run/resolvconf/interfaces
|
||||
mkdir -p /run/resolvconf/interfaces
|
||||
ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd
|
||||
''}
|
||||
|
||||
# Make sure resolv.conf is up to date if not managed manually, by systemd or
|
||||
# by NetworkManager
|
||||
${optionalString (!config.environment.etc?"resolv.conf" &&
|
||||
(cfg.networkmanager.enable ->
|
||||
cfg.networkmanager.rc-manager == "resolvconf")) ''
|
||||
${pkgs.openresolv}/bin/resolvconf -u
|
||||
''}
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ with lib;
|
|||
networkmanager-openvpn = super.networkmanager-openvpn.override { withGnome = false; };
|
||||
networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
|
||||
networkmanager-iodine = super.networkmanager-iodine.override { withGnome = false; };
|
||||
pinentry = super.pinentry.override { gtk2 = null; gcr = null; qt = null; };
|
||||
pinentry = super.pinentry.override { gtk2 = null; gcr = null; qt4 = null; qt5 = null; };
|
||||
gobject-introspection = super.gobject-introspection.override { x11Support = false; };
|
||||
}));
|
||||
};
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
# /etc files related to networking, such as /etc/services.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.networking.resolvconf;
|
||||
|
||||
resolvconfOptions = cfg.extraOptions
|
||||
++ optional cfg.dnsSingleRequest "single-request"
|
||||
++ optional cfg.dnsExtensionMechanism "edns0";
|
||||
|
||||
configText =
|
||||
''
|
||||
# This is the default, but we must set it here to prevent
|
||||
# a collision with an apparently unrelated environment
|
||||
# variable with the same name exported by dhcpcd.
|
||||
interface_order='lo lo[0-9]*'
|
||||
'' + optionalString config.services.nscd.enable ''
|
||||
# Invalidate the nscd cache whenever resolv.conf is
|
||||
# regenerated.
|
||||
libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null'
|
||||
'' + optionalString (length resolvconfOptions > 0) ''
|
||||
# Options as described in resolv.conf(5)
|
||||
resolv_conf_options='${concatStringsSep " " resolvconfOptions}'
|
||||
'' + optionalString cfg.useLocalResolver ''
|
||||
# This hosts runs a full-blown DNS resolver.
|
||||
name_servers='127.0.0.1'
|
||||
'' + cfg.extraConfig;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
networking.resolvconf = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
description = ''
|
||||
DNS configuration is managed by resolvconf.
|
||||
'';
|
||||
};
|
||||
|
||||
useHostResolvConf = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
In containers, whether to use the
|
||||
<filename>resolv.conf</filename> supplied by the host.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsSingleRequest = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Recent versions of glibc will issue both ipv4 (A) and ipv6 (AAAA)
|
||||
address queries at the same time, from the same port. Sometimes upstream
|
||||
routers will systemically drop the ipv4 queries. The symptom of this problem is
|
||||
that 'getent hosts example.com' only returns ipv6 (or perhaps only ipv4) addresses. The
|
||||
workaround for this is to specify the option 'single-request' in
|
||||
/etc/resolv.conf. This option enables that.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsExtensionMechanism = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable the <code>edns0</code> option in <filename>resolv.conf</filename>. With
|
||||
that option set, <code>glibc</code> supports use of the extension mechanisms for
|
||||
DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
|
||||
which does not work without it.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "libc=NO";
|
||||
description = ''
|
||||
Extra configuration to append to <filename>resolvconf.conf</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [ "ndots:1" "rotate" ];
|
||||
description = ''
|
||||
Set the options in <filename>/etc/resolv.conf</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
useLocalResolver = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Use local DNS server for resolving.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
networking.resolvconf.enable = !(config.environment.etc ? "resolv.conf");
|
||||
|
||||
environment.etc."resolvconf.conf".text =
|
||||
if !cfg.enable then
|
||||
# Force-stop any attempts to use resolvconf
|
||||
''
|
||||
echo "resolvconf is disabled on this system but was used anyway:" >&2
|
||||
echo "$0 $*" >&2
|
||||
exit 1
|
||||
''
|
||||
else configText;
|
||||
}
|
||||
|
||||
(mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.openresolv ];
|
||||
|
||||
systemd.services.resolvconf = {
|
||||
description = "resolvconf update";
|
||||
|
||||
before = [ "network-pre.target" ];
|
||||
wants = [ "network-pre.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = [ config.environment.etc."resolvconf.conf".source ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.openresolv}/bin/resolvconf -u";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
})
|
||||
];
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{ config, pkgs ,lib ,... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.xdg.portal = {
|
||||
enable =
|
||||
mkEnableOption "<link xlink:href='https://github.com/flatpak/xdg-desktop-portal'>xdg desktop integration</link>"//{
|
||||
default = false;
|
||||
};
|
||||
|
||||
extraPortals = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
description = ''
|
||||
List of additional portals to add to path. Portals allow interaction
|
||||
with system, like choosing files or taking screenshots. At minimum,
|
||||
a desktop portal implementation should be listed. GNOME and KDE already
|
||||
adds <package>xdg-desktop-portal-gtk</package>; and
|
||||
<package>xdg-desktop-portal-kde</package> respectively. On other desktop
|
||||
environments you probably want to add them yourself.
|
||||
'';
|
||||
};
|
||||
|
||||
gtkUsePortal = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Sets environment variable <literal>GTK_USE_PORTAL</literal> to <literal>1</literal>.
|
||||
This is needed for packages ran outside Flatpak to respect and use XDG Desktop Portals.
|
||||
For example, you'd need to set this for non-flatpak Firefox to use native filechoosers.
|
||||
Defaults to <literal>false</literal> to respect its opt-in nature.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
cfg = config.xdg.portal;
|
||||
packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
|
||||
|
||||
in mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{ assertion = (cfg.gtkUsePortal -> cfg.extraPortals != []);
|
||||
message = "Setting xdg.portal.gtkUsePortal to true requires a portal implementation in xdg.portal.extraPortals such as xdg-desktop-portal-gtk or xdg-desktop-portal-kde.";
|
||||
}
|
||||
];
|
||||
|
||||
services.dbus.packages = packages;
|
||||
systemd.packages = packages;
|
||||
|
||||
environment.variables = {
|
||||
GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
|
||||
XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -84,7 +84,7 @@ with lib;
|
|||
|
||||
system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
|
||||
#!ipxe
|
||||
kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
||||
kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams}
|
||||
initrd initrd
|
||||
boot
|
||||
'';
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
./config/xdg/icons.nix
|
||||
./config/xdg/menus.nix
|
||||
./config/xdg/mime.nix
|
||||
./config/xdg/portal.nix
|
||||
./config/appstream.nix
|
||||
./config/xdg/sounds.nix
|
||||
./config/gtk/gtk-icon-cache.nix
|
||||
|
@ -25,6 +26,7 @@
|
|||
./config/nsswitch.nix
|
||||
./config/power-management.nix
|
||||
./config/pulseaudio.nix
|
||||
./config/resolvconf.nix
|
||||
./config/shells-environment.nix
|
||||
./config/swap.nix
|
||||
./config/sysctl.nix
|
||||
|
@ -138,6 +140,7 @@
|
|||
./programs/sway.nix
|
||||
./programs/thefuck.nix
|
||||
./programs/tmux.nix
|
||||
./programs/tsm-client.nix
|
||||
./programs/udevil.nix
|
||||
./programs/venus.nix
|
||||
./programs/vim.nix
|
||||
|
@ -195,6 +198,7 @@
|
|||
./services/audio/slimserver.nix
|
||||
./services/audio/snapserver.nix
|
||||
./services/audio/squeezelite.nix
|
||||
./services/audio/spotifyd.nix
|
||||
./services/audio/ympd.nix
|
||||
./services/backup/automysqlbackup.nix
|
||||
./services/backup/bacula.nix
|
||||
|
@ -209,6 +213,7 @@
|
|||
./services/backup/restic-rest-server.nix
|
||||
./services/backup/rsnapshot.nix
|
||||
./services/backup/tarsnap.nix
|
||||
./services/backup/tsm.nix
|
||||
./services/backup/znapzend.nix
|
||||
./services/cluster/hadoop/default.nix
|
||||
./services/cluster/kubernetes/addons/dns.nix
|
||||
|
@ -418,6 +423,7 @@
|
|||
./services/misc/gollum.nix
|
||||
./services/misc/gpsd.nix
|
||||
./services/misc/headphones.nix
|
||||
./services/misc/greenclip.nix
|
||||
./services/misc/home-assistant.nix
|
||||
./services/misc/ihaskell.nix
|
||||
./services/misc/irkerd.nix
|
||||
|
@ -469,6 +475,7 @@
|
|||
./services/misc/synergy.nix
|
||||
./services/misc/sysprof.nix
|
||||
./services/misc/taskserver
|
||||
./services/misc/tiddlywiki.nix
|
||||
./services/misc/tzupdate.nix
|
||||
./services/misc/uhub.nix
|
||||
./services/misc/weechat.nix
|
||||
|
@ -512,6 +519,7 @@
|
|||
./services/monitoring/systemhealth.nix
|
||||
./services/monitoring/teamviewer.nix
|
||||
./services/monitoring/telegraf.nix
|
||||
./services/monitoring/thanos.nix
|
||||
./services/monitoring/ups.nix
|
||||
./services/monitoring/uptime.nix
|
||||
./services/monitoring/vnstat.nix
|
||||
|
@ -686,6 +694,7 @@
|
|||
./services/networking/tcpcrypt.nix
|
||||
./services/networking/teamspeak3.nix
|
||||
./services/networking/tedicross.nix
|
||||
./services/networking/thelounge.nix
|
||||
./services/networking/tinc.nix
|
||||
./services/networking/tinydns.nix
|
||||
./services/networking/tftpd.nix
|
||||
|
@ -772,6 +781,7 @@
|
|||
./services/web-apps/icingaweb2/module-monitoring.nix
|
||||
./services/web-apps/limesurvey.nix
|
||||
./services/web-apps/mattermost.nix
|
||||
./services/web-apps/mediawiki.nix
|
||||
./services/web-apps/miniflux.nix
|
||||
./services/web-apps/nextcloud.nix
|
||||
./services/web-apps/nexus.nix
|
||||
|
@ -807,6 +817,7 @@
|
|||
./services/web-servers/uwsgi.nix
|
||||
./services/web-servers/varnish/default.nix
|
||||
./services/web-servers/zope2.nix
|
||||
./services/x11/extra-layouts.nix
|
||||
./services/x11/colord.nix
|
||||
./services/x11/compton.nix
|
||||
./services/x11/unclutter.nix
|
||||
|
|
|
@ -26,7 +26,9 @@ with lib;
|
|||
|
||||
security.allowSimultaneousMultithreading = mkDefault false;
|
||||
|
||||
security.virtualization.flushL1DataCache = mkDefault "always";
|
||||
security.forcePageTableIsolation = mkDefault true;
|
||||
|
||||
security.virtualisation.flushL1DataCache = mkDefault "always";
|
||||
|
||||
security.apparmor.enable = mkDefault true;
|
||||
|
||||
|
@ -42,9 +44,6 @@ with lib;
|
|||
|
||||
# Disable legacy virtual syscalls
|
||||
"vsyscall=none"
|
||||
|
||||
# Enable PTI even if CPU claims to be safe from meltdown
|
||||
"pti=on"
|
||||
];
|
||||
|
||||
boot.blacklistedKernelModules = [
|
||||
|
|
|
@ -12,7 +12,7 @@ with lib;
|
|||
''
|
||||
# Set up the per-user profile.
|
||||
mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR"
|
||||
if [ "$(stat --printf '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then
|
||||
if [ "$(stat -c '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then
|
||||
echo "WARNING: the per-user profile dir $NIX_USER_PROFILE_DIR should belong to user id $(id -u)" >&2
|
||||
fi
|
||||
|
||||
|
@ -34,7 +34,7 @@ with lib;
|
|||
# Create the per-user garbage collector roots directory.
|
||||
NIX_USER_GCROOTS_DIR="/nix/var/nix/gcroots/per-user/$USER"
|
||||
mkdir -m 0755 -p "$NIX_USER_GCROOTS_DIR"
|
||||
if [ "$(stat --printf '%u' "$NIX_USER_GCROOTS_DIR")" != "$(id -u)" ]; then
|
||||
if [ "$(stat -c '%u' "$NIX_USER_GCROOTS_DIR")" != "$(id -u)" ]; then
|
||||
echo "WARNING: the per-user gcroots dir $NIX_USER_GCROOTS_DIR should belong to user id $(id -u)" >&2
|
||||
fi
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ let
|
|||
|
||||
knownHostsText = (flip (concatMapStringsSep "\n") knownHosts
|
||||
(h: assert h.hostNames != [];
|
||||
concatStringsSep "," h.hostNames + " "
|
||||
optionalString h.certAuthority "@cert-authority " + concatStringsSep "," h.hostNames + " "
|
||||
+ (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
|
||||
)) + "\n";
|
||||
|
||||
|
@ -128,6 +128,14 @@ in
|
|||
default = {};
|
||||
type = types.loaOf (types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
certAuthority = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
This public key is an SSH certificate authority, rather than an
|
||||
individual host's key.
|
||||
'';
|
||||
};
|
||||
hostNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
|
@ -227,6 +235,7 @@ in
|
|||
systemd.user.services.ssh-agent = mkIf cfg.startAgent
|
||||
{ description = "SSH Agent";
|
||||
wantedBy = [ "default.target" ];
|
||||
unitConfig.ConditionUser = "!@system";
|
||||
serviceConfig =
|
||||
{ ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";
|
||||
ExecStart =
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
|
||||
inherit (builtins) length map;
|
||||
inherit (lib.attrsets) attrNames filterAttrs hasAttr mapAttrs mapAttrsToList optionalAttrs;
|
||||
inherit (lib.modules) mkDefault mkIf;
|
||||
inherit (lib.options) literalExample mkEnableOption mkOption;
|
||||
inherit (lib.strings) concatStringsSep optionalString toLower;
|
||||
inherit (lib.types) addCheck attrsOf lines loaOf nullOr package path port str strMatching submodule;
|
||||
|
||||
# Checks if given list of strings contains unique
|
||||
# elements when compared without considering case.
|
||||
# Type: checkIUnique :: [string] -> bool
|
||||
# Example: checkIUnique ["foo" "Foo"] => false
|
||||
checkIUnique = lst:
|
||||
let
|
||||
lenUniq = l: length (lib.lists.unique l);
|
||||
in
|
||||
lenUniq lst == lenUniq (map toLower lst);
|
||||
|
||||
# TSM rejects servername strings longer than 64 chars.
|
||||
servernameType = strMatching ".{1,64}";
|
||||
|
||||
serverOptions = { name, config, ... }: {
|
||||
options.name = mkOption {
|
||||
type = servernameType;
|
||||
example = "mainTsmServer";
|
||||
description = ''
|
||||
Local name of the IBM TSM server,
|
||||
must be uncapitalized and no longer than 64 chars.
|
||||
The value will be used for the
|
||||
<literal>server</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
'';
|
||||
};
|
||||
options.server = mkOption {
|
||||
type = strMatching ".+";
|
||||
example = "tsmserver.company.com";
|
||||
description = ''
|
||||
Host/domain name or IP address of the IBM TSM server.
|
||||
The value will be used for the
|
||||
<literal>tcpserveraddress</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
'';
|
||||
};
|
||||
options.port = mkOption {
|
||||
type = addCheck port (p: p<=32767);
|
||||
default = 1500; # official default
|
||||
description = ''
|
||||
TCP port of the IBM TSM server.
|
||||
The value will be used for the
|
||||
<literal>tcpport</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
TSM does not support ports above 32767.
|
||||
'';
|
||||
};
|
||||
options.node = mkOption {
|
||||
type = strMatching ".+";
|
||||
example = "MY-TSM-NODE";
|
||||
description = ''
|
||||
Target node name on the IBM TSM server.
|
||||
The value will be used for the
|
||||
<literal>nodename</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
'';
|
||||
};
|
||||
options.genPasswd = mkEnableOption ''
|
||||
automatic client password generation.
|
||||
This option influences the
|
||||
<literal>passwordaccess</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
The password will be stored in the directory
|
||||
given by the option <option>passwdDir</option>.
|
||||
<emphasis>Caution</emphasis>:
|
||||
If this option is enabled and the server forces
|
||||
to renew the password (e.g. on first connection),
|
||||
a random password will be generated and stored
|
||||
'';
|
||||
options.passwdDir = mkOption {
|
||||
type = path;
|
||||
example = "/home/alice/tsm-password";
|
||||
description = ''
|
||||
Directory that holds the TSM
|
||||
node's password information.
|
||||
The value will be used for the
|
||||
<literal>passworddir</literal>
|
||||
directive in <filename>dsm.sys</filename>.
|
||||
'';
|
||||
};
|
||||
options.includeExclude = mkOption {
|
||||
type = lines;
|
||||
default = "";
|
||||
example = ''
|
||||
exclude.dir /nix/store
|
||||
include.encrypt /home/.../*
|
||||
'';
|
||||
description = ''
|
||||
<literal>include.*</literal> and
|
||||
<literal>exclude.*</literal> directives to be
|
||||
used when sending files to the IBM TSM server.
|
||||
The lines will be written into a file that the
|
||||
<literal>inclexcl</literal>
|
||||
directive in <filename>dsm.sys</filename> points to.
|
||||
'';
|
||||
};
|
||||
options.extraConfig = mkOption {
|
||||
# TSM option keys are case insensitive;
|
||||
# we have to ensure there are no keys that
|
||||
# differ only by upper and lower case.
|
||||
type = addCheck
|
||||
(attrsOf (nullOr str))
|
||||
(attrs: checkIUnique (attrNames attrs));
|
||||
default = {};
|
||||
example.compression = "yes";
|
||||
example.passwordaccess = null;
|
||||
description = ''
|
||||
Additional key-value pairs for the server stanza.
|
||||
Values must be strings, or <literal>null</literal>
|
||||
for the key not to be used in the stanza
|
||||
(e.g. to overrule values generated by other options).
|
||||
'';
|
||||
};
|
||||
options.text = mkOption {
|
||||
type = lines;
|
||||
example = literalExample
|
||||
''lib.modules.mkAfter "compression no"'';
|
||||
description = ''
|
||||
Additional text lines for the server stanza.
|
||||
This option can be used if certion configuration keys
|
||||
must be used multiple times or ordered in a certain way
|
||||
as the <option>extraConfig</option> option can't
|
||||
control the order of lines in the resulting stanza.
|
||||
Note that the <literal>server</literal>
|
||||
line at the beginning of the stanza is
|
||||
not part of this option's value.
|
||||
'';
|
||||
};
|
||||
options.stanza = mkOption {
|
||||
type = str;
|
||||
internal = true;
|
||||
visible = false;
|
||||
description = "Server stanza text generated from the options.";
|
||||
};
|
||||
config.name = mkDefault name;
|
||||
# Client system-options file directives are explained here:
|
||||
# https://www.ibm.com/support/knowledgecenter/SSEQVQ_8.1.8/client/c_opt_usingopts.html
|
||||
config.extraConfig =
|
||||
mapAttrs (lib.trivial.const mkDefault) (
|
||||
{
|
||||
commmethod = "v6tcpip"; # uses v4 or v6, based on dns lookup result
|
||||
tcpserveraddress = config.server;
|
||||
tcpport = builtins.toString config.port;
|
||||
nodename = config.node;
|
||||
passwordaccess = if config.genPasswd then "generate" else "prompt";
|
||||
passworddir = ''"${config.passwdDir}"'';
|
||||
} // optionalAttrs (config.includeExclude!="") {
|
||||
inclexcl = ''"${pkgs.writeText "inclexcl.dsm.sys" config.includeExclude}"'';
|
||||
}
|
||||
);
|
||||
config.text =
|
||||
let
|
||||
attrset = filterAttrs (k: v: v!=null) config.extraConfig;
|
||||
mkLine = k: v: k + optionalString (v!="") " ${v}";
|
||||
lines = mapAttrsToList mkLine attrset;
|
||||
in
|
||||
concatStringsSep "\n" lines;
|
||||
config.stanza = ''
|
||||
server ${config.name}
|
||||
${config.text}
|
||||
'';
|
||||
};
|
||||
|
||||
options.programs.tsmClient = {
|
||||
enable = mkEnableOption ''
|
||||
IBM Spectrum Protect (Tivoli Storage Manager, TSM)
|
||||
client command line applications with a
|
||||
client system-options file "dsm.sys"
|
||||
'';
|
||||
servers = mkOption {
|
||||
type = loaOf (submodule [ serverOptions ]);
|
||||
default = {};
|
||||
example.mainTsmServer = {
|
||||
server = "tsmserver.company.com";
|
||||
node = "MY-TSM-NODE";
|
||||
extraConfig.compression = "yes";
|
||||
};
|
||||
description = ''
|
||||
Server definitions ("stanzas")
|
||||
for the client system-options file.
|
||||
'';
|
||||
};
|
||||
defaultServername = mkOption {
|
||||
type = nullOr servernameType;
|
||||
default = null;
|
||||
example = "mainTsmServer";
|
||||
description = ''
|
||||
If multiple server stanzas are declared with
|
||||
<option>programs.tsmClient.servers</option>,
|
||||
this option may be used to name a default
|
||||
server stanza that IBM TSM uses in the absence of
|
||||
a user-defined <filename>dsm.opt</filename> file.
|
||||
This option translates to a
|
||||
<literal>defaultserver</literal> configuration line.
|
||||
'';
|
||||
};
|
||||
dsmSysText = mkOption {
|
||||
type = lines;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
This configuration key contains the effective text
|
||||
of the client system-options file "dsm.sys".
|
||||
It should not be changed, but may be
|
||||
used to feed the configuration into other
|
||||
TSM-depending packages used on the system.
|
||||
'';
|
||||
};
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.tsm-client;
|
||||
defaultText = "pkgs.tsm-client";
|
||||
example = literalExample "pkgs.tsm-client-withGui";
|
||||
description = ''
|
||||
The TSM client derivation to be
|
||||
added to the system environment.
|
||||
It will called with <literal>.override</literal>
|
||||
to add paths to the client system-options file.
|
||||
'';
|
||||
};
|
||||
wrappedPackage = mkOption {
|
||||
type = package;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
The TSM client derivation, wrapped with the path
|
||||
to the client system-options file "dsm.sys".
|
||||
This option is to provide the effective derivation
|
||||
for other modules that want to call TSM executables.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
cfg = config.programs.tsmClient;
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = checkIUnique (mapAttrsToList (k: v: v.name) cfg.servers);
|
||||
message = ''
|
||||
TSM servernames contain duplicate name
|
||||
(note that case doesn't matter!)
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = (cfg.defaultServername!=null)->(hasAttr cfg.defaultServername cfg.servers);
|
||||
message = "TSM defaultServername not found in list of servers";
|
||||
}
|
||||
];
|
||||
|
||||
dsmSysText = ''
|
||||
**** IBM Spectrum Protect (Tivoli Storage Manager)
|
||||
**** client system-options file "dsm.sys".
|
||||
**** Do not edit!
|
||||
**** This file is generated by NixOS configuration.
|
||||
|
||||
${optionalString (cfg.defaultServername!=null) "defaultserver ${cfg.defaultServername}"}
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: v.stanza) cfg.servers)}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
inherit options;
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
inherit assertions;
|
||||
programs.tsmClient.dsmSysText = dsmSysText;
|
||||
programs.tsmClient.wrappedPackage = cfg.package.override rec {
|
||||
dsmSysCli = pkgs.writeText "dsm.sys" cfg.dsmSysText;
|
||||
dsmSysApi = dsmSysCli;
|
||||
};
|
||||
environment.systemPackages = [ cfg.wrappedPackage ];
|
||||
};
|
||||
|
||||
meta.maintainers = [ lib.maintainers.yarny ];
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ in
|
|||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.xonsh;
|
||||
example = literalExample "pkgs.xonsh.override { configFile = \"/path/to/xonshrc\"; }";
|
||||
description = ''
|
||||
xonsh package to use.
|
||||
|
@ -46,11 +47,11 @@ in
|
|||
|
||||
environment.etc."xonshrc".text = cfg.config;
|
||||
|
||||
environment.systemPackages = [ pkgs.xonsh ];
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.shells =
|
||||
[ "/run/current-system/sw/bin/xonsh"
|
||||
"${pkgs.xonsh}/bin/xonsh"
|
||||
"${cfg.package}/bin/xonsh"
|
||||
];
|
||||
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ with lib;
|
|||
let value = getAttrFromPath [ "services" "ddclient" "domain" ] config;
|
||||
in if value != "" then [ value ] else []))
|
||||
(mkRemovedOptionModule [ "services" "ddclient" "homeDir" ] "")
|
||||
(mkRenamedOptionModule [ "services" "flatpak" "extraPortals" ] [ "xdg" "portal" "extraPortals" ])
|
||||
(mkRenamedOptionModule [ "services" "i2pd" "extIp" ] [ "services" "i2pd" "address" ])
|
||||
(mkRenamedOptionModule [ "services" "kubernetes" "apiserver" "admissionControl" ] [ "services" "kubernetes" "apiserver" "enableAdmissionPlugins" ])
|
||||
(mkRenamedOptionModule [ "services" "kubernetes" "apiserver" "address" ] ["services" "kubernetes" "apiserver" "bindAddress"])
|
||||
|
@ -62,6 +63,8 @@ with lib;
|
|||
(mkRemovedOptionModule [ "security" "setuidOwners" ] "Use security.wrappers instead")
|
||||
(mkRemovedOptionModule [ "security" "setuidPrograms" ] "Use security.wrappers instead")
|
||||
|
||||
(mkRenamedOptionModule [ "security" "virtualization" "flushL1DataCache" ] [ "security" "virtualisation" "flushL1DataCache" ])
|
||||
|
||||
# PAM
|
||||
(mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ])
|
||||
|
||||
|
@ -248,6 +251,12 @@ with lib;
|
|||
# KSM
|
||||
(mkRenamedOptionModule [ "hardware" "enableKSM" ] [ "hardware" "ksm" "enable" ])
|
||||
|
||||
# resolvconf
|
||||
(mkRenamedOptionModule [ "networking" "dnsSingleRequest" ] [ "networking" "resolvconf" "dnsSingleRequest" ])
|
||||
(mkRenamedOptionModule [ "networking" "dnsExtensionMechanism" ] [ "networking" "resolvconf" "dnsExtensionMechanism" ])
|
||||
(mkRenamedOptionModule [ "networking" "extraResolvconfConf" ] [ "networking" "resolvconf" "extraConfig" ])
|
||||
(mkRenamedOptionModule [ "networking" "resolvconfOptions" ] [ "networking" "resolvconf" "extraOptions" ])
|
||||
|
||||
] ++ (forEach [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
|
||||
"jsonExporter" "minioExporter" "nginxExporter" "nodeExporter"
|
||||
"snmpExporter" "unifiExporter" "varnishExporter" ]
|
||||
|
|
|
@ -48,13 +48,25 @@ with lib;
|
|||
e.g., shared caches). This attack vector is unproven.
|
||||
|
||||
Disabling SMT is a supplement to the L1 data cache flushing mitigation
|
||||
(see <xref linkend="opt-security.virtualization.flushL1DataCache"/>)
|
||||
(see <xref linkend="opt-security.virtualisation.flushL1DataCache"/>)
|
||||
versus malicious VM guests (SMT could "bring back" previously flushed
|
||||
data).
|
||||
'';
|
||||
};
|
||||
|
||||
security.virtualization.flushL1DataCache = mkOption {
|
||||
security.forcePageTableIsolation = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to force-enable the Page Table Isolation (PTI) Linux kernel
|
||||
feature even on CPU models that claim to be safe from Meltdown.
|
||||
|
||||
This hardening feature is most beneficial to systems that run untrusted
|
||||
workloads that rely on address space isolation for security.
|
||||
'';
|
||||
};
|
||||
|
||||
security.virtualisation.flushL1DataCache = mkOption {
|
||||
type = types.nullOr (types.enum [ "never" "cond" "always" ]);
|
||||
default = null;
|
||||
description = ''
|
||||
|
@ -114,8 +126,12 @@ with lib;
|
|||
boot.kernelParams = [ "nosmt" ];
|
||||
})
|
||||
|
||||
(mkIf (config.security.virtualization.flushL1DataCache != null) {
|
||||
boot.kernelParams = [ "kvm-intel.vmentry_l1d_flush=${config.security.virtualization.flushL1DataCache}" ];
|
||||
(mkIf config.security.forcePageTableIsolation {
|
||||
boot.kernelParams = [ "pti=on" ];
|
||||
})
|
||||
|
||||
(mkIf (config.security.virtualisation.flushL1DataCache != null) {
|
||||
boot.kernelParams = [ "kvm-intel.vmentry_l1d_flush=${config.security.virtualisation.flushL1DataCache}" ];
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.spotifyd;
|
||||
spotifydConf = pkgs.writeText "spotifyd.conf" cfg.config;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.spotifyd = {
|
||||
enable = mkEnableOption "spotifyd, a Spotify playing daemon";
|
||||
|
||||
config = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Configuration for Spotifyd. For syntax and directives, see
|
||||
https://github.com/Spotifyd/spotifyd#Configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.spotifyd = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" "sound.target" ];
|
||||
description = "spotifyd, a Spotify playing daemon";
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.spotifyd}/bin/spotifyd --no-daemon --cache_path /var/cache/spotifyd --config ${spotifydConf}";
|
||||
Restart = "always";
|
||||
RestartSec = 12;
|
||||
DynamicUser = true;
|
||||
CacheDirectory = "spotifyd";
|
||||
SupplementaryGroups = ["audio"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = [ maintainers.anderslundstedt ];
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
|
||||
inherit (lib.attrsets) hasAttr;
|
||||
inherit (lib.modules) mkDefault mkIf;
|
||||
inherit (lib.options) mkEnableOption mkOption;
|
||||
inherit (lib.types) nullOr strMatching;
|
||||
|
||||
options.services.tsmBackup = {
|
||||
enable = mkEnableOption ''
|
||||
automatic backups with the
|
||||
IBM Spectrum Protect (Tivoli Storage Manager, TSM) client.
|
||||
This also enables
|
||||
<option>programs.tsmClient.enable</option>
|
||||
'';
|
||||
command = mkOption {
|
||||
type = strMatching ".+";
|
||||
default = "backup";
|
||||
example = "incr";
|
||||
description = ''
|
||||
The actual command passed to the
|
||||
<literal>dsmc</literal> executable to start the backup.
|
||||
'';
|
||||
};
|
||||
servername = mkOption {
|
||||
type = strMatching ".+";
|
||||
example = "mainTsmServer";
|
||||
description = ''
|
||||
Create a systemd system service
|
||||
<literal>tsm-backup.service</literal> that starts
|
||||
a backup based on the given servername's stanza.
|
||||
Note that this server's
|
||||
<option>passwdDir</option> will default to
|
||||
<filename>/var/lib/tsm-backup/password</filename>
|
||||
(but may be overridden);
|
||||
also, the service will use
|
||||
<filename>/var/lib/tsm-backup</filename> as
|
||||
<literal>HOME</literal> when calling
|
||||
<literal>dsmc</literal>.
|
||||
'';
|
||||
};
|
||||
autoTime = mkOption {
|
||||
type = nullOr (strMatching ".+");
|
||||
default = null;
|
||||
example = "12:00";
|
||||
description = ''
|
||||
The backup service will be invoked
|
||||
automatically at the given date/time,
|
||||
which must be in the format described in
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
The default <literal>null</literal>
|
||||
disables automatic backups.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
cfg = config.services.tsmBackup;
|
||||
cfgPrg = config.programs.tsmClient;
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = hasAttr cfg.servername cfgPrg.servers;
|
||||
message = "TSM service servername not found in list of servers";
|
||||
}
|
||||
{
|
||||
assertion = cfgPrg.servers.${cfg.servername}.genPasswd;
|
||||
message = "TSM service requires automatic password generation";
|
||||
}
|
||||
];
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
inherit options;
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
inherit assertions;
|
||||
programs.tsmClient.enable = true;
|
||||
programs.tsmClient.servers."${cfg.servername}".passwdDir =
|
||||
mkDefault "/var/lib/tsm-backup/password";
|
||||
systemd.services.tsm-backup = {
|
||||
description = "IBM Spectrum Protect (Tivoli Storage Manager) Backup";
|
||||
# DSM_LOG needs a trailing slash to have it treated as a directory.
|
||||
# `/var/log` would be littered with TSM log files otherwise.
|
||||
environment.DSM_LOG = "/var/log/tsm-backup/";
|
||||
# TSM needs a HOME dir to store certificates.
|
||||
environment.HOME = "/var/lib/tsm-backup";
|
||||
# for exit status description see
|
||||
# https://www.ibm.com/support/knowledgecenter/en/SSEQVQ_8.1.8/client/c_sched_rtncode.html
|
||||
serviceConfig.SuccessExitStatus = "4 8";
|
||||
# The `-se` option must come after the command.
|
||||
# The `-optfile` option suppresses a `dsm.opt`-not-found warning.
|
||||
serviceConfig.ExecStart =
|
||||
"${cfgPrg.wrappedPackage}/bin/dsmc ${cfg.command} -se='${cfg.servername}' -optfile=/dev/null";
|
||||
serviceConfig.LogsDirectory = "tsm-backup";
|
||||
serviceConfig.StateDirectory = "tsm-backup";
|
||||
serviceConfig.StateDirectoryMode = "0750";
|
||||
startAt = mkIf (cfg.autoTime!=null) cfg.autoTime;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = [ lib.maintainers.yarny ];
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
{ lib, pkgs, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.zfs.autoReplication;
|
||||
recursive = optionalString cfg.recursive " --recursive";
|
||||
followDelete = optionalString cfg.followDelete " --follow-delete";
|
||||
in {
|
||||
options = {
|
||||
services.zfs.autoReplication = {
|
||||
enable = mkEnableOption "ZFS snapshot replication.";
|
||||
|
||||
followDelete = mkOption {
|
||||
description = "Remove remote snapshots that don't have a local correspondant.";
|
||||
default = true;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
description = "Remote host where snapshots should be sent.";
|
||||
example = "example.com";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
identityFilePath = mkOption {
|
||||
description = "Path to SSH key used to login to host.";
|
||||
example = "/home/username/.ssh/id_rsa";
|
||||
type = types.path;
|
||||
};
|
||||
|
||||
localFilesystem = mkOption {
|
||||
description = "Local ZFS fileystem from which snapshots should be sent. Defaults to the attribute name.";
|
||||
example = "pool/file/path";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
remoteFilesystem = mkOption {
|
||||
description = "Remote ZFS filesystem where snapshots should be sent.";
|
||||
example = "pool/file/path";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
recursive = mkOption {
|
||||
description = "Recursively discover snapshots to send.";
|
||||
default = true;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
description = "Username used by SSH to login to remote host.";
|
||||
example = "username";
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
pkgs.lz4
|
||||
];
|
||||
|
||||
systemd.services."zfs-replication" = {
|
||||
after = [
|
||||
"zfs-snapshot-daily.service"
|
||||
"zfs-snapshot-frequent.service"
|
||||
"zfs-snapshot-hourly.service"
|
||||
"zfs-snapshot-monthly.service"
|
||||
"zfs-snapshot-weekly.service"
|
||||
];
|
||||
description = "ZFS Snapshot Replication";
|
||||
documentation = [
|
||||
"https://github.com/alunduil/zfs-replicate"
|
||||
];
|
||||
restartIfChanged = false;
|
||||
serviceConfig.ExecStart = "${pkgs.zfs-replicate}/bin/zfs-replicate${recursive} -l ${escapeShellArg cfg.username} -i ${escapeShellArg cfg.identityFilePath}${followDelete} ${escapeShellArg cfg.host} ${escapeShellArg cfg.remoteFilesystem} ${escapeShellArg cfg.localFilesystem}";
|
||||
wantedBy = [
|
||||
"zfs-snapshot-daily.service"
|
||||
"zfs-snapshot-frequent.service"
|
||||
"zfs-snapshot-hourly.service"
|
||||
"zfs-snapshot-monthly.service"
|
||||
"zfs-snapshot-weekly.service"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ alunduil ];
|
||||
};
|
||||
}
|
|
@ -237,8 +237,8 @@ in
|
|||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.rootpwFile != null || cfg.rootpw != null;
|
||||
message = "Either services.openldap.rootpw or services.openldap.rootpwFile must be set";
|
||||
assertion = cfg.configDir != null || cfg.rootpwFile != null || cfg.rootpw != null;
|
||||
message = "services.openldap: Unless configDir is set, either rootpw or rootpwFile must be set";
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -6,23 +6,10 @@ let
|
|||
|
||||
cfg = config.services.postgresql;
|
||||
|
||||
# see description of extraPlugins
|
||||
postgresqlAndPlugins = pg:
|
||||
if cfg.extraPlugins == [] then pg
|
||||
else pkgs.buildEnv {
|
||||
name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}";
|
||||
paths = [ pg pg.lib ] ++ cfg.extraPlugins;
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
postBuild =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
rm $out/bin/{pg_config,postgres,pg_ctl}
|
||||
cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl}
|
||||
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
|
||||
'';
|
||||
};
|
||||
|
||||
postgresql = postgresqlAndPlugins cfg.package;
|
||||
postgresql =
|
||||
if cfg.extraPlugins == []
|
||||
then cfg.package
|
||||
else cfg.package.withPackages (_: cfg.extraPlugins);
|
||||
|
||||
# The main PostgreSQL configuration file.
|
||||
configFile = pkgs.writeText "postgresql.conf"
|
||||
|
@ -55,7 +42,7 @@ in
|
|||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
example = literalExample "pkgs.postgresql_9_6";
|
||||
example = literalExample "pkgs.postgresql_11";
|
||||
description = ''
|
||||
PostgreSQL package to use.
|
||||
'';
|
||||
|
@ -71,7 +58,7 @@ in
|
|||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
example = "/var/lib/postgresql/9.6";
|
||||
example = "/var/lib/postgresql/11";
|
||||
description = ''
|
||||
Data directory for PostgreSQL.
|
||||
'';
|
||||
|
@ -192,17 +179,11 @@ in
|
|||
extraPlugins = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql_9_4; }) ]";
|
||||
example = literalExample "with pkgs.postgresql_11.pkgs; [ postgis pg_repack ]";
|
||||
description = ''
|
||||
When this list contains elements a new store path is created.
|
||||
PostgreSQL and the elements are symlinked into it. Then pg_config,
|
||||
postgres and pg_ctl are copied to make them use the new
|
||||
$out/lib directory as pkglibdir. This makes it possible to use postgis
|
||||
without patching the .sql files which reference $libdir/postgis-1.5.
|
||||
List of PostgreSQL plugins. PostgreSQL version for each plugin should
|
||||
match version for <literal>services.postgresql.package</literal> value.
|
||||
'';
|
||||
# Note: the duplication of executables is about 4MB size.
|
||||
# So a nicer solution was patching postgresql to allow setting the
|
||||
# libdir explicitely.
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
<filename>configuration.nix</filename>:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.postgresql.enable"/> = true;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_4;
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_11;
|
||||
</programlisting>
|
||||
Note that you are required to specify the desired version of PostgreSQL
|
||||
(e.g. <literal>pkgs.postgresql_9_4</literal>). Since upgrading your
|
||||
(e.g. <literal>pkgs.postgresql_11</literal>). Since upgrading your
|
||||
PostgreSQL version requires a database dump and reload (see below), NixOS
|
||||
cannot provide a default value for
|
||||
<xref linkend="opt-services.postgresql.package"/> such as the most recent
|
||||
|
@ -52,7 +52,7 @@ Type "help" for help.
|
|||
|
||||
<para>
|
||||
By default, PostgreSQL stores its databases in
|
||||
<filename>/var/db/postgresql</filename>. You can override this using
|
||||
<filename>/var/lib/postgresql/$psqlSchema</filename>. You can override this using
|
||||
<xref linkend="opt-services.postgresql.dataDir"/>, e.g.
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.postgresql.dataDir"/> = "/data/postgresql";
|
||||
|
@ -74,4 +74,70 @@ Type "help" for help.
|
|||
<link linkend="opt-services.postgresql.enable">here</link>.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="module-services-postgres-plugins">
|
||||
<title>Plugins</title>
|
||||
|
||||
<para>
|
||||
Plugins collection for each PostgreSQL version can be accessed with
|
||||
<literal>.pkgs</literal>. For example, for
|
||||
<literal>pkgs.postgresql_11</literal> package, its plugin collection is
|
||||
accessed by <literal>pkgs.postgresql_11.pkgs</literal>:
|
||||
<screen>
|
||||
<prompt>$ </prompt>nix repl '<nixpkgs>'
|
||||
|
||||
Loading '<nixpkgs>'...
|
||||
Added 10574 variables.
|
||||
|
||||
<prompt>nix-repl> </prompt>postgresql_11.pkgs.<TAB><TAB>
|
||||
postgresql_11.pkgs.cstore_fdw postgresql_11.pkgs.pg_repack
|
||||
postgresql_11.pkgs.pg_auto_failover postgresql_11.pkgs.pg_safeupdate
|
||||
postgresql_11.pkgs.pg_bigm postgresql_11.pkgs.pg_similarity
|
||||
postgresql_11.pkgs.pg_cron postgresql_11.pkgs.pg_topn
|
||||
postgresql_11.pkgs.pg_hll postgresql_11.pkgs.pgjwt
|
||||
postgresql_11.pkgs.pg_partman postgresql_11.pkgs.pgroonga
|
||||
...
|
||||
</screen>
|
||||
</para>
|
||||
<para>
|
||||
To add plugins via NixOS configuration, set <literal>services.postgresql.extraPlugins</literal>:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_11;
|
||||
<xref linkend="opt-services.postgresql.extraPlugins"/> = with pkgs.postgresql_11.pkgs; [
|
||||
pg_repack
|
||||
postgis
|
||||
];
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
You can build custom PostgreSQL-with-plugins (to be used outside of NixOS) using
|
||||
function <literal>.withPackages</literal>. For example, creating a custom
|
||||
PostgreSQL package in an overlay can look like:
|
||||
<programlisting>
|
||||
self: super: {
|
||||
postgresql_custom = self.postgresql_11.withPackages (ps: [
|
||||
ps.pg_repack
|
||||
ps.postgis
|
||||
]);
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Here's a recipe on how to override a particular plugin through an overlay:
|
||||
<programlisting>
|
||||
self: super: {
|
||||
postgresql_11 = super.postgresql_11.override { this = self.postgresql_11; } // {
|
||||
pkgs = super.postgresql_11.pkgs // {
|
||||
pg_repack = super.postgresql_11.pkgs.pg_repack.overrideAttrs (_: {
|
||||
name = "pg_repack-v20181024";
|
||||
src = self.fetchzip {
|
||||
url = "https://github.com/reorg/pg_repack/archive/923fa2f3c709a506e111cc963034bf2fd127aa00.tar.gz";
|
||||
sha256 = "17k6hq9xaax87yz79j773qyigm4fwk8z4zh5cyp6z0sxnwfqxxw5";
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -15,38 +15,28 @@ in {
|
|||
options = {
|
||||
services.flatpak = {
|
||||
enable = mkEnableOption "flatpak";
|
||||
|
||||
extraPortals = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
description = ''
|
||||
List of additional portals to add to path. Portals allow interaction
|
||||
with system, like choosing files or taking screenshots. At minimum,
|
||||
a desktop portal implementation should be listed. GNOME already
|
||||
adds <package>xdg-desktop-portal-gtk</package>; for KDE, there
|
||||
is <package>xdg-desktop-portal-kde</package>. Other desktop
|
||||
environments will probably want to do the same.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{ assertion = (config.xdg.portal.enable == true);
|
||||
message = "To use Flatpak you must enable XDG Desktop Portals with xdg.portal.enable.";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.flatpak ];
|
||||
|
||||
services.dbus.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
|
||||
services.dbus.packages = [ pkgs.flatpak ];
|
||||
|
||||
systemd.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
|
||||
systemd.packages = [ pkgs.flatpak ];
|
||||
|
||||
environment.profiles = [
|
||||
"$HOME/.local/share/flatpak/exports"
|
||||
"/var/lib/flatpak/exports"
|
||||
];
|
||||
|
||||
environment.variables = {
|
||||
XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
in other cases, you will need to add something like the following to your
|
||||
<filename>configuration.nix</filename>:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.flatpak.extraPortals"/> = [ pkgs.xdg-desktop-portal-gtk ];
|
||||
<xref linkend="opt-xdg.portal.extraPortals"/> = [ pkgs.xdg-desktop-portal-gtk ];
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
|
|
|
@ -9,6 +9,20 @@ let
|
|||
in {
|
||||
|
||||
options.services.bloop = {
|
||||
extraOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"-J-Xmx2G"
|
||||
"-J-XX:MaxInlineLevel=20"
|
||||
"-J-XX:+UseParallelGC"
|
||||
];
|
||||
description = ''
|
||||
Specifies additional command line argument to pass to bloop
|
||||
java process.
|
||||
'';
|
||||
};
|
||||
|
||||
install = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -25,10 +39,13 @@ in {
|
|||
systemd.user.services.bloop = {
|
||||
description = "Bloop Scala build server";
|
||||
|
||||
environment = {
|
||||
PATH = mkForce "${makeBinPath [ config.programs.java.package ]}";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = ''${pkgs.bloop}/bin/blp-server'';
|
||||
Restart = "always";
|
||||
Type = "simple";
|
||||
ExecStart = ''${pkgs.bloop}/bin/bloop server'';
|
||||
Restart = "always";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -150,6 +150,9 @@ in
|
|||
rm -rf /var/lib/graylog/plugins || true
|
||||
mkdir -p /var/lib/graylog/plugins -m 755
|
||||
|
||||
mkdir -p "$(dirname ${cfg.nodeIdFile})"
|
||||
chown -R ${cfg.user} "$(dirname ${cfg.nodeIdFile})"
|
||||
|
||||
for declarativeplugin in `ls ${glPlugins}/bin/`; do
|
||||
ln -sf ${glPlugins}/bin/$declarativeplugin /var/lib/graylog/plugins/$declarativeplugin
|
||||
done
|
||||
|
|
|
@ -13,6 +13,7 @@ let
|
|||
|| cfg.extraAliases != "";
|
||||
haveTransport = cfg.transport != "";
|
||||
haveVirtual = cfg.virtual != "";
|
||||
haveLocalRecipients = cfg.localRecipients != null;
|
||||
|
||||
clientAccess =
|
||||
optional (cfg.dnsBlacklistOverrides != "")
|
||||
|
@ -244,6 +245,7 @@ let
|
|||
|
||||
aliasesFile = pkgs.writeText "postfix-aliases" aliases;
|
||||
virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
|
||||
localRecipientMapFile = pkgs.writeText "postfix-local-recipient-map" (concatMapStrings (x: x + " ACCEPT\n") cfg.localRecipients);
|
||||
checkClientAccessFile = pkgs.writeText "postfix-check-client-access" cfg.dnsBlacklistOverrides;
|
||||
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
|
||||
masterCfFile = pkgs.writeText "postfix-master.cf" masterCfContent;
|
||||
|
@ -506,6 +508,19 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
localRecipients = mkOption {
|
||||
type = with types; nullOr (listOf string);
|
||||
default = null;
|
||||
description = ''
|
||||
List of accepted local users. Specify a bare username, an
|
||||
<literal>"@domain.tld"</literal> wild-card, or a complete
|
||||
<literal>"user@domain.tld"</literal> address. If set, these names end
|
||||
up in the local recipient map -- see the local(8) man-page -- and
|
||||
effectively replace the system user database lookup that's otherwise
|
||||
used by default.
|
||||
'';
|
||||
};
|
||||
|
||||
transport = mkOption {
|
||||
default = "";
|
||||
description = "
|
||||
|
@ -742,6 +757,7 @@ in
|
|||
// optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
|
||||
// optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
|
||||
// optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
|
||||
// optionalAttrs haveLocalRecipients { local_recipient_maps = [ "hash:/etc/postfix/local_recipients" ] ++ optional haveAliases "$alias_maps"; }
|
||||
// optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
|
||||
// optionalAttrs cfg.useSrs {
|
||||
sender_canonical_maps = [ "tcp:127.0.0.1:10001" ];
|
||||
|
@ -869,6 +885,9 @@ in
|
|||
(mkIf haveVirtual {
|
||||
services.postfix.mapFiles."virtual" = virtualFile;
|
||||
})
|
||||
(mkIf haveLocalRecipients {
|
||||
services.postfix.mapFiles."local_recipients" = localRecipientMapFile;
|
||||
})
|
||||
(mkIf cfg.enableHeaderChecks {
|
||||
services.postfix.mapFiles."header_checks" = headerChecksFile;
|
||||
})
|
||||
|
|
|
@ -55,6 +55,11 @@ let
|
|||
[service]
|
||||
DISABLE_REGISTRATION = ${boolToString cfg.disableRegistration}
|
||||
|
||||
${optionalString (cfg.mailerPasswordFile != null) ''
|
||||
[mailer]
|
||||
PASSWD = #mailerpass#
|
||||
''}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
in
|
||||
|
@ -255,6 +260,13 @@ in
|
|||
description = "Upper level of template and static files path.";
|
||||
};
|
||||
|
||||
mailerPasswordFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/lib/secrets/gitea/mailpw";
|
||||
description = "Path to a file containing the SMTP password.";
|
||||
};
|
||||
|
||||
disableRegistration = mkEnableOption "the registration lock" // {
|
||||
description = ''
|
||||
By default any user can create an account on this <literal>gitea</literal> instance.
|
||||
|
@ -344,9 +356,15 @@ in
|
|||
KEY="$(head -n1 ${secretKey})"
|
||||
DBPASS="$(head -n1 ${cfg.database.passwordFile})"
|
||||
JWTSECRET="$(head -n1 ${jwtSecret})"
|
||||
${if (cfg.mailerPasswordFile == null) then ''
|
||||
MAILERPASSWORD="#mailerpass#"
|
||||
'' else ''
|
||||
MAILERPASSWORD="$(head -n1 ${cfg.mailerPasswordFile} || :)"
|
||||
''}
|
||||
sed -e "s,#secretkey#,$KEY,g" \
|
||||
-e "s,#dbpass#,$DBPASS,g" \
|
||||
-e "s,#jwtsecet#,$JWTSECET,g" \
|
||||
-e "s,#mailerpass#,$MAILERPASSWORD,g" \
|
||||
-i ${runConfig}
|
||||
chmod 640 ${runConfig} ${secretKey} ${jwtSecret}
|
||||
''}
|
||||
|
|
|
@ -52,7 +52,7 @@ let
|
|||
gitlab_url = "http+unix://${pathUrlQuote gitlabSocket}";
|
||||
http_settings.self_signed_cert = false;
|
||||
repos_path = "${cfg.statePath}/repositories";
|
||||
secret_file = "${cfg.statePath}/config/gitlab_shell_secret";
|
||||
secret_file = "${cfg.statePath}/gitlab_shell_secret";
|
||||
log_file = "${cfg.statePath}/log/gitlab-shell.log";
|
||||
custom_hooks_dir = "${cfg.statePath}/custom_hooks";
|
||||
redis = {
|
||||
|
@ -109,7 +109,7 @@ let
|
|||
gitlab_shell = {
|
||||
path = "${cfg.packages.gitlab-shell}";
|
||||
hooks_path = "${cfg.statePath}/shell/hooks";
|
||||
secret_file = "${cfg.statePath}/config/gitlab_shell_secret";
|
||||
secret_file = "${cfg.statePath}/gitlab_shell_secret";
|
||||
upload_pack = true;
|
||||
receive_pack = true;
|
||||
};
|
||||
|
@ -132,14 +132,9 @@ let
|
|||
HOME = "${cfg.statePath}/home";
|
||||
UNICORN_PATH = "${cfg.statePath}/";
|
||||
GITLAB_PATH = "${cfg.packages.gitlab}/share/gitlab/";
|
||||
GITLAB_STATE_PATH = cfg.statePath;
|
||||
GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads";
|
||||
SCHEMA = "${cfg.statePath}/db/schema.rb";
|
||||
GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads";
|
||||
GITLAB_LOG_PATH = "${cfg.statePath}/log";
|
||||
GITLAB_SHELL_PATH = "${cfg.packages.gitlab-shell}";
|
||||
GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/shell/config.yml";
|
||||
GITLAB_SHELL_SECRET_PATH = "${cfg.statePath}/config/gitlab_shell_secret";
|
||||
GITLAB_SHELL_HOOKS_PATH = "${cfg.statePath}/shell/hooks";
|
||||
GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "redis.yml" (builtins.toJSON redisConfig);
|
||||
prometheus_multiproc_dir = "/run/gitlab";
|
||||
RAILS_ENV = "production";
|
||||
|
@ -502,23 +497,44 @@ in {
|
|||
systemd.tmpfiles.rules = [
|
||||
"d /run/gitlab 0755 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabEnv.HOME} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"z ${gitlabEnv.HOME}/.ssh/authorized_keys 0600 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.backupPath} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/builds 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/config 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/config/initializers 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/db 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/log 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/repositories 2770 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/shell 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/tmp 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/tmp/pids 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/tmp/sockets 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/uploads 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/pre-receive.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/post-receive.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${cfg.statePath}/custom_hooks/update.d 0700 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path} 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/artifacts 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/lfs-objects 0750 ${cfg.user} ${cfg.group} -"
|
||||
"d ${gitlabConfig.production.shared.path}/pages 0750 ${cfg.user} ${cfg.group} -"
|
||||
];
|
||||
"L+ ${cfg.statePath}/lib - - - - ${cfg.packages.gitlab}/share/gitlab/lib"
|
||||
"L+ /run/gitlab/config - - - - ${cfg.statePath}/config"
|
||||
"L+ /run/gitlab/log - - - - ${cfg.statePath}/log"
|
||||
"L+ /run/gitlab/tmp - - - - ${cfg.statePath}/tmp"
|
||||
"L+ /run/gitlab/uploads - - - - ${cfg.statePath}/uploads"
|
||||
|
||||
"L+ /run/gitlab/shell-config.yml - - - - ${pkgs.writeText "config.yml" (builtins.toJSON gitlabShellConfig)}"
|
||||
|
||||
"L+ ${cfg.statePath}/config/gitlab.yml - - - - ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)}"
|
||||
"L+ ${cfg.statePath}/config/database.yml - - - - ${pkgs.writeText "database.yml" (builtins.toJSON databaseConfig)}"
|
||||
"L+ ${cfg.statePath}/config/secrets.yml - - - - ${pkgs.writeText "secrets.yml" (builtins.toJSON secretsConfig)}"
|
||||
"L+ ${cfg.statePath}/config/unicorn.rb - - - - ${./defaultUnicornConfig.rb}"
|
||||
|
||||
"L+ ${cfg.statePath}/config/initializers/extra-gitlab.rb - - - - ${extraGitlabRb}"
|
||||
] ++ optional cfg.smtp.enable
|
||||
"L+ ${cfg.statePath}/config/initializers/smtp_settings.rb - - - - ${smtpSettings}" ;
|
||||
|
||||
systemd.services.gitlab-sidekiq = {
|
||||
after = [ "network.target" "redis.service" "gitlab.service" ];
|
||||
|
@ -570,6 +586,7 @@ in {
|
|||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [
|
||||
exiftool
|
||||
gitAndTools.git
|
||||
gnutar
|
||||
gzip
|
||||
|
@ -609,40 +626,14 @@ in {
|
|||
gnupg
|
||||
];
|
||||
preStart = ''
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/db/* ${cfg.statePath}/db
|
||||
rm -rf ${cfg.statePath}/config
|
||||
mkdir ${cfg.statePath}/config
|
||||
if [ -e ${cfg.statePath}/lib ]; then
|
||||
rm ${cfg.statePath}/lib
|
||||
fi
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} cp -f ${cfg.packages.gitlab}/share/gitlab/VERSION ${cfg.statePath}/VERSION
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} rm -rf ${cfg.statePath}/db/*
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} cp -rf --no-preserve=mode ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} cp -rf --no-preserve=mode ${cfg.packages.gitlab}/share/gitlab/db/* ${cfg.statePath}/db
|
||||
|
||||
ln -sf ${cfg.packages.gitlab}/share/gitlab/lib ${cfg.statePath}/lib
|
||||
[ -L /run/gitlab/config ] || ln -sf ${cfg.statePath}/config /run/gitlab/config
|
||||
[ -L /run/gitlab/log ] || ln -sf ${cfg.statePath}/log /run/gitlab/log
|
||||
[ -L /run/gitlab/tmp ] || ln -sf ${cfg.statePath}/tmp /run/gitlab/tmp
|
||||
[ -L /run/gitlab/uploads ] || ln -sf ${cfg.statePath}/uploads /run/gitlab/uploads
|
||||
cp ${cfg.packages.gitlab}/share/gitlab/VERSION ${cfg.statePath}/VERSION
|
||||
cp -rf ${cfg.packages.gitlab}/share/gitlab/config.dist/* ${cfg.statePath}/config
|
||||
ln -sf ${extraGitlabRb} ${cfg.statePath}/config/initializers/extra-gitlab.rb
|
||||
${optionalString cfg.smtp.enable ''
|
||||
ln -sf ${smtpSettings} ${cfg.statePath}/config/initializers/smtp_settings.rb
|
||||
''}
|
||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${cfg.statePath}/config/gitlab_shell_secret
|
||||
${pkgs.openssl}/bin/openssl rand -hex 32 > ${cfg.statePath}/gitlab_shell_secret
|
||||
|
||||
# JSON is a subset of YAML
|
||||
ln -sf ${pkgs.writeText "gitlab.yml" (builtins.toJSON gitlabConfig)} ${cfg.statePath}/config/gitlab.yml
|
||||
ln -sf ${pkgs.writeText "database.yml" (builtins.toJSON databaseConfig)} ${cfg.statePath}/config/database.yml
|
||||
ln -sf ${pkgs.writeText "secrets.yml" (builtins.toJSON secretsConfig)} ${cfg.statePath}/config/secrets.yml
|
||||
ln -sf ${./defaultUnicornConfig.rb} ${cfg.statePath}/config/unicorn.rb
|
||||
|
||||
# Install the shell required to push repositories
|
||||
ln -sf ${pkgs.writeText "config.yml" (builtins.toJSON gitlabShellConfig)} /run/gitlab/shell-config.yml
|
||||
[ -L ${cfg.statePath}/shell/hooks ] || ln -sf ${cfg.packages.gitlab-shell}/hooks ${cfg.statePath}/shell/hooks
|
||||
${cfg.packages.gitlab-shell}/bin/install
|
||||
|
||||
chown -R ${cfg.user}:${cfg.group} ${cfg.statePath}/
|
||||
chmod -R ug+rwX,o-rwx+X ${cfg.statePath}/
|
||||
chown -R ${cfg.user}:${cfg.group} /run/gitlab
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} ${cfg.packages.gitlab-shell}/bin/install
|
||||
|
||||
if ! test -e "${cfg.statePath}/db-created"; then
|
||||
if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
|
||||
|
@ -655,7 +646,7 @@ in {
|
|||
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake db:schema:load
|
||||
|
||||
touch "${cfg.statePath}/db-created"
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} touch "${cfg.statePath}/db-created"
|
||||
fi
|
||||
|
||||
# Always do the db migrations just to be sure the database is up-to-date
|
||||
|
@ -664,22 +655,13 @@ in {
|
|||
if ! test -e "${cfg.statePath}/db-seeded"; then
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} ${gitlab-rake}/bin/gitlab-rake db:seed_fu \
|
||||
GITLAB_ROOT_PASSWORD='${cfg.initialRootPassword}' GITLAB_ROOT_EMAIL='${cfg.initialRootEmail}'
|
||||
touch "${cfg.statePath}/db-seeded"
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} touch "${cfg.statePath}/db-seeded"
|
||||
fi
|
||||
|
||||
# The gitlab:shell:create_hooks task seems broken for fixing links
|
||||
# so we instead delete all the hooks and create them anew
|
||||
# We remove potentially broken links to old gitlab-shell versions
|
||||
rm -f ${cfg.statePath}/repositories/**/*.git/hooks
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${gitlab-rake}/bin/gitlab-rake gitlab:shell:create_hooks
|
||||
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} -H ${pkgs.git}/bin/git config --global core.autocrlf "input"
|
||||
|
||||
# Change permissions in the last step because some of the
|
||||
# intermediary scripts like to create directories as root.
|
||||
chmod -R u+rwX,go-rwx+X ${gitlabEnv.HOME}
|
||||
chmod -R ug+rwX,o-rwx ${cfg.statePath}/repositories
|
||||
chmod -R ug-s ${cfg.statePath}/repositories
|
||||
find ${cfg.statePath}/repositories -type d -print0 | xargs -0 chmod g+s
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
|
|
|
@ -143,21 +143,37 @@ in
|
|||
users.users.${cfg.user} = {
|
||||
description = "Gitolite user";
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.gitolite;
|
||||
group = cfg.group;
|
||||
useDefaultShell = true;
|
||||
};
|
||||
users.groups."${cfg.group}".gid = config.ids.gids.gitolite;
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} - -"
|
||||
"d '${cfg.dataDir}'/.gitolite - ${cfg.user} ${cfg.group} - -"
|
||||
"d '${cfg.dataDir}'/.gitolite/logs - ${cfg.user} ${cfg.group} - -"
|
||||
|
||||
"Z ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
|
||||
systemd.services."gitolite-init" = {
|
||||
description = "Gitolite initialization";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
unitConfig.RequiresMountsFor = cfg.dataDir;
|
||||
|
||||
serviceConfig.User = "${cfg.user}";
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
environment = {
|
||||
GITOLITE_RC = ".gitolite.rc";
|
||||
GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
WorkingDirectory = "~";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
|
||||
path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
|
||||
script =
|
||||
|
@ -187,11 +203,6 @@ in
|
|||
'';
|
||||
in
|
||||
''
|
||||
cd ${cfg.dataDir}
|
||||
mkdir -p .gitolite/logs
|
||||
|
||||
GITOLITE_RC=.gitolite.rc
|
||||
GITOLITE_RC_DEFAULT=${rcDir}/gitolite.rc.default
|
||||
if ( [[ ! -e "$GITOLITE_RC" ]] && [[ ! -L "$GITOLITE_RC" ]] ) ||
|
||||
( [[ -f "$GITOLITE_RC" ]] && diff -q "$GITOLITE_RC" "$GITOLITE_RC_DEFAULT" >/dev/null ) ||
|
||||
( [[ -L "$GITOLITE_RC" ]] && [[ "$(readlink "$GITOLITE_RC")" =~ ^/nix/store/ ]] )
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.greenclip;
|
||||
in {
|
||||
|
||||
options.services.greenclip = {
|
||||
enable = mkEnableOption "Greenclip daemon";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.haskellPackages.greenclip;
|
||||
defaultText = "pkgs.haskellPackages.greenclip";
|
||||
description = "greenclip derivation to use.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.user.services.greenclip = {
|
||||
enable = true;
|
||||
description = "greenclip daemon";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
after = [ "graphical-session.target" ];
|
||||
serviceConfig.ExecStart = "${cfg.package}/bin/greenclip daemon";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
};
|
||||
}
|
|
@ -467,7 +467,7 @@ in
|
|||
fi
|
||||
'';
|
||||
|
||||
nix.nrBuildUsers = mkDefault (lib.max 32 cfg.maxJobs);
|
||||
nix.nrBuildUsers = mkDefault (lib.max 32 (if cfg.maxJobs == "auto" then 0 else cfg.maxJobs));
|
||||
|
||||
users.users = nixbldUsers;
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (lib) mkDefault mkEnableOption mkIf mkOption types;
|
||||
inherit (lib) concatStringsSep literalExample mapAttrsToList;
|
||||
inherit (lib) optional optionalAttrs optionalString singleton versionAtLeast;
|
||||
|
||||
cfg = config.services.redmine;
|
||||
|
||||
bundle = "${cfg.package}/share/redmine/bin/bundle";
|
||||
|
@ -11,11 +13,11 @@ let
|
|||
production:
|
||||
adapter: ${cfg.database.type}
|
||||
database: ${cfg.database.name}
|
||||
host: ${cfg.database.host}
|
||||
host: ${if (cfg.database.type == "postgresql" && cfg.database.socket != null) then cfg.database.socket else cfg.database.host}
|
||||
port: ${toString cfg.database.port}
|
||||
username: ${cfg.database.user}
|
||||
password: #dbpass#
|
||||
${optionalString (cfg.database.socket != null) "socket: ${cfg.database.socket}"}
|
||||
${optionalString (cfg.database.type == "mysql2" && cfg.database.socket != null) "socket: ${cfg.database.socket}"}
|
||||
'';
|
||||
|
||||
configurationYml = pkgs.writeText "configuration.yml" ''
|
||||
|
@ -50,16 +52,15 @@ let
|
|||
'';
|
||||
});
|
||||
|
||||
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql2";
|
||||
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "postgresql";
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
services.redmine = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Enable the Redmine service.";
|
||||
};
|
||||
enable = mkEnableOption "Redmine";
|
||||
|
||||
# default to the 4.x series not forcing major version upgrade of those on the 3.x series
|
||||
package = mkOption {
|
||||
|
@ -107,7 +108,8 @@ in
|
|||
description = ''
|
||||
Extra configuration in configuration.yml.
|
||||
|
||||
See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
|
||||
See <link xlink:href="https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration"/>
|
||||
for details.
|
||||
'';
|
||||
example = literalExample ''
|
||||
email_delivery:
|
||||
|
@ -124,7 +126,8 @@ in
|
|||
description = ''
|
||||
Extra configuration in additional_environment.rb.
|
||||
|
||||
See https://svn.redmine.org/redmine/trunk/config/additional_environment.rb.example
|
||||
See <link xlink:href="https://svn.redmine.org/redmine/trunk/config/additional_environment.rb.example"/>
|
||||
for details.
|
||||
'';
|
||||
example = literalExample ''
|
||||
config.logger.level = Logger::DEBUG
|
||||
|
@ -169,13 +172,14 @@ in
|
|||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = (if cfg.database.socket != null then "localhost" else "127.0.0.1");
|
||||
default = "localhost";
|
||||
description = "Database host address.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 3306;
|
||||
default = if cfg.database.type == "postgresql" then 5432 else 3306;
|
||||
defaultText = "3306";
|
||||
description = "Database host port.";
|
||||
};
|
||||
|
||||
|
@ -213,10 +217,20 @@ in
|
|||
|
||||
socket = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
default =
|
||||
if mysqlLocal then "/run/mysqld/mysqld.sock"
|
||||
else if pgsqlLocal then "/run/postgresql"
|
||||
else null;
|
||||
defaultText = "/run/mysqld/mysqld.sock";
|
||||
example = "/run/mysqld/mysqld.sock";
|
||||
description = "Path to the unix socket file to use for authentication.";
|
||||
};
|
||||
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Create the database and database user locally.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -227,12 +241,37 @@ in
|
|||
{ assertion = cfg.database.passwordFile != null || cfg.database.password != "" || cfg.database.socket != null;
|
||||
message = "one of services.redmine.database.socket, services.redmine.database.passwordFile, or services.redmine.database.password must be set";
|
||||
}
|
||||
{ assertion = cfg.database.socket != null -> (cfg.database.type == "mysql2");
|
||||
message = "Socket authentication is only available for the mysql2 database type";
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.user == cfg.user;
|
||||
message = "services.redmine.database.user must be set to ${cfg.user} if services.redmine.database.createLocally is set true";
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.socket != null;
|
||||
message = "services.redmine.database.socket must be set if services.redmine.database.createLocally is set to true";
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.host == "localhost";
|
||||
message = "services.redmine.database.host must be set to localhost if services.redmine.database.createLocally is set to true";
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
services.mysql = mkIf mysqlLocal {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{ name = cfg.database.user;
|
||||
ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.postgresql = mkIf pgsqlLocal {
|
||||
enable = true;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{ name = cfg.database.user;
|
||||
ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# create symlinks for the basic directory layout the redmine package expects
|
||||
systemd.tmpfiles.rules = [
|
||||
|
@ -259,7 +298,7 @@ in
|
|||
];
|
||||
|
||||
systemd.services.redmine = {
|
||||
after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
|
||||
after = [ "network.target" ] ++ optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.RAILS_ENV = "production";
|
||||
environment.RAILS_CACHE = "${cfg.stateDir}/cache";
|
||||
|
|
|
@ -411,7 +411,7 @@ in {
|
|||
} else {
|
||||
cert = "${cfg.pki.manual.server.cert}";
|
||||
key = "${cfg.pki.manual.server.key}";
|
||||
crl = "${cfg.pki.manual.server.crl}";
|
||||
${mapNullable (_: "crl") cfg.pki.manual.server.crl} = "${cfg.pki.manual.server.crl}";
|
||||
});
|
||||
|
||||
ca.cert = if needToCreateCA then "${cfg.dataDir}/keys/ca.cert"
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.tiddlywiki;
|
||||
listenParams = concatStrings (mapAttrsToList (n: v: " '${n}=${toString v}' ") cfg.listenOptions);
|
||||
exe = "${pkgs.nodePackages.tiddlywiki}/lib/node_modules/.bin/tiddlywiki";
|
||||
name = "tiddlywiki";
|
||||
dataDir = "/var/lib/" + name;
|
||||
|
||||
in {
|
||||
|
||||
options.services.tiddlywiki = {
|
||||
|
||||
enable = mkEnableOption "TiddlyWiki nodejs server";
|
||||
|
||||
listenOptions = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
example = {
|
||||
credentials = "../credentials.csv";
|
||||
readers="(authenticated)";
|
||||
port = 3456;
|
||||
};
|
||||
description = ''
|
||||
Parameters passed to <literal>--listen</literal> command.
|
||||
Refer to <link xlink:href="https://tiddlywiki.com/#WebServer"/>
|
||||
for details on supported values.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd = {
|
||||
services.tiddlywiki = {
|
||||
description = "TiddlyWiki nodejs server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
DynamicUser = true;
|
||||
StateDirectory = name;
|
||||
ExecStartPre = "-${exe} ${dataDir} --init server";
|
||||
ExecStart = "${exe} ${dataDir} --listen ${listenParams}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -552,6 +552,8 @@ in {
|
|||
description = "Grafana user";
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
group = "grafana";
|
||||
};
|
||||
users.groups.grafana = {};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
{ config, pkgs, lib, options, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) concatStrings foldl foldl' genAttrs literalExample maintainers
|
||||
mapAttrsToList mkDefault mkEnableOption mkIf mkMerge mkOption
|
||||
optional types;
|
||||
|
||||
cfg = config.services.prometheus.exporters;
|
||||
|
||||
# each attribute in `exporterOpts` is expected to have specified:
|
||||
|
@ -17,25 +19,30 @@ let
|
|||
# Note that `extraOpts` is optional, but a script for the exporter's
|
||||
# systemd service must be provided by specifying either
|
||||
# `serviceOpts.script` or `serviceOpts.serviceConfig.ExecStart`
|
||||
exporterOpts = {
|
||||
blackbox = import ./exporters/blackbox.nix { inherit config lib pkgs; };
|
||||
collectd = import ./exporters/collectd.nix { inherit config lib pkgs; };
|
||||
dnsmasq = import ./exporters/dnsmasq.nix { inherit config lib pkgs; };
|
||||
dovecot = import ./exporters/dovecot.nix { inherit config lib pkgs; };
|
||||
fritzbox = import ./exporters/fritzbox.nix { inherit config lib pkgs; };
|
||||
json = import ./exporters/json.nix { inherit config lib pkgs; };
|
||||
minio = import ./exporters/minio.nix { inherit config lib pkgs; };
|
||||
nginx = import ./exporters/nginx.nix { inherit config lib pkgs; };
|
||||
node = import ./exporters/node.nix { inherit config lib pkgs; };
|
||||
postfix = import ./exporters/postfix.nix { inherit config lib pkgs; };
|
||||
snmp = import ./exporters/snmp.nix { inherit config lib pkgs; };
|
||||
surfboard = import ./exporters/surfboard.nix { inherit config lib pkgs; };
|
||||
tor = import ./exporters/tor.nix { inherit config lib pkgs; };
|
||||
unifi = import ./exporters/unifi.nix { inherit config lib pkgs; };
|
||||
varnish = import ./exporters/varnish.nix { inherit config lib pkgs; };
|
||||
bind = import ./exporters/bind.nix { inherit config lib pkgs; };
|
||||
wireguard = import ./exporters/wireguard.nix { inherit config lib pkgs; };
|
||||
};
|
||||
|
||||
exporterOpts = genAttrs [
|
||||
"bind"
|
||||
"blackbox"
|
||||
"collectd"
|
||||
"dnsmasq"
|
||||
"dovecot"
|
||||
"fritzbox"
|
||||
"json"
|
||||
"mail"
|
||||
"minio"
|
||||
"nginx"
|
||||
"node"
|
||||
"postfix"
|
||||
"postgres"
|
||||
"snmp"
|
||||
"surfboard"
|
||||
"tor"
|
||||
"unifi"
|
||||
"varnish"
|
||||
"wireguard"
|
||||
] (name:
|
||||
import (./. + "/exporters/${name}.nix") { inherit config lib pkgs options; }
|
||||
);
|
||||
|
||||
mkExporterOpts = ({ name, port }: {
|
||||
enable = mkEnableOption "the prometheus ${name} exporter";
|
||||
|
@ -81,7 +88,7 @@ let
|
|||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
default = "${name}-exporter";
|
||||
description = ''
|
||||
User name under which the ${name} exporter shall be run.
|
||||
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
|
||||
|
@ -89,7 +96,7 @@ let
|
|||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
default = "${name}-exporter";
|
||||
description = ''
|
||||
Group under which the ${name} exporter shall be run.
|
||||
Has no effect when <option>systemd.services.prometheus-${name}-exporter.serviceConfig.DynamicUser</option> is true.
|
||||
|
@ -97,9 +104,10 @@ let
|
|||
};
|
||||
});
|
||||
|
||||
mkSubModule = { name, port, extraOpts, ... }: {
|
||||
mkSubModule = { name, port, extraOpts, imports }: {
|
||||
${name} = mkOption {
|
||||
type = types.submodule {
|
||||
inherit imports;
|
||||
options = (mkExporterOpts {
|
||||
inherit name port;
|
||||
} // extraOpts);
|
||||
|
@ -112,13 +120,30 @@ let
|
|||
mkSubModules = (foldl' (a: b: a//b) {}
|
||||
(mapAttrsToList (name: opts: mkSubModule {
|
||||
inherit name;
|
||||
inherit (opts) port serviceOpts;
|
||||
inherit (opts) port;
|
||||
extraOpts = opts.extraOpts or {};
|
||||
imports = opts.imports or [];
|
||||
}) exporterOpts)
|
||||
);
|
||||
|
||||
mkExporterConf = { name, conf, serviceOpts }:
|
||||
let
|
||||
enableDynamicUser = serviceOpts.serviceConfig.DynamicUser or true;
|
||||
in
|
||||
mkIf conf.enable {
|
||||
warnings = conf.warnings or [];
|
||||
users.users = (mkIf (conf.user == "${name}-exporter" && !enableDynamicUser) {
|
||||
"${name}-exporter" = {
|
||||
description = ''
|
||||
Prometheus ${name} exporter service user
|
||||
'';
|
||||
isSystemUser = true;
|
||||
inherit (conf) group;
|
||||
};
|
||||
});
|
||||
users.groups = (mkIf (conf.group == "${name}-exporter" && !enableDynamicUser) {
|
||||
"${name}-exporter" = {};
|
||||
});
|
||||
networking.firewall.extraCommands = mkIf conf.openFirewall (concatStrings [
|
||||
"ip46tables -A nixos-fw ${conf.firewallFilter} "
|
||||
"-m comment --comment ${name}-exporter -j nixos-fw-accept"
|
||||
|
@ -129,7 +154,8 @@ let
|
|||
serviceConfig.Restart = mkDefault "always";
|
||||
serviceConfig.PrivateTmp = mkDefault true;
|
||||
serviceConfig.WorkingDirectory = mkDefault /tmp;
|
||||
} serviceOpts ] ++ optional (!(serviceOpts.serviceConfig.DynamicUser or false)) {
|
||||
serviceConfig.DynamicUser = mkDefault enableDynamicUser;
|
||||
} serviceOpts ] ++ optional (!enableDynamicUser) {
|
||||
serviceConfig.User = conf.user;
|
||||
serviceConfig.Group = conf.group;
|
||||
});
|
||||
|
@ -154,13 +180,19 @@ in
|
|||
};
|
||||
|
||||
config = mkMerge ([{
|
||||
assertions = [{
|
||||
assertions = [ {
|
||||
assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
|
||||
message = ''
|
||||
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
|
||||
or `services.prometheus.exporters.snmp.configurationPath' set!
|
||||
'';
|
||||
}];
|
||||
} {
|
||||
assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {});
|
||||
message = ''
|
||||
Please specify either 'services.prometheus.exporters.mail.configuration'
|
||||
or 'services.prometheus.exporters.mail.configFile'.
|
||||
'';
|
||||
} ];
|
||||
}] ++ [(mkIf config.services.minio.enable {
|
||||
services.prometheus.exporters.minio.minioAddress = mkDefault "http://localhost:9000";
|
||||
services.prometheus.exporters.minio.minioAccessKey = mkDefault config.services.minio.accessKey;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
exporter</link>, it provides hardware and OS metrics from the host it's
|
||||
running on. The exporter could be configured as follows:
|
||||
<programlisting>
|
||||
services.promtheus.exporters.node = {
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
enabledCollectors = [
|
||||
"logind"
|
||||
|
@ -113,7 +113,7 @@
|
|||
specific options and configuration:
|
||||
<programlisting>
|
||||
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -159,8 +159,10 @@ in
|
|||
# `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
|
||||
# has to be specified here. This will be merged with the default
|
||||
# service confiuration.
|
||||
# Note that by default 'DynamicUser' is 'true'.
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
@ -184,4 +186,42 @@ in
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="module-services-prometheus-exporters-update-exporter-module">
|
||||
<title>Updating an exporter module</title>
|
||||
<para>
|
||||
Should an exporter option change at some point, it is possible to add
|
||||
information about the change to the exporter definition similar to
|
||||
<literal>nixpkgs/nixos/modules/rename.nix</literal>:
|
||||
<programlisting>
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.nginx;
|
||||
in
|
||||
{
|
||||
port = 9113;
|
||||
extraOpts = {
|
||||
# additional module options
|
||||
# ...
|
||||
};
|
||||
serviceOpts = {
|
||||
# service configuration
|
||||
# ...
|
||||
};
|
||||
imports = [
|
||||
# 'services.prometheus.exporters.nginx.telemetryEndpoint' -> 'services.prometheus.exporters.nginx.telemetryPath'
|
||||
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
|
||||
|
||||
# removed option 'services.prometheus.exporters.nginx.insecure'
|
||||
(mkRemovedOptionModule [ "insecure" ] ''
|
||||
This option was replaced by 'prometheus.exporters.nginx.sslVerify' which defaults to true.
|
||||
'')
|
||||
({ options.warnings = options.warnings; })
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -39,7 +39,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-bind-exporter}/bin/bind_exporter \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -18,7 +18,6 @@ in
|
|||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
AmbientCapabilities = [ "CAP_NET_RAW" ]; # for ping probes
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -64,7 +64,6 @@ in
|
|||
'' else "";
|
||||
in {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
|
||||
-log.format ${cfg.logFormat} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -26,7 +26,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \
|
||||
--listen ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -39,8 +39,8 @@ in
|
|||
mail_plugins = $mail_plugins old_stats
|
||||
service old-stats {
|
||||
unix_listener old-stats {
|
||||
user = nobody
|
||||
group = nobody
|
||||
user = dovecot-exporter
|
||||
group = dovecot-exporter
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
@ -59,6 +59,7 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -26,7 +26,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-fritzbox-exporter}/bin/exporter \
|
||||
-listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -24,7 +24,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
|
||||
--port ${toString cfg.port} \
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.mail;
|
||||
|
||||
configurationFile = pkgs.writeText "prometheus-mail-exporter.conf" (builtins.toJSON (
|
||||
# removes the _module attribute, null values and converts attrNames to lowercase
|
||||
mapAttrs' (name: value:
|
||||
if name == "servers"
|
||||
then nameValuePair (toLower name)
|
||||
((map (srv: (mapAttrs' (n: v: nameValuePair (toLower n) v)
|
||||
(filterAttrs (n: v: !(n == "_module" || v == null)) srv)
|
||||
))) value)
|
||||
else nameValuePair (toLower name) value
|
||||
) (filterAttrs (n: _: !(n == "_module")) cfg.configuration)
|
||||
));
|
||||
|
||||
serverOptions.options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Value for label 'configname' which will be added to all metrics.
|
||||
'';
|
||||
};
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Hostname of the server that should be probed.
|
||||
'';
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
example = 587;
|
||||
description = ''
|
||||
Port to use for SMTP.
|
||||
'';
|
||||
};
|
||||
from = mkOption {
|
||||
type = types.str;
|
||||
example = "exporteruser@domain.tld";
|
||||
description = ''
|
||||
Content of 'From' Header for probing mails.
|
||||
'';
|
||||
};
|
||||
to = mkOption {
|
||||
type = types.str;
|
||||
example = "exporteruser@domain.tld";
|
||||
description = ''
|
||||
Content of 'To' Header for probing mails.
|
||||
'';
|
||||
};
|
||||
detectionDir = mkOption {
|
||||
type = types.path;
|
||||
example = "/var/spool/mail/exporteruser/new";
|
||||
description = ''
|
||||
Directory in which new mails for the exporter user are placed.
|
||||
Note that this needs to exist when the exporter starts.
|
||||
'';
|
||||
};
|
||||
login = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "exporteruser@domain.tld";
|
||||
description = ''
|
||||
Username to use for SMTP authentication.
|
||||
'';
|
||||
};
|
||||
passphrase = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Password to use for SMTP authentication.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
exporterOptions.options = {
|
||||
monitoringInterval = mkOption {
|
||||
type = types.str;
|
||||
example = "10s";
|
||||
description = ''
|
||||
Time interval between two probe attempts.
|
||||
'';
|
||||
};
|
||||
mailCheckTimeout = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Timeout until mails are considered "didn't make it".
|
||||
'';
|
||||
};
|
||||
disableFileDelition = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Disables the exporter's function to delete probing mails.
|
||||
'';
|
||||
};
|
||||
servers = mkOption {
|
||||
type = types.listOf (types.submodule serverOptions);
|
||||
default = [];
|
||||
example = literalExample ''
|
||||
[ {
|
||||
name = "testserver";
|
||||
server = "smtp.domain.tld";
|
||||
port = 587;
|
||||
from = "exporteruser@domain.tld";
|
||||
to = "exporteruser@domain.tld";
|
||||
detectionDir = "/path/to/Maildir/new";
|
||||
} ]
|
||||
'';
|
||||
description = ''
|
||||
List of servers that should be probed.
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
port = 9225;
|
||||
extraOpts = {
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
Specify the mailexporter configuration file to use.
|
||||
'';
|
||||
};
|
||||
configuration = mkOption {
|
||||
type = types.submodule exporterOptions;
|
||||
default = {};
|
||||
description = ''
|
||||
Specify the mailexporter configuration file to use.
|
||||
'';
|
||||
};
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-mail-exporter}/bin/mailexporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--config.file ${
|
||||
if cfg.configuration != {} then configurationFile else cfg.configFile
|
||||
} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -50,7 +50,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
|
||||
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -16,32 +16,39 @@ in
|
|||
Can be enabled with services.nginx.statusPage = true.
|
||||
'';
|
||||
};
|
||||
telemetryEndpoint = mkOption {
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
insecure = mkOption {
|
||||
sslVerify = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Ignore server certificate if using https.
|
||||
Whether to perform certificate verification for https.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-nginx-exporter}/bin/nginx_exporter \
|
||||
--nginx.scrape_uri '${cfg.scrapeUri}' \
|
||||
--telemetry.address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--telemetry.endpoint ${cfg.telemetryEndpoint} \
|
||||
--insecure ${toString cfg.insecure} \
|
||||
${pkgs.prometheus-nginx-exporter}/bin/nginx-prometheus-exporter \
|
||||
--nginx.scrape-uri '${cfg.scrapeUri}' \
|
||||
--nginx.ssl-verify ${toString cfg.sslVerify} \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--web.telemetry-path ${cfg.telemetryPath} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "telemetryEndpoint" ] [ "telemetryPath" ])
|
||||
(mkRemovedOptionModule [ "insecure" ] ''
|
||||
This option was replaced by 'prometheus.exporters.nginx.sslVerify'.
|
||||
'')
|
||||
({ options.warnings = options.warnings; })
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -27,6 +27,7 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
RuntimeDirectory = "prometheus-node-exporter";
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-node-exporter}/bin/node_exporter \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -62,6 +62,7 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.postgres;
|
||||
in
|
||||
{
|
||||
port = 9187;
|
||||
extraOpts = {
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
dataSourceName = mkOption {
|
||||
type = types.str;
|
||||
default = "user=postgres database=postgres host=/run/postgresql sslmode=disable";
|
||||
example = "postgresql://username:password@localhost:5432/postgres?sslmode=disable";
|
||||
description = ''
|
||||
Accepts PostgreSQL URI form and key=value form arguments.
|
||||
'';
|
||||
};
|
||||
runAsLocalSuperUser = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to run the exporter as the local 'postgres' super user.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
environment.DATA_SOURCE_NAME = cfg.dataSourceName;
|
||||
serviceConfig = {
|
||||
DynamicUser = false;
|
||||
User = mkIf cfg.runAsLocalSuperUser (mkForce "postgres");
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-postgres-exporter}/bin/postgres_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--web.telemetry-path ${cfg.telemetryPath} \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -57,7 +57,6 @@ in
|
|||
else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
|
||||
in {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
|
||||
--config.file=${configFile} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -20,7 +20,6 @@ in
|
|||
description = "Prometheus exporter for surfboard cable modem";
|
||||
unitConfig.Documentation = "https://github.com/ipstatic/surfboard_exporter";
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-surfboard-exporter}/bin/surfboard_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -26,7 +26,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-tor-exporter}/bin/prometheus-tor-exporter \
|
||||
-b ${cfg.listenAddress} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -51,7 +51,6 @@ in
|
|||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
|
||||
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -68,8 +68,8 @@ in
|
|||
serviceOpts = {
|
||||
path = [ pkgs.varnish ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
RestartSec = mkDefault 1;
|
||||
DynamicUser = false;
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs }:
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -23,20 +23,30 @@ in {
|
|||
to set the peers up.
|
||||
'';
|
||||
};
|
||||
|
||||
singleSubnetPerField = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
By default, all allowed IPs and subnets are comma-separated in the
|
||||
<literal>allowed_ips</literal> field. With this option enabled,
|
||||
a single IP and subnet will be listed in fields like <literal>allowed_ip_0</literal>,
|
||||
<literal>allowed_ip_1</literal> and so on.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
script = ''
|
||||
${pkgs.prometheus-wireguard-exporter}/bin/prometheus_wireguard_exporter \
|
||||
-p ${toString cfg.port} \
|
||||
${optionalString cfg.verbose "-v"} \
|
||||
${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"}
|
||||
'';
|
||||
|
||||
path = [ pkgs.wireguard-tools ];
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-wireguard-exporter}/bin/prometheus_wireguard_exporter \
|
||||
-p ${toString cfg.port} \
|
||||
${optionalString cfg.verbose "-v"} \
|
||||
${optionalString cfg.singleSubnetPerField "-s"} \
|
||||
${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,801 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.thanos;
|
||||
|
||||
nullOpt = type: description: mkOption {
|
||||
type = types.nullOr type;
|
||||
default = null;
|
||||
inherit description;
|
||||
};
|
||||
|
||||
optionToArgs = opt: v : optional (v != null) ''--${opt}="${toString v}"'';
|
||||
flagToArgs = opt: v : optional v ''--${opt}'';
|
||||
listToArgs = opt: vs : map (v: ''--${opt}="${v}"'') vs;
|
||||
attrsToArgs = opt: kvs: mapAttrsToList (k: v: ''--${opt}=${k}=\"${v}\"'') kvs;
|
||||
|
||||
mkParamDef = type: default: description: mkParam type (description + ''
|
||||
|
||||
Defaults to <literal>${toString default}</literal> in Thanos
|
||||
when set to <literal>null</literal>.
|
||||
'');
|
||||
|
||||
mkParam = type: description: {
|
||||
toArgs = optionToArgs;
|
||||
option = nullOpt type description;
|
||||
};
|
||||
|
||||
mkFlagParam = description: {
|
||||
toArgs = flagToArgs;
|
||||
option = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
inherit description;
|
||||
};
|
||||
};
|
||||
|
||||
mkListParam = opt: description: {
|
||||
toArgs = _opt: listToArgs opt;
|
||||
option = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
inherit description;
|
||||
};
|
||||
};
|
||||
|
||||
mkAttrsParam = opt: description: {
|
||||
toArgs = _opt: attrsToArgs opt;
|
||||
option = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
inherit description;
|
||||
};
|
||||
};
|
||||
|
||||
mkStateDirParam = opt: default: description: {
|
||||
toArgs = _opt: stateDir: optionToArgs opt "/var/lib/${stateDir}";
|
||||
option = mkOption {
|
||||
type = types.str;
|
||||
inherit default;
|
||||
inherit description;
|
||||
};
|
||||
};
|
||||
|
||||
toYAML = name: attrs: pkgs.runCommandNoCC name {
|
||||
preferLocalBuild = true;
|
||||
json = builtins.toFile "${name}.json" (builtins.toJSON attrs);
|
||||
nativeBuildInputs = [ pkgs.remarshal ];
|
||||
} ''json2yaml -i $json -o $out'';
|
||||
|
||||
thanos = cmd: "${cfg.package}/bin/thanos ${cmd}" +
|
||||
(let args = cfg."${cmd}".arguments;
|
||||
in optionalString (length args != 0) (" \\\n " +
|
||||
concatStringsSep " \\\n " args));
|
||||
|
||||
argumentsOf = cmd: concatLists (collect isList
|
||||
(flip mapParamsRecursive params."${cmd}" (path: param:
|
||||
let opt = concatStringsSep "." path;
|
||||
v = getAttrFromPath path cfg."${cmd}";
|
||||
in param.toArgs opt v)));
|
||||
|
||||
mkArgumentsOption = cmd: mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = argumentsOf cmd;
|
||||
description = ''
|
||||
Arguments to the <literal>thanos ${cmd}</literal> command.
|
||||
|
||||
Defaults to a list of arguments formed by converting the structured
|
||||
options of <option>services.thanos.${cmd}</option> to a list of arguments.
|
||||
|
||||
Overriding this option will cause none of the structured options to have
|
||||
any effect. So only set this if you know what you're doing!
|
||||
'';
|
||||
};
|
||||
|
||||
mapParamsRecursive =
|
||||
let noParam = attr: !(attr ? "toArgs" && attr ? "option");
|
||||
in mapAttrsRecursiveCond noParam;
|
||||
|
||||
paramsToOptions = mapParamsRecursive (_path: param: param.option);
|
||||
|
||||
params = {
|
||||
|
||||
log = {
|
||||
|
||||
log.level = mkParamDef (types.enum ["debug" "info" "warn" "error" "fatal"]) "info" ''
|
||||
Log filtering level.
|
||||
'';
|
||||
|
||||
log.format = mkParam types.str ''
|
||||
Log format to use.
|
||||
'';
|
||||
};
|
||||
|
||||
tracing = cfg: {
|
||||
tracing.config-file = {
|
||||
toArgs = _opt: path: optionToArgs "tracing.config-file" path;
|
||||
option = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = if cfg.tracing.config == null then null
|
||||
else toString (toYAML "tracing.yaml" cfg.tracing.config);
|
||||
defaultText = ''
|
||||
if config.services.thanos.<cmd>.tracing.config == null then null
|
||||
else toString (toYAML "tracing.yaml" config.services.thanos.<cmd>.tracing.config);
|
||||
'';
|
||||
description = ''
|
||||
Path to YAML file that contains tracing configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
tracing.config =
|
||||
{
|
||||
toArgs = _opt: _attrs: [];
|
||||
option = nullOpt types.attrs ''
|
||||
Tracing configuration.
|
||||
|
||||
When not <literal>null</literal> the attribute set gets converted to
|
||||
a YAML file and stored in the Nix store. The option
|
||||
<option>tracing.config-file</option> will default to its path.
|
||||
|
||||
If <option>tracing.config-file</option> is set this option has no effect.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
common = cfg: params.log // params.tracing cfg // {
|
||||
|
||||
http-address = mkParamDef types.str "0.0.0.0:10902" ''
|
||||
Listen <literal>host:port</literal> for HTTP endpoints.
|
||||
'';
|
||||
|
||||
grpc-address = mkParamDef types.str "0.0.0.0:10901" ''
|
||||
Listen <literal>ip:port</literal> address for gRPC endpoints (StoreAPI).
|
||||
|
||||
Make sure this address is routable from other components.
|
||||
'';
|
||||
|
||||
grpc-server-tls-cert = mkParam types.str ''
|
||||
TLS Certificate for gRPC server, leave blank to disable TLS
|
||||
'';
|
||||
|
||||
grpc-server-tls-key = mkParam types.str ''
|
||||
TLS Key for the gRPC server, leave blank to disable TLS
|
||||
'';
|
||||
|
||||
grpc-server-tls-client-ca = mkParam types.str ''
|
||||
TLS CA to verify clients against.
|
||||
|
||||
If no client CA is specified, there is no client verification on server side.
|
||||
(tls.NoClientCert)
|
||||
'';
|
||||
};
|
||||
|
||||
objstore = cfg: {
|
||||
|
||||
objstore.config-file = {
|
||||
toArgs = _opt: path: optionToArgs "objstore.config-file" path;
|
||||
option = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = if cfg.objstore.config == null then null
|
||||
else toString (toYAML "objstore.yaml" cfg.objstore.config);
|
||||
defaultText = ''
|
||||
if config.services.thanos.<cmd>.objstore.config == null then null
|
||||
else toString (toYAML "objstore.yaml" config.services.thanos.<cmd>.objstore.config);
|
||||
'';
|
||||
description = ''
|
||||
Path to YAML file that contains object store configuration.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
objstore.config =
|
||||
{
|
||||
toArgs = _opt: _attrs: [];
|
||||
option = nullOpt types.attrs ''
|
||||
Object store configuration.
|
||||
|
||||
When not <literal>null</literal> the attribute set gets converted to
|
||||
a YAML file and stored in the Nix store. The option
|
||||
<option>objstore.config-file</option> will default to its path.
|
||||
|
||||
If <option>objstore.config-file</option> is set this option has no effect.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sidecar = params.common cfg.sidecar // params.objstore cfg.sidecar // {
|
||||
|
||||
prometheus.url = mkParamDef types.str "http://localhost:9090" ''
|
||||
URL at which to reach Prometheus's API.
|
||||
|
||||
For better performance use local network.
|
||||
'';
|
||||
|
||||
tsdb.path = {
|
||||
toArgs = optionToArgs;
|
||||
option = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/${config.services.prometheus2.stateDir}/data";
|
||||
defaultText = "/var/lib/\${config.services.prometheus2.stateDir}/data";
|
||||
description = ''
|
||||
Data directory of TSDB.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
reloader.config-file = mkParam types.str ''
|
||||
Config file watched by the reloader.
|
||||
'';
|
||||
|
||||
reloader.config-envsubst-file = mkParam types.str ''
|
||||
Output file for environment variable substituted config file.
|
||||
'';
|
||||
|
||||
reloader.rule-dirs = mkListParam "reloader.rule-dir" ''
|
||||
Rule directories for the reloader to refresh.
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
store = params.common cfg.store // params.objstore cfg.store // {
|
||||
|
||||
stateDir = mkStateDirParam "data-dir" "thanos-store" ''
|
||||
Data directory relative to <literal>/var/lib</literal>
|
||||
in which to cache remote blocks.
|
||||
'';
|
||||
|
||||
index-cache-size = mkParamDef types.str "250MB" ''
|
||||
Maximum size of items held in the index cache.
|
||||
'';
|
||||
|
||||
chunk-pool-size = mkParamDef types.str "2GB" ''
|
||||
Maximum size of concurrently allocatable bytes for chunks.
|
||||
'';
|
||||
|
||||
store.grpc.series-sample-limit = mkParamDef types.int 0 ''
|
||||
Maximum amount of samples returned via a single Series call.
|
||||
|
||||
<literal>0</literal> means no limit.
|
||||
|
||||
NOTE: for efficiency we take 120 as the number of samples in chunk (it
|
||||
cannot be bigger than that), so the actual number of samples might be
|
||||
lower, even though the maximum could be hit.
|
||||
'';
|
||||
|
||||
store.grpc.series-max-concurrency = mkParamDef types.int 20 ''
|
||||
Maximum number of concurrent Series calls.
|
||||
'';
|
||||
|
||||
sync-block-duration = mkParamDef types.str "3m" ''
|
||||
Repeat interval for syncing the blocks between local and remote view.
|
||||
'';
|
||||
|
||||
block-sync-concurrency = mkParamDef types.int 20 ''
|
||||
Number of goroutines to use when syncing blocks from object storage.
|
||||
'';
|
||||
};
|
||||
|
||||
query = params.common cfg.query // {
|
||||
|
||||
grpc-client-tls-secure = mkFlagParam ''
|
||||
Use TLS when talking to the gRPC server
|
||||
'';
|
||||
|
||||
grpc-client-tls-cert = mkParam types.str ''
|
||||
TLS Certificates to use to identify this client to the server
|
||||
'';
|
||||
|
||||
grpc-client-tls-key = mkParam types.str ''
|
||||
TLS Key for the client's certificate
|
||||
'';
|
||||
|
||||
grpc-client-tls-ca = mkParam types.str ''
|
||||
TLS CA Certificates to use to verify gRPC servers
|
||||
'';
|
||||
|
||||
grpc-client-server-name = mkParam types.str ''
|
||||
Server name to verify the hostname on the returned gRPC certificates.
|
||||
See <link xlink:href="https://tools.ietf.org/html/rfc4366#section-3.1"/>
|
||||
'';
|
||||
|
||||
web.route-prefix = mkParam types.str ''
|
||||
Prefix for API and UI endpoints.
|
||||
|
||||
This allows thanos UI to be served on a sub-path. This option is
|
||||
analogous to <option>web.route-prefix</option> of Promethus.
|
||||
'';
|
||||
|
||||
web.external-prefix = mkParam types.str ''
|
||||
Static prefix for all HTML links and redirect URLs in the UI query web
|
||||
interface.
|
||||
|
||||
Actual endpoints are still served on / or the
|
||||
<option>web.route-prefix</option>. This allows thanos UI to be served
|
||||
behind a reverse proxy that strips a URL sub-path.
|
||||
'';
|
||||
|
||||
web.prefix-header = mkParam types.str ''
|
||||
Name of HTTP request header used for dynamic prefixing of UI links and
|
||||
redirects.
|
||||
|
||||
This option is ignored if the option
|
||||
<literal>web.external-prefix</literal> is set.
|
||||
|
||||
Security risk: enable this option only if a reverse proxy in front of
|
||||
thanos is resetting the header.
|
||||
|
||||
The setting <literal>web.prefix-header="X-Forwarded-Prefix"</literal>
|
||||
can be useful, for example, if Thanos UI is served via Traefik reverse
|
||||
proxy with <literal>PathPrefixStrip</literal> option enabled, which
|
||||
sends the stripped prefix value in <literal>X-Forwarded-Prefix</literal>
|
||||
header. This allows thanos UI to be served on a sub-path.
|
||||
'';
|
||||
|
||||
query.timeout = mkParamDef types.str "2m" ''
|
||||
Maximum time to process query by query node.
|
||||
'';
|
||||
|
||||
query.max-concurrent = mkParamDef types.int 20 ''
|
||||
Maximum number of queries processed concurrently by query node.
|
||||
'';
|
||||
|
||||
query.replica-label = mkParam types.str ''
|
||||
Label to treat as a replica indicator along which data is
|
||||
deduplicated.
|
||||
|
||||
Still you will be able to query without deduplication using
|
||||
<literal>dedup=false</literal> parameter.
|
||||
'';
|
||||
|
||||
selector-labels = mkAttrsParam "selector-label" ''
|
||||
Query selector labels that will be exposed in info endpoint.
|
||||
'';
|
||||
|
||||
store.addresses = mkListParam "store" ''
|
||||
Addresses of statically configured store API servers.
|
||||
|
||||
The scheme may be prefixed with <literal>dns+</literal> or
|
||||
<literal>dnssrv+</literal> to detect store API servers through
|
||||
respective DNS lookups.
|
||||
'';
|
||||
|
||||
store.sd-files = mkListParam "store.sd-files" ''
|
||||
Path to files that contain addresses of store API servers. The path
|
||||
can be a glob pattern.
|
||||
'';
|
||||
|
||||
store.sd-interval = mkParamDef types.str "5m" ''
|
||||
Refresh interval to re-read file SD files. It is used as a resync fallback.
|
||||
'';
|
||||
|
||||
store.sd-dns-interval = mkParamDef types.str "30s" ''
|
||||
Interval between DNS resolutions.
|
||||
'';
|
||||
|
||||
store.unhealthy-timeout = mkParamDef types.str "5m" ''
|
||||
Timeout before an unhealthy store is cleaned from the store UI page.
|
||||
'';
|
||||
|
||||
query.auto-downsampling = mkFlagParam ''
|
||||
Enable automatic adjustment (step / 5) to what source of data should
|
||||
be used in store gateways if no
|
||||
<literal>max_source_resolution</literal> param is specified.
|
||||
'';
|
||||
|
||||
query.partial-response = mkFlagParam ''
|
||||
Enable partial response for queries if no
|
||||
<literal>partial_response</literal> param is specified.
|
||||
'';
|
||||
|
||||
query.default-evaluation-interval = mkParamDef types.str "1m" ''
|
||||
Set default evaluation interval for sub queries.
|
||||
'';
|
||||
|
||||
store.response-timeout = mkParamDef types.str "0ms" ''
|
||||
If a Store doesn't send any data in this specified duration then a
|
||||
Store will be ignored and partial data will be returned if it's
|
||||
enabled. <literal>0</literal> disables timeout.
|
||||
'';
|
||||
};
|
||||
|
||||
rule = params.common cfg.rule // params.objstore cfg.rule // {
|
||||
|
||||
labels = mkAttrsParam "label" ''
|
||||
Labels to be applied to all generated metrics.
|
||||
|
||||
Similar to external labels for Prometheus,
|
||||
used to identify ruler and its blocks as unique source.
|
||||
'';
|
||||
|
||||
stateDir = mkStateDirParam "data-dir" "thanos-rule" ''
|
||||
Data directory relative to <literal>/var/lib</literal>.
|
||||
'';
|
||||
|
||||
rule-files = mkListParam "rule-file" ''
|
||||
Rule files that should be used by rule manager. Can be in glob format.
|
||||
'';
|
||||
|
||||
eval-interval = mkParamDef types.str "30s" ''
|
||||
The default evaluation interval to use.
|
||||
'';
|
||||
|
||||
tsdb.block-duration = mkParamDef types.str "2h" ''
|
||||
Block duration for TSDB block.
|
||||
'';
|
||||
|
||||
tsdb.retention = mkParamDef types.str "48h" ''
|
||||
Block retention time on local disk.
|
||||
'';
|
||||
|
||||
alertmanagers.urls = mkListParam "alertmanagers.url" ''
|
||||
Alertmanager replica URLs to push firing alerts.
|
||||
|
||||
Ruler claims success if push to at least one alertmanager from
|
||||
discovered succeeds. The scheme may be prefixed with
|
||||
<literal>dns+</literal> or <literal>dnssrv+</literal> to detect
|
||||
Alertmanager IPs through respective DNS lookups. The port defaults to
|
||||
<literal>9093</literal> or the SRV record's value. The URL path is
|
||||
used as a prefix for the regular Alertmanager API path.
|
||||
'';
|
||||
|
||||
alertmanagers.send-timeout = mkParamDef types.str "10s" ''
|
||||
Timeout for sending alerts to alertmanager.
|
||||
'';
|
||||
|
||||
alert.query-url = mkParam types.str ''
|
||||
The external Thanos Query URL that would be set in all alerts 'Source' field.
|
||||
'';
|
||||
|
||||
alert.label-drop = mkListParam "alert.label-drop" ''
|
||||
Labels by name to drop before sending to alertmanager.
|
||||
|
||||
This allows alert to be deduplicated on replica label.
|
||||
|
||||
Similar Prometheus alert relabelling
|
||||
'';
|
||||
|
||||
web.route-prefix = mkParam types.str ''
|
||||
Prefix for API and UI endpoints.
|
||||
|
||||
This allows thanos UI to be served on a sub-path.
|
||||
|
||||
This option is analogous to <literal>--web.route-prefix</literal> of Promethus.
|
||||
'';
|
||||
|
||||
web.external-prefix = mkParam types.str ''
|
||||
Static prefix for all HTML links and redirect URLs in the UI query web
|
||||
interface.
|
||||
|
||||
Actual endpoints are still served on / or the
|
||||
<option>web.route-prefix</option>. This allows thanos UI to be served
|
||||
behind a reverse proxy that strips a URL sub-path.
|
||||
'';
|
||||
|
||||
web.prefix-header = mkParam types.str ''
|
||||
Name of HTTP request header used for dynamic prefixing of UI links and
|
||||
redirects.
|
||||
|
||||
This option is ignored if the option
|
||||
<option>web.external-prefix</option> is set.
|
||||
|
||||
Security risk: enable this option only if a reverse proxy in front of
|
||||
thanos is resetting the header.
|
||||
|
||||
The header <literal>X-Forwarded-Prefix</literal> can be useful, for
|
||||
example, if Thanos UI is served via Traefik reverse proxy with
|
||||
<literal>PathPrefixStrip</literal> option enabled, which sends the
|
||||
stripped prefix value in <literal>X-Forwarded-Prefix</literal>
|
||||
header. This allows thanos UI to be served on a sub-path.
|
||||
'';
|
||||
|
||||
query.addresses = mkListParam "query" ''
|
||||
Addresses of statically configured query API servers.
|
||||
|
||||
The scheme may be prefixed with <literal>dns+</literal> or
|
||||
<literal>dnssrv+</literal> to detect query API servers through
|
||||
respective DNS lookups.
|
||||
'';
|
||||
|
||||
query.sd-files = mkListParam "query.sd-files" ''
|
||||
Path to file that contain addresses of query peers.
|
||||
The path can be a glob pattern.
|
||||
'';
|
||||
|
||||
query.sd-interval = mkParamDef types.str "5m" ''
|
||||
Refresh interval to re-read file SD files. (used as a fallback)
|
||||
'';
|
||||
|
||||
query.sd-dns-interval = mkParamDef types.str "30s" ''
|
||||
Interval between DNS resolutions.
|
||||
'';
|
||||
};
|
||||
|
||||
compact = params.log // params.tracing cfg.compact // params.objstore cfg.compact // {
|
||||
|
||||
http-address = mkParamDef types.str "0.0.0.0:10902" ''
|
||||
Listen <literal>host:port</literal> for HTTP endpoints.
|
||||
'';
|
||||
|
||||
stateDir = mkStateDirParam "data-dir" "thanos-compact" ''
|
||||
Data directory relative to <literal>/var/lib</literal>
|
||||
in which to cache blocks and process compactions.
|
||||
'';
|
||||
|
||||
consistency-delay = mkParamDef types.str "30m" ''
|
||||
Minimum age of fresh (non-compacted) blocks before they are being
|
||||
processed. Malformed blocks older than the maximum of consistency-delay
|
||||
and 30m0s will be removed.
|
||||
'';
|
||||
|
||||
retention.resolution-raw = mkParamDef types.str "0d" ''
|
||||
How long to retain raw samples in bucket.
|
||||
|
||||
<literal>0d</literal> - disables this retention
|
||||
'';
|
||||
|
||||
retention.resolution-5m = mkParamDef types.str "0d" ''
|
||||
How long to retain samples of resolution 1 (5 minutes) in bucket.
|
||||
|
||||
<literal>0d</literal> - disables this retention
|
||||
'';
|
||||
|
||||
retention.resolution-1h = mkParamDef types.str "0d" ''
|
||||
How long to retain samples of resolution 2 (1 hour) in bucket.
|
||||
|
||||
<literal>0d</literal> - disables this retention
|
||||
'';
|
||||
|
||||
startAt = {
|
||||
toArgs = _opt: startAt: flagToArgs "wait" (startAt == null);
|
||||
option = nullOpt types.str ''
|
||||
When this option is set to a <literal>systemd.time</literal>
|
||||
specification the Thanos compactor will run at the specified period.
|
||||
|
||||
When this option is <literal>null</literal> the Thanos compactor service
|
||||
will run continuously. So it will not exit after all compactions have
|
||||
been processed but wait for new work.
|
||||
'';
|
||||
};
|
||||
|
||||
block-sync-concurrency = mkParamDef types.int 20 ''
|
||||
Number of goroutines to use when syncing block metadata from object storage.
|
||||
'';
|
||||
|
||||
compact.concurrency = mkParamDef types.int 1 ''
|
||||
Number of goroutines to use when compacting groups.
|
||||
'';
|
||||
};
|
||||
|
||||
downsample = params.log // params.tracing cfg.downsample // params.objstore cfg.downsample // {
|
||||
|
||||
stateDir = mkStateDirParam "data-dir" "thanos-downsample" ''
|
||||
Data directory relative to <literal>/var/lib</literal>
|
||||
in which to cache blocks and process downsamplings.
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
receive = params.common cfg.receive // params.objstore cfg.receive // {
|
||||
|
||||
remote-write.address = mkParamDef types.str "0.0.0.0:19291" ''
|
||||
Address to listen on for remote write requests.
|
||||
'';
|
||||
|
||||
stateDir = mkStateDirParam "tsdb.path" "thanos-receive" ''
|
||||
Data directory relative to <literal>/var/lib</literal> of TSDB.
|
||||
'';
|
||||
|
||||
labels = mkAttrsParam "labels" ''
|
||||
External labels to announce.
|
||||
|
||||
This flag will be removed in the future when handling multiple tsdb
|
||||
instances is added.
|
||||
'';
|
||||
|
||||
tsdb.retention = mkParamDef types.str "15d" ''
|
||||
How long to retain raw samples on local storage.
|
||||
|
||||
<literal>0d</literal> - disables this retention
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
assertRelativeStateDir = cmd: {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !hasPrefix "/" cfg."${cmd}".stateDir;
|
||||
message =
|
||||
"The option services.thanos.${cmd}.stateDir should not be an absolute directory." +
|
||||
" It should be a directory relative to /var/lib.";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
in {
|
||||
|
||||
options.services.thanos = {
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.thanos;
|
||||
defaultText = "pkgs.thanos";
|
||||
description = ''
|
||||
The thanos package that should be used.
|
||||
'';
|
||||
};
|
||||
|
||||
sidecar = paramsToOptions params.sidecar // {
|
||||
enable = mkEnableOption
|
||||
"the Thanos sidecar for Prometheus server";
|
||||
arguments = mkArgumentsOption "sidecar";
|
||||
};
|
||||
|
||||
store = paramsToOptions params.store // {
|
||||
enable = mkEnableOption
|
||||
"the Thanos store node giving access to blocks in a bucket provider.";
|
||||
arguments = mkArgumentsOption "store";
|
||||
};
|
||||
|
||||
query = paramsToOptions params.query // {
|
||||
enable = mkEnableOption
|
||||
("the Thanos query node exposing PromQL enabled Query API " +
|
||||
"with data retrieved from multiple store nodes");
|
||||
arguments = mkArgumentsOption "query";
|
||||
};
|
||||
|
||||
rule = paramsToOptions params.rule // {
|
||||
enable = mkEnableOption
|
||||
("the Thanos ruler service which evaluates Prometheus rules against" +
|
||||
" given Query nodes, exposing Store API and storing old blocks in bucket");
|
||||
arguments = mkArgumentsOption "rule";
|
||||
};
|
||||
|
||||
compact = paramsToOptions params.compact // {
|
||||
enable = mkEnableOption
|
||||
"the Thanos compactor which continuously compacts blocks in an object store bucket";
|
||||
arguments = mkArgumentsOption "compact";
|
||||
};
|
||||
|
||||
downsample = paramsToOptions params.downsample // {
|
||||
enable = mkEnableOption
|
||||
"the Thanos downsampler which continuously downsamples blocks in an object store bucket";
|
||||
arguments = mkArgumentsOption "downsample";
|
||||
};
|
||||
|
||||
receive = paramsToOptions params.receive // {
|
||||
enable = mkEnableOption
|
||||
("the Thanos receiver which accept Prometheus remote write API requests " +
|
||||
"and write to local tsdb (EXPERIMENTAL, this may change drastically without notice)");
|
||||
arguments = mkArgumentsOption "receive";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
|
||||
(mkIf cfg.sidecar.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = config.services.prometheus2.enable;
|
||||
message =
|
||||
"Please enable services.prometheus2 when enabling services.thanos.sidecar.";
|
||||
}
|
||||
{
|
||||
assertion = !(config.services.prometheus2.globalConfig.external_labels == null ||
|
||||
config.services.prometheus2.globalConfig.external_labels == {});
|
||||
message =
|
||||
"services.thanos.sidecar requires uniquely identifying external labels " +
|
||||
"to be configured in the Prometheus server. " +
|
||||
"Please set services.prometheus2.globalConfig.external_labels.";
|
||||
}
|
||||
];
|
||||
systemd.services.thanos-sidecar = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "prometheus2.service" ];
|
||||
serviceConfig = {
|
||||
User = "prometheus";
|
||||
Restart = "always";
|
||||
ExecStart = thanos "sidecar";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.store.enable (mkMerge [
|
||||
(assertRelativeStateDir "store")
|
||||
{
|
||||
systemd.services.thanos-store = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = cfg.store.stateDir;
|
||||
Restart = "always";
|
||||
ExecStart = thanos "store";
|
||||
};
|
||||
};
|
||||
}
|
||||
]))
|
||||
|
||||
(mkIf cfg.query.enable {
|
||||
systemd.services.thanos-query = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
ExecStart = thanos "query";
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.rule.enable (mkMerge [
|
||||
(assertRelativeStateDir "rule")
|
||||
{
|
||||
systemd.services.thanos-rule = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = cfg.rule.stateDir;
|
||||
Restart = "always";
|
||||
ExecStart = thanos "rule";
|
||||
};
|
||||
};
|
||||
}
|
||||
]))
|
||||
|
||||
(mkIf cfg.compact.enable (mkMerge [
|
||||
(assertRelativeStateDir "compact")
|
||||
{
|
||||
systemd.services.thanos-compact =
|
||||
let wait = cfg.compact.startAt == null; in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
Type = if wait then "simple" else "oneshot";
|
||||
Restart = if wait then "always" else "no";
|
||||
DynamicUser = true;
|
||||
StateDirectory = cfg.compact.stateDir;
|
||||
ExecStart = thanos "compact";
|
||||
};
|
||||
} // optionalAttrs (!wait) { inherit (cfg.compact) startAt; };
|
||||
}
|
||||
]))
|
||||
|
||||
(mkIf cfg.downsample.enable (mkMerge [
|
||||
(assertRelativeStateDir "downsample")
|
||||
{
|
||||
systemd.services.thanos-downsample = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = cfg.downsample.stateDir;
|
||||
Restart = "always";
|
||||
ExecStart = thanos "downsample";
|
||||
};
|
||||
};
|
||||
}
|
||||
]))
|
||||
|
||||
(mkIf cfg.receive.enable (mkMerge [
|
||||
(assertRelativeStateDir "receive")
|
||||
{
|
||||
systemd.services.thanos-receive = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = cfg.receive.stateDir;
|
||||
Restart = "always";
|
||||
ExecStart = thanos "receive";
|
||||
};
|
||||
};
|
||||
}
|
||||
]))
|
||||
|
||||
];
|
||||
}
|
|
@ -23,6 +23,7 @@ let
|
|||
LogType = console
|
||||
ListenIP = ${cfg.listen.ip}
|
||||
ListenPort = ${toString cfg.listen.port}
|
||||
Server = ${cfg.server}
|
||||
# TODO: set to cfg.database.socket if database type is pgsql?
|
||||
DBHost = ${optionalString (cfg.database.createLocally != true) cfg.database.host}
|
||||
${optionalString (cfg.database.createLocally != true) "DBPort = ${cfg.database.port}"}
|
||||
|
@ -50,6 +51,13 @@ in
|
|||
services.zabbixProxy = {
|
||||
enable = mkEnableOption "the Zabbix Proxy";
|
||||
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The IP address or hostname of the Zabbix server to connect to.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default =
|
||||
|
|
|
@ -48,6 +48,7 @@ in {
|
|||
requires = [ "keybase.service" ];
|
||||
after = [ "keybase.service" ];
|
||||
path = [ "/run/wrappers" ];
|
||||
unitConfig.ConditionUser = "!@system";
|
||||
serviceConfig = {
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${cfg.mountPoint}";
|
||||
ExecStart = "${pkgs.kbfs}/bin/kbfsfuse ${toString cfg.extraFlags} ${cfg.mountPoint}";
|
||||
|
|
|
@ -33,7 +33,7 @@ let
|
|||
${cfg.extraConfig}
|
||||
|
||||
${ concatMapStrings
|
||||
({ name, file, master ? true, slaves ? [], masters ? [] }:
|
||||
({ name, file, master ? true, slaves ? [], masters ? [], extraConfig ? "" }:
|
||||
''
|
||||
zone "${name}" {
|
||||
type ${if master then "master" else "slave"};
|
||||
|
@ -52,6 +52,7 @@ let
|
|||
''
|
||||
}
|
||||
allow-query { any; };
|
||||
${extraConfig}
|
||||
};
|
||||
'')
|
||||
cfg.zones }
|
||||
|
@ -131,6 +132,7 @@ in
|
|||
file = "/var/dns/example.com";
|
||||
masters = ["192.168.0.1"];
|
||||
slaves = [];
|
||||
extraConfig = "";
|
||||
}];
|
||||
};
|
||||
|
||||
|
@ -168,7 +170,9 @@ in
|
|||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.bind.enable {
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
networking.resolvconf.useLocalResolver = mkDefault true;
|
||||
|
||||
users.users = singleton
|
||||
{ name = bindUser;
|
||||
|
|
|
@ -79,7 +79,7 @@ in
|
|||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.dnsmasq.enable {
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
networking.nameservers =
|
||||
optional cfg.resolveLocalQueries "127.0.0.1";
|
||||
|
@ -92,6 +92,15 @@ in
|
|||
description = "Dnsmasq daemon user";
|
||||
};
|
||||
|
||||
networking.resolvconf = mkIf cfg.resolveLocalQueries {
|
||||
useLocalResolver = mkDefault true;
|
||||
|
||||
extraConfig = ''
|
||||
dnsmasq_conf=/etc/dnsmasq-conf.conf
|
||||
dnsmasq_resolv=/etc/dnsmasq-resolv.conf
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.dnsmasq = {
|
||||
description = "Dnsmasq Daemon";
|
||||
after = [ "network.target" "systemd-resolved.service" ];
|
||||
|
|
|
@ -26,6 +26,7 @@ in {
|
|||
|
||||
systemd.user.services.keybase = {
|
||||
description = "Keybase service";
|
||||
unitConfig.ConditionUser = "!@system";
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.keybase}/bin/keybase service --auto-forked
|
||||
|
|
|
@ -16,7 +16,8 @@ let
|
|||
plugins=keyfile
|
||||
dhcp=${cfg.dhcp}
|
||||
dns=${cfg.dns}
|
||||
rc-manager=${cfg.rc-manager}
|
||||
# If resolvconf is disabled that means that resolv.conf is managed by some other module.
|
||||
rc-manager=${if config.networking.resolvconf.enable then "resolvconf" else "unmanaged"}
|
||||
|
||||
[keyfile]
|
||||
${optionalString (cfg.unmanaged != [])
|
||||
|
@ -176,7 +177,7 @@ in {
|
|||
basePackages = mkOption {
|
||||
type = types.attrsOf types.package;
|
||||
default = { inherit (pkgs)
|
||||
networkmanager modemmanager wpa_supplicant
|
||||
networkmanager modemmanager wpa_supplicant crda
|
||||
networkmanager-openvpn networkmanager-vpnc
|
||||
networkmanager-openconnect networkmanager-fortisslvpn
|
||||
networkmanager-l2tp networkmanager-iodine; };
|
||||
|
@ -268,25 +269,6 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
rc-manager = mkOption {
|
||||
type = types.enum [ "symlink" "file" "resolvconf" "netconfig" "unmanaged" "none" ];
|
||||
default = "resolvconf";
|
||||
description = ''
|
||||
Set the <literal>resolv.conf</literal> management mode.
|
||||
</para>
|
||||
<para>
|
||||
A description of these modes can be found in the main section of
|
||||
<link xlink:href="https://developer.gnome.org/NetworkManager/stable/NetworkManager.conf.html">
|
||||
https://developer.gnome.org/NetworkManager/stable/NetworkManager.conf.html
|
||||
</link>
|
||||
or in
|
||||
<citerefentry>
|
||||
<refentrytitle>NetworkManager.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>.
|
||||
'';
|
||||
};
|
||||
|
||||
dispatcherScripts = mkOption {
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
|
@ -513,7 +495,7 @@ in {
|
|||
networking = {
|
||||
useDHCP = false;
|
||||
# use mkDefault to trigger the assertion about the conflict above
|
||||
wireless.enable = lib.mkDefault false;
|
||||
wireless.enable = mkDefault false;
|
||||
};
|
||||
|
||||
security.polkit.extraConfig = polkitConf;
|
||||
|
|
|
@ -35,6 +35,11 @@ in
|
|||
|
||||
config = mkIf config.services.rdnssd.enable {
|
||||
|
||||
assertions = [{
|
||||
assertion = config.networking.resolvconf.enable;
|
||||
message = "rdnssd needs resolvconf to work (probably something sets up a static resolv.conf)";
|
||||
}];
|
||||
|
||||
systemd.services.rdnssd = {
|
||||
description = "RDNSS daemon";
|
||||
after = [ "network.target" ];
|
||||
|
|
|
@ -291,7 +291,7 @@ in {
|
|||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "nogroup";
|
||||
default = defaultUser;
|
||||
description = ''
|
||||
Syncthing will be run under this group (group will not be created if it doesn't exist.
|
||||
This can be your user name).
|
||||
|
@ -372,16 +372,18 @@ in {
|
|||
|
||||
systemd.packages = [ pkgs.syncthing ];
|
||||
|
||||
users = mkIf (cfg.systemService && cfg.user == defaultUser) {
|
||||
users."${defaultUser}" =
|
||||
users.users = mkIf (cfg.systemService && cfg.user == defaultUser) {
|
||||
"${defaultUser}" =
|
||||
{ group = cfg.group;
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.syncthing;
|
||||
description = "Syncthing daemon user";
|
||||
};
|
||||
};
|
||||
|
||||
groups."${defaultUser}".gid =
|
||||
users.groups = mkIf (cfg.systemService && cfg.group == defaultUser) {
|
||||
"${defaultUser}".gid =
|
||||
config.ids.gids.syncthing;
|
||||
};
|
||||
|
||||
|
@ -403,18 +405,12 @@ in {
|
|||
Group = cfg.group;
|
||||
ExecStartPre = mkIf (cfg.declarative.cert != null || cfg.declarative.key != null)
|
||||
"+${pkgs.writers.writeBash "syncthing-copy-keys" ''
|
||||
mkdir -p ${cfg.configDir}
|
||||
chown ${cfg.user}:${cfg.group} ${cfg.configDir}
|
||||
chmod 700 ${cfg.configDir}
|
||||
install -dm700 -o ${cfg.user} -g ${cfg.group} ${cfg.configDir}
|
||||
${optionalString (cfg.declarative.cert != null) ''
|
||||
cp ${toString cfg.declarative.cert} ${cfg.configDir}/cert.pem
|
||||
chown ${cfg.user}:${cfg.group} ${cfg.configDir}/cert.pem
|
||||
chmod 400 ${cfg.configDir}/cert.pem
|
||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.declarative.cert} ${cfg.configDir}/cert.pem
|
||||
''}
|
||||
${optionalString (cfg.declarative.key != null) ''
|
||||
cp ${toString cfg.declarative.key} ${cfg.configDir}/key.pem
|
||||
chown ${cfg.user}:${cfg.group} ${cfg.configDir}/key.pem
|
||||
chmod 400 ${cfg.configDir}/key.pem
|
||||
install -Dm400 -o ${cfg.user} -g ${cfg.group} ${toString cfg.declarative.key} ${cfg.configDir}/key.pem
|
||||
''}
|
||||
''}"
|
||||
;
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.thelounge;
|
||||
dataDir = "/var/lib/thelounge";
|
||||
configJsData = "module.exports = " + builtins.toJSON (
|
||||
{ private = cfg.private; port = cfg.port; } // cfg.extraConfig
|
||||
);
|
||||
in {
|
||||
options.services.thelounge = {
|
||||
enable = mkEnableOption "The Lounge web IRC client";
|
||||
|
||||
private = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Make your The Lounge instance private. You will need to configure user
|
||||
accounts by using the (<command>thelounge</command>) command or by adding
|
||||
entries in <filename>${dataDir}/users</filename>. You might need to restart
|
||||
The Lounge after making changes to the state directory.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 9000;
|
||||
description = "TCP port to listen on for http connections.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = {};
|
||||
type = types.attrs;
|
||||
example = literalExample ''{
|
||||
reverseProxy = true;
|
||||
defaults = {
|
||||
name = "Your Network";
|
||||
host = "localhost";
|
||||
port = 6697;
|
||||
};
|
||||
}'';
|
||||
description = ''
|
||||
The Lounge's <filename>config.js</filename> contents as attribute set (will be
|
||||
converted to JSON to generate the configuration file).
|
||||
|
||||
The options defined here will be merged to the default configuration file.
|
||||
Note: In case of duplicate configuration, options from <option>extraConfig</option> have priority.
|
||||
|
||||
Documentation: <link xlink:href="https://thelounge.chat/docs/server/configuration" />
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.users.thelounge = {
|
||||
description = "thelounge service user";
|
||||
group = "thelounge";
|
||||
};
|
||||
users.groups.thelounge = {};
|
||||
systemd.services.thelounge = {
|
||||
description = "The Lounge web IRC client";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment = { THELOUNGE_HOME = dataDir; };
|
||||
preStart = "ln -sf ${pkgs.writeText "config.js" configJsData} ${dataDir}/config.js";
|
||||
serviceConfig = {
|
||||
User = "thelounge";
|
||||
StateDirectory = baseNameOf dataDir;
|
||||
ExecStart = "${pkgs.thelounge}/bin/thelounge start";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.thelounge ];
|
||||
};
|
||||
}
|
|
@ -101,6 +101,8 @@ in
|
|||
isSystemUser = true;
|
||||
};
|
||||
|
||||
networking.resolvconf.useLocalResolver = mkDefault true;
|
||||
|
||||
systemd.services.unbound = {
|
||||
description = "Unbound recursive Domain Name Server";
|
||||
after = [ "network.target" ];
|
||||
|
|
|
@ -204,6 +204,7 @@ in {
|
|||
environment.systemPackages = [ pkgs.wpa_supplicant ];
|
||||
|
||||
services.dbus.packages = [ pkgs.wpa_supplicant ];
|
||||
services.udev.packages = [ pkgs.crda ];
|
||||
|
||||
# FIXME: start a separate wpa_supplicant instance per interface.
|
||||
systemd.services.wpa_supplicant = let
|
||||
|
|
|
@ -107,8 +107,6 @@ in {
|
|||
path = with pkgs; [ iptables ipset iproute systemd ];
|
||||
|
||||
postStart = ''
|
||||
${pkgs.ipset}/bin/ipset -quiet create -exist sshguard4 hash:ip family inet
|
||||
${pkgs.ipset}/bin/ipset -quiet create -exist sshguard6 hash:ip family inet6
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -m set --match-set sshguard4 src -j DROP
|
||||
${pkgs.iptables}/bin/ip6tables -I INPUT -m set --match-set sshguard6 src -j DROP
|
||||
'';
|
||||
|
|
|
@ -81,7 +81,7 @@ let
|
|||
|
||||
${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) ''
|
||||
BridgeRelay 1
|
||||
ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${obfs4}/bin/obfs4proxy managed
|
||||
ServerTransportPlugin ${concatStringsSep "," cfg.relay.bridgeTransports} exec ${pkgs.obfs4}/bin/obfs4proxy managed
|
||||
ExtORPort auto
|
||||
${optionalString (cfg.relay.role == "private-bridge") ''
|
||||
ExtraInfoStatistics 0
|
||||
|
|
|
@ -7,46 +7,28 @@
|
|||
# is not aware of the path in which the nss modules live. As a workaround, we
|
||||
# have `enable-cache yes` with an explicit ttl of 0
|
||||
server-user nscd
|
||||
threads 1
|
||||
paranoia no
|
||||
debug-level 0
|
||||
|
||||
enable-cache passwd yes
|
||||
positive-time-to-live passwd 0
|
||||
negative-time-to-live passwd 0
|
||||
suggested-size passwd 211
|
||||
check-files passwd yes
|
||||
persistent passwd no
|
||||
shared passwd yes
|
||||
|
||||
enable-cache group yes
|
||||
positive-time-to-live group 0
|
||||
negative-time-to-live group 0
|
||||
suggested-size group 211
|
||||
check-files group yes
|
||||
persistent group no
|
||||
shared group yes
|
||||
|
||||
enable-cache netgroup yes
|
||||
positive-time-to-live netgroup 0
|
||||
negative-time-to-live netgroup 0
|
||||
suggested-size netgroup 211
|
||||
check-files netgroup yes
|
||||
persistent netgroup no
|
||||
shared netgroup yes
|
||||
|
||||
enable-cache hosts yes
|
||||
positive-time-to-live hosts 600
|
||||
negative-time-to-live hosts 0
|
||||
suggested-size hosts 211
|
||||
check-files hosts yes
|
||||
persistent hosts no
|
||||
shared hosts yes
|
||||
|
||||
enable-cache services yes
|
||||
positive-time-to-live services 0
|
||||
negative-time-to-live services 0
|
||||
suggested-size services 211
|
||||
check-files services yes
|
||||
persistent services no
|
||||
shared services yes
|
||||
|
|
|
@ -39,11 +39,6 @@ in
|
|||
config = mkIf cfg.enable {
|
||||
environment.etc."nscd.conf".text = cfg.config;
|
||||
|
||||
users.users.nscd =
|
||||
{ isSystemUser = true;
|
||||
description = "Name service cache daemon user";
|
||||
};
|
||||
|
||||
systemd.services.nscd =
|
||||
{ description = "Name Service Cache Daemon";
|
||||
|
||||
|
@ -51,22 +46,23 @@ in
|
|||
|
||||
environment = { LD_LIBRARY_PATH = nssModulesPath; };
|
||||
|
||||
preStart =
|
||||
''
|
||||
mkdir -m 0755 -p /run/nscd
|
||||
rm -f /run/nscd/nscd.pid
|
||||
mkdir -m 0755 -p /var/db/nscd
|
||||
'';
|
||||
|
||||
restartTriggers = [
|
||||
config.environment.etc.hosts.source
|
||||
config.environment.etc."nsswitch.conf".source
|
||||
config.environment.etc."nscd.conf".source
|
||||
];
|
||||
|
||||
# We use DynamicUser because in default configurations nscd doesn't
|
||||
# create any files that need to survive restarts. However, in some
|
||||
# configurations, nscd needs to be started as root; it will drop
|
||||
# privileges after all the NSS modules have read their configuration
|
||||
# files. So prefix the ExecStart command with "!" to prevent systemd
|
||||
# from dropping privileges early. See ExecStart in systemd.service(5).
|
||||
serviceConfig =
|
||||
{ ExecStart = "@${pkgs.glibc.bin}/sbin/nscd nscd";
|
||||
{ ExecStart = "!@${pkgs.glibc.bin}/sbin/nscd nscd";
|
||||
Type = "forking";
|
||||
DynamicUser = true;
|
||||
RuntimeDirectory = "nscd";
|
||||
PIDFile = "/run/nscd/nscd.pid";
|
||||
Restart = "always";
|
||||
ExecReload =
|
||||
|
@ -75,15 +71,6 @@ in
|
|||
"${pkgs.glibc.bin}/sbin/nscd --invalidate hosts"
|
||||
];
|
||||
};
|
||||
|
||||
# Urgggggh... Nscd forks before opening its socket and writing
|
||||
# its pid. So wait until it's ready.
|
||||
postStart =
|
||||
''
|
||||
while ! ${pkgs.glibc.bin}/sbin/nscd -g > /dev/null; do
|
||||
sleep 0.2
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,473 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
|
||||
inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
|
||||
inherit (lib) concatStringsSep literalExample mapAttrsToList optional optionals optionalString types;
|
||||
|
||||
cfg = config.services.mediawiki;
|
||||
fpm = config.services.phpfpm.pools.mediawiki;
|
||||
user = "mediawiki";
|
||||
group = config.services.httpd.group;
|
||||
cacheDir = "/var/cache/mediawiki";
|
||||
stateDir = "/var/lib/mediawiki";
|
||||
|
||||
pkg = pkgs.stdenv.mkDerivation rec {
|
||||
pname = "mediawiki-full";
|
||||
version = src.version;
|
||||
src = cfg.package;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r * $out/
|
||||
|
||||
rm -rf $out/share/mediawiki/skins/*
|
||||
rm -rf $out/share/mediawiki/extensions/*
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: ''
|
||||
ln -s ${v} $out/share/mediawiki/skins/${k}
|
||||
'') cfg.skins)}
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: ''
|
||||
ln -s ${v} $out/share/mediawiki/extensions/${k}
|
||||
'') cfg.extensions)}
|
||||
'';
|
||||
};
|
||||
|
||||
mediawikiScripts = pkgs.runCommand "mediawiki-scripts" {
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do
|
||||
makeWrapper ${pkgs.php}/bin/php $out/bin/mediawiki-$(basename $i .php) \
|
||||
--set MEDIAWIKI_CONFIG ${mediawikiConfig} \
|
||||
--add-flags ${pkg}/share/mediawiki/maintenance/$i
|
||||
done
|
||||
'';
|
||||
|
||||
mediawikiConfig = pkgs.writeText "LocalSettings.php" ''
|
||||
<?php
|
||||
# Protect against web entry
|
||||
if ( !defined( 'MEDIAWIKI' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$wgSitename = "${cfg.name}";
|
||||
$wgMetaNamespace = false;
|
||||
|
||||
## The URL base path to the directory containing the wiki;
|
||||
## defaults for all runtime URL paths are based off of this.
|
||||
## For more information on customizing the URLs
|
||||
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
|
||||
## https://www.mediawiki.org/wiki/Manual:Short_URL
|
||||
$wgScriptPath = "";
|
||||
|
||||
## The protocol and server name to use in fully-qualified URLs
|
||||
$wgServer = "${if cfg.virtualHost.enableSSL then "https" else "http"}://${cfg.virtualHost.hostName}";
|
||||
|
||||
## The URL path to static resources (images, scripts, etc.)
|
||||
$wgResourceBasePath = $wgScriptPath;
|
||||
|
||||
## The URL path to the logo. Make sure you change this from the default,
|
||||
## or else you'll overwrite your logo when you upgrade!
|
||||
$wgLogo = "$wgResourceBasePath/resources/assets/wiki.png";
|
||||
|
||||
## UPO means: this is also a user preference option
|
||||
|
||||
$wgEnableEmail = true;
|
||||
$wgEnableUserEmail = true; # UPO
|
||||
|
||||
$wgEmergencyContact = "${if cfg.virtualHost.adminAddr != null then cfg.virtualHost.adminAddr else config.services.httpd.adminAddr}";
|
||||
$wgPasswordSender = $wgEmergencyContact;
|
||||
|
||||
$wgEnotifUserTalk = false; # UPO
|
||||
$wgEnotifWatchlist = false; # UPO
|
||||
$wgEmailAuthentication = true;
|
||||
|
||||
## Database settings
|
||||
$wgDBtype = "${cfg.database.type}";
|
||||
$wgDBserver = "${cfg.database.host}:${if cfg.database.socket != null then cfg.database.socket else toString cfg.database.port}";
|
||||
$wgDBname = "${cfg.database.name}";
|
||||
$wgDBuser = "${cfg.database.user}";
|
||||
${optionalString (cfg.database.passwordFile != null) "$wgDBpassword = file_get_contents(\"${cfg.database.passwordFile}\");"}
|
||||
|
||||
${optionalString (cfg.database.type == "mysql" && cfg.database.tablePrefix != null) ''
|
||||
# MySQL specific settings
|
||||
$wgDBprefix = "${cfg.database.tablePrefix}";
|
||||
''}
|
||||
|
||||
${optionalString (cfg.database.type == "mysql") ''
|
||||
# MySQL table options to use during installation or update
|
||||
$wgDBTableOptions = "ENGINE=InnoDB, DEFAULT CHARSET=binary";
|
||||
''}
|
||||
|
||||
## Shared memory settings
|
||||
$wgMainCacheType = CACHE_NONE;
|
||||
$wgMemCachedServers = [];
|
||||
|
||||
${optionalString (cfg.uploadsDir != null) ''
|
||||
$wgEnableUploads = true;
|
||||
$wgUploadDirectory = "${cfg.uploadsDir}";
|
||||
''}
|
||||
|
||||
$wgUseImageMagick = true;
|
||||
$wgImageMagickConvertCommand = "${pkgs.imagemagick}/bin/convert";
|
||||
|
||||
# InstantCommons allows wiki to use images from https://commons.wikimedia.org
|
||||
$wgUseInstantCommons = false;
|
||||
|
||||
# Periodically send a pingback to https://www.mediawiki.org/ with basic data
|
||||
# about this MediaWiki instance. The Wikimedia Foundation shares this data
|
||||
# with MediaWiki developers to help guide future development efforts.
|
||||
$wgPingback = true;
|
||||
|
||||
## If you use ImageMagick (or any other shell command) on a
|
||||
## Linux server, this will need to be set to the name of an
|
||||
## available UTF-8 locale
|
||||
$wgShellLocale = "C.UTF-8";
|
||||
|
||||
## Set $wgCacheDirectory to a writable directory on the web server
|
||||
## to make your wiki go slightly faster. The directory should not
|
||||
## be publically accessible from the web.
|
||||
$wgCacheDirectory = "${cacheDir}";
|
||||
|
||||
# Site language code, should be one of the list in ./languages/data/Names.php
|
||||
$wgLanguageCode = "en";
|
||||
|
||||
$wgSecretKey = file_get_contents("${stateDir}/secret.key");
|
||||
|
||||
# Changing this will log out all existing sessions.
|
||||
$wgAuthenticationTokenVersion = "";
|
||||
|
||||
## For attaching licensing metadata to pages, and displaying an
|
||||
## appropriate copyright notice / icon. GNU Free Documentation
|
||||
## License and Creative Commons licenses are supported so far.
|
||||
$wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright
|
||||
$wgRightsUrl = "";
|
||||
$wgRightsText = "";
|
||||
$wgRightsIcon = "";
|
||||
|
||||
# Path to the GNU diff3 utility. Used for conflict resolution.
|
||||
$wgDiff = "${pkgs.diffutils}/bin/diff";
|
||||
$wgDiff3 = "${pkgs.diffutils}/bin/diff3";
|
||||
|
||||
# Enabled skins.
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: "wfLoadSkin('${k}');") cfg.skins)}
|
||||
|
||||
# Enabled extensions.
|
||||
${concatStringsSep "\n" (mapAttrsToList (k: v: "wfLoadExtension('${k}');") cfg.extensions)}
|
||||
|
||||
|
||||
# End of automatically generated settings.
|
||||
# Add more configuration options below.
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
# interface
|
||||
options = {
|
||||
services.mediawiki = {
|
||||
|
||||
enable = mkEnableOption "MediaWiki";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.mediawiki;
|
||||
description = "Which MediaWiki package to use.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
default = "MediaWiki";
|
||||
example = "Foobar Wiki";
|
||||
description = "Name of the wiki.";
|
||||
};
|
||||
|
||||
uploadsDir = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = "${stateDir}/uploads";
|
||||
description = ''
|
||||
This directory is used for uploads of pictures. The directory passed here is automatically
|
||||
created and permissions adjusted as required.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description = "A file containing the initial password for the admin user.";
|
||||
example = "/run/keys/mediawiki-password";
|
||||
};
|
||||
|
||||
skins = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf types.path;
|
||||
description = ''
|
||||
List of paths whose content is copied to the 'skins'
|
||||
subdirectory of the MediaWiki installation.
|
||||
'';
|
||||
};
|
||||
|
||||
extensions = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf types.path;
|
||||
description = ''
|
||||
List of paths whose content is copied to the 'extensions'
|
||||
subdirectory of the MediaWiki installation.
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
type = mkOption {
|
||||
type = types.enum [ "mysql" "postgres" "sqlite" "mssql" "oracle" ];
|
||||
default = "mysql";
|
||||
description = "Database engine to use. MySQL/MariaDB is the database of choice by MediaWiki developers.";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
description = "Database host address.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3306;
|
||||
description = "Database host port.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "mediawiki";
|
||||
description = "Database name.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "mediawiki";
|
||||
description = "Database user.";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/keys/mediawiki-dbpassword";
|
||||
description = ''
|
||||
A file containing the password corresponding to
|
||||
<option>database.user</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
tablePrefix = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
If you only have access to a single database and wish to install more than
|
||||
one version of MediaWiki, or have other applications that also use the
|
||||
database, you can give the table names a unique prefix to stop any naming
|
||||
conflicts or confusion.
|
||||
See <link xlink:href='https://www.mediawiki.org/wiki/Manual:$wgDBprefix'/>.
|
||||
'';
|
||||
};
|
||||
|
||||
socket = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = if cfg.database.createLocally then "/run/mysqld/mysqld.sock" else null;
|
||||
defaultText = "/run/mysqld/mysqld.sock";
|
||||
description = "Path to the unix socket file to use for authentication.";
|
||||
};
|
||||
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = cfg.database.type == "mysql";
|
||||
defaultText = "true";
|
||||
description = ''
|
||||
Create the database and database user locally.
|
||||
This currently only applies if database type "mysql" is selected.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
virtualHost = mkOption {
|
||||
type = types.submodule ({
|
||||
options = import ../web-servers/apache-httpd/per-server-options.nix {
|
||||
inherit lib;
|
||||
forMainServer = false;
|
||||
};
|
||||
});
|
||||
example = literalExample ''
|
||||
{
|
||||
hostName = "mediawiki.example.org";
|
||||
enableSSL = true;
|
||||
adminAddr = "webmaster@example.org";
|
||||
sslServerCert = "/var/lib/acme/mediawiki.example.org/full.pem";
|
||||
sslServerKey = "/var/lib/acme/mediawiki.example.org/key.pem";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Apache configuration can be done by adapting <option>services.httpd.virtualHosts</option>.
|
||||
See <xref linkend="opt-services.httpd.virtualHosts"/> for further information.
|
||||
'';
|
||||
};
|
||||
|
||||
poolConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
pm = dynamic
|
||||
pm.max_children = 32
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 2
|
||||
pm.max_spare_servers = 4
|
||||
pm.max_requests = 500
|
||||
'';
|
||||
description = ''
|
||||
Options for MediaWiki's PHP pool. See the documentation on <literal>php-fpm.conf</literal>
|
||||
for details on configuration directives.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Any additional text to be appended to MediaWiki's
|
||||
LocalSettings.php configuration file. For configuration
|
||||
settings, see <link xlink:href="https://www.mediawiki.org/wiki/Manual:Configuration_settings"/>.
|
||||
'';
|
||||
default = "";
|
||||
example = ''
|
||||
$wgEnableEmail = false;
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
# implementation
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.type == "mysql";
|
||||
message = "services.mediawiki.createLocally is currently only supported for database type 'mysql'";
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.user == user;
|
||||
message = "services.mediawiki.database.user must be set to ${user} if services.mediawiki.database.createLocally is set true";
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.socket != null;
|
||||
message = "services.mediawiki.database.socket must be set if services.mediawiki.database.createLocally is set to true";
|
||||
}
|
||||
{ assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
|
||||
message = "a password cannot be specified if services.mediawiki.database.createLocally is set to true";
|
||||
}
|
||||
];
|
||||
|
||||
services.mediawiki.skins = {
|
||||
MonoBook = "${cfg.package}/share/mediawiki/skins/MonoBook";
|
||||
Timeless = "${cfg.package}/share/mediawiki/skins/Timeless";
|
||||
Vector = "${cfg.package}/share/mediawiki/skins/Vector";
|
||||
};
|
||||
|
||||
services.mysql = mkIf cfg.database.createLocally {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{ name = cfg.database.user;
|
||||
ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.phpfpm.pools.mediawiki = {
|
||||
listen = "/run/phpfpm/mediawiki.sock";
|
||||
extraConfig = ''
|
||||
listen.owner = ${config.services.httpd.user}
|
||||
listen.group = ${config.services.httpd.group}
|
||||
user = ${user}
|
||||
group = ${group}
|
||||
|
||||
env[MEDIAWIKI_CONFIG] = ${mediawikiConfig}
|
||||
|
||||
${cfg.poolConfig}
|
||||
'';
|
||||
};
|
||||
|
||||
services.httpd = {
|
||||
enable = true;
|
||||
adminAddr = mkDefault cfg.virtualHost.adminAddr;
|
||||
extraModules = [ "proxy_fcgi" ];
|
||||
virtualHosts = [ (mkMerge [
|
||||
cfg.virtualHost {
|
||||
documentRoot = mkForce "${pkg}/share/mediawiki";
|
||||
extraConfig = ''
|
||||
<Directory "${pkg}/share/mediawiki">
|
||||
<FilesMatch "\.php$">
|
||||
<If "-f %{REQUEST_FILENAME}">
|
||||
SetHandler "proxy:unix:${fpm.listen}|fcgi://localhost/"
|
||||
</If>
|
||||
</FilesMatch>
|
||||
|
||||
Require all granted
|
||||
DirectoryIndex index.php
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
'' + optionalString (cfg.uploadsDir != null) ''
|
||||
Alias "/images" "${cfg.uploadsDir}"
|
||||
<Directory "${cfg.uploadsDir}">
|
||||
Require all granted
|
||||
</Directory>
|
||||
'';
|
||||
}
|
||||
]) ];
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${stateDir}' 0750 ${user} ${group} - -"
|
||||
"d '${cacheDir}' 0750 ${user} ${group} - -"
|
||||
] ++ optionals (cfg.uploadsDir != null) [
|
||||
"d '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
|
||||
"Z '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
|
||||
];
|
||||
|
||||
systemd.services.mediawiki-init = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "phpfpm-mediawiki.service" ];
|
||||
after = optional cfg.database.createLocally "mysql.service";
|
||||
script = ''
|
||||
if ! test -e "${stateDir}/secret.key"; then
|
||||
tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c 64 > ${stateDir}/secret.key
|
||||
fi
|
||||
|
||||
echo "exit( wfGetDB( DB_MASTER )->tableExists( 'user' ) ? 1 : 0 );" | \
|
||||
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/eval.php --conf ${mediawikiConfig} && \
|
||||
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/install.php \
|
||||
--confpath /tmp \
|
||||
--scriptpath / \
|
||||
--dbserver ${cfg.database.host}${optionalString (cfg.database.socket != null) ":${cfg.database.socket}"} \
|
||||
--dbport ${toString cfg.database.port} \
|
||||
--dbname ${cfg.database.name} \
|
||||
${optionalString (cfg.database.tablePrefix != null) "--dbprefix ${cfg.database.tablePrefix}"} \
|
||||
--dbuser ${cfg.database.user} \
|
||||
${optionalString (cfg.database.passwordFile != null) "--dbpassfile ${cfg.database.passwordFile}"} \
|
||||
--passfile ${cfg.passwordFile} \
|
||||
${cfg.name} \
|
||||
admin
|
||||
|
||||
${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig} --quick
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
Group = group;
|
||||
PrivateTmp = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.httpd.after = optional (cfg.database.createLocally && cfg.database.type == "mysql") "mysql.service";
|
||||
|
||||
users.users.${user}.group = group;
|
||||
|
||||
environment.systemPackages = [ mediawikiScripts ];
|
||||
};
|
||||
}
|
|
@ -297,8 +297,23 @@ in {
|
|||
|
||||
systemd.services = {
|
||||
"nextcloud-setup" = let
|
||||
c = cfg.config;
|
||||
writePhpArrary = a: "[${concatMapStringsSep "," (val: ''"${toString val}"'') a}]";
|
||||
overrideConfig = pkgs.writeText "nextcloud-config.php" ''
|
||||
<?php
|
||||
${optionalString (c.dbpassFile != null) ''
|
||||
function nix_read_pwd() {
|
||||
$file = "${c.dbpassFile}";
|
||||
if (!file_exists($file)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
"Cannot start Nextcloud, dbpass file %s set by NixOS doesn't exist!",
|
||||
$file
|
||||
));
|
||||
}
|
||||
|
||||
return trim(file_get_contents($file));
|
||||
}
|
||||
''}
|
||||
$CONFIG = [
|
||||
'apps_paths' => [
|
||||
[ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ],
|
||||
|
@ -309,19 +324,27 @@ in {
|
|||
${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
|
||||
'log_type' => 'syslog',
|
||||
'log_level' => '${builtins.toString cfg.logLevel}',
|
||||
${optionalString (cfg.config.overwriteProtocol != null) "'overwriteprotocol' => '${cfg.config.overwriteProtocol}',"}
|
||||
${optionalString (c.overwriteProtocol != null) "'overwriteprotocol' => '${c.overwriteProtocol}',"}
|
||||
${optionalString (c.dbname != null) "'dbname' => '${c.dbname}',"}
|
||||
${optionalString (c.dbhost != null) "'dbhost' => '${c.dbhost}',"}
|
||||
${optionalString (c.dbport != null) "'dbport' => '${toString c.dbport}',"}
|
||||
${optionalString (c.dbuser != null) "'dbuser' => '${c.dbuser}',"}
|
||||
${optionalString (c.dbtableprefix != null) "'dbtableprefix' => '${toString c.dbtableprefix}',"}
|
||||
${optionalString (c.dbpass != null) "'dbpassword' => '${c.dbpass}',"}
|
||||
${optionalString (c.dbpassFile != null) "'dbpassword' => nix_read_pwd(),"}
|
||||
'dbtype' => '${c.dbtype}',
|
||||
'trusted_domains' => ${writePhpArrary ([ cfg.hostName ] ++ c.extraTrustedDomains)},
|
||||
];
|
||||
'';
|
||||
occInstallCmd = let
|
||||
c = cfg.config;
|
||||
adminpass = if c.adminpassFile != null
|
||||
then ''"$(<"${toString c.adminpassFile}")"''
|
||||
else ''"${toString c.adminpass}"'';
|
||||
dbpass = if c.dbpassFile != null
|
||||
then ''"$(<"${toString c.dbpassFile}")"''
|
||||
else if c.dbpass != null
|
||||
then ''"${toString c.dbpass}"''
|
||||
else null;
|
||||
adminpass = if c.adminpassFile != null
|
||||
then ''"$(<"${toString c.adminpassFile}")"''
|
||||
else ''"${toString c.adminpass}"'';
|
||||
installFlags = concatStringsSep " \\\n "
|
||||
(mapAttrsToList (k: v: "${k} ${toString v}") {
|
||||
"--database" = ''"${c.dbtype}"'';
|
||||
|
|
|
@ -42,10 +42,12 @@
|
|||
|
||||
services.postgresql = {
|
||||
<link linkend="opt-services.postgresql.enable">enable</link> = true;
|
||||
<link linkend="opt-services.postgresql.initialScript">initialScript</link> = pkgs.writeText "psql-init" ''
|
||||
CREATE ROLE nextcloud WITH LOGIN;
|
||||
CREATE DATABASE nextcloud WITH OWNER nextcloud;
|
||||
'';
|
||||
<link linkend="opt-services.postgresql.ensureDatabases">ensureDatabases</link> = [ "nextcloud" ];
|
||||
<link linkend="opt-services.postgresql.ensureUsers">ensureUsers</link> = [
|
||||
{ name = "nextcloud";
|
||||
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# ensure that postgres is running *before* running the setup
|
||||
|
@ -63,17 +65,22 @@
|
|||
are used internally to configure an HTTP server using
|
||||
<literal><link xlink:href="https://php-fpm.org/">PHP-FPM</link></literal>
|
||||
and <literal>nginx</literal>. The <literal>config</literal> attribute set is
|
||||
used for the <literal>config.php</literal> which is used for the
|
||||
application's configuration. <emphasis>Beware: this isn't entirely pure
|
||||
since the config is modified by the application's runtime!</emphasis>
|
||||
used by the imperative installer and all values are written to an additional file
|
||||
to ensure that changes can be applied by changing the module's options.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In case the application serves multiple hosts (those are checked with
|
||||
In case the application serves multiple domains (those are checked with
|
||||
<literal><link xlink:href="http://php.net/manual/en/reserved.variables.server.php">$_SERVER['HTTP_HOST']</link></literal>)
|
||||
those can be added using
|
||||
it's needed to add them to
|
||||
<literal><link linkend="opt-services.nextcloud.config.extraTrustedDomains">services.nextcloud.config.extraTrustedDomains</link></literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Auto updates for Nextcloud apps can be enabled using
|
||||
<literal><link linkend="opt-services.nextcloud.autoUpdateApps.enable">services.nextcloud.autoUpdateApps</link></literal>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
<section xml:id="module-services-nextcloud-pitfalls-during-upgrade">
|
||||
<title>Pitfalls</title>
|
||||
|
@ -87,35 +94,24 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
Right now changes to the <literal>services.nextcloud.config</literal>
|
||||
attribute set won't take effect after the first install (except
|
||||
<literal><link linkend="opt-services.nextcloud.config.extraTrustedDomains">services.nextcloud.config.extraTrustedDomains</link></literal>)
|
||||
since the actual configuration file is generated by the NextCloud installer
|
||||
which also sets up critical parts such as the database structure.
|
||||
All configuration parameters are also stored in
|
||||
<literal>/var/lib/nextcloud/config/override.config.php</literal> which is generated by
|
||||
the module and linked from the store to ensure that all values from <literal>config.php</literal>
|
||||
can be modified by the module.
|
||||
However <literal>config.php</literal> manages the application's state and shouldn't be touched
|
||||
manually because of that.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis>Warning: don't delete <literal>config.php</literal>! This file
|
||||
<warning>
|
||||
<para>Don't delete <literal>config.php</literal>! This file
|
||||
tracks the application's state and a deletion can cause unwanted
|
||||
side-effects!</emphasis>
|
||||
</para>
|
||||
side-effects!</para>
|
||||
</warning>
|
||||
|
||||
<para>
|
||||
<emphasis>Warning: don't rerun <literal>nextcloud-occ
|
||||
<warning>
|
||||
<para>Don't rerun <literal>nextcloud-occ
|
||||
maintenance:install</literal>! This command tries to install the application
|
||||
and can cause unwanted side-effects!</emphasis>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The issues are known and reported in
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/49783">#49783</link>,
|
||||
for now it's unfortunately necessary to manually work around these issues.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Right now app installation and configuration is done imperatively in the nextcloud web ui or via the <literal>nextcloud-occ</literal> command line utility.
|
||||
You can activate auto updates for your apps via
|
||||
<literal><link linkend="opt-services.nextcloud.autoUpdateApps.enable">services.nextcloud.autoUpdateApps</link></literal>.
|
||||
</para>
|
||||
and can cause unwanted side-effects!</para>
|
||||
</warning>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -16,6 +16,9 @@ let
|
|||
|
||||
poolName = "tt-rss";
|
||||
|
||||
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
|
||||
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
|
||||
|
||||
tt-rss-config = pkgs.writeText "config.php" ''
|
||||
<?php
|
||||
|
||||
|
@ -200,6 +203,12 @@ let
|
|||
and 3306 for pgsql and mysql respectively).
|
||||
'';
|
||||
};
|
||||
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Create the database and database user locally.";
|
||||
};
|
||||
};
|
||||
|
||||
auth = {
|
||||
|
@ -551,9 +560,13 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
systemd.services.tt-rss = let
|
||||
dbService = if cfg.database.type == "pgsql" then "postgresql.service" else "mysql.service";
|
||||
in {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${cfg.root}' 0755 ${cfg.user} tt_rss - -"
|
||||
"Z '${cfg.root}' 0755 ${cfg.user} tt_rss - -"
|
||||
];
|
||||
|
||||
systemd.services.tt-rss =
|
||||
{
|
||||
|
||||
description = "Tiny Tiny RSS feeds update daemon";
|
||||
|
||||
|
@ -562,14 +575,14 @@ let
|
|||
if cfg.database.type == "pgsql" then ''
|
||||
${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \
|
||||
${optionalString (cfg.database.passwordFile != null) "PGPASSWORD=$(cat ${cfg.database.passwordFile})"} \
|
||||
${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.postgresql.package}/bin/psql \
|
||||
${config.services.postgresql.package}/bin/psql \
|
||||
-U ${cfg.database.user} \
|
||||
${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \
|
||||
-c '${e}' \
|
||||
${cfg.database.name}''
|
||||
|
||||
else if cfg.database.type == "mysql" then ''
|
||||
echo '${e}' | ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.mysql.package}/bin/mysql \
|
||||
echo '${e}' | ${config.services.mysql.package}/bin/mysql \
|
||||
-u ${cfg.database.user} \
|
||||
${optionalString (cfg.database.password != null) "-p${cfg.database.password}"} \
|
||||
${optionalString (cfg.database.host != null) "-h ${cfg.database.host} -P ${toString dbPort}"} \
|
||||
|
@ -579,7 +592,6 @@ let
|
|||
|
||||
in ''
|
||||
rm -rf "${cfg.root}/*"
|
||||
mkdir -m 755 -p "${cfg.root}"
|
||||
cp -r "${pkgs.tt-rss}/"* "${cfg.root}"
|
||||
${optionalString (cfg.pluginPackages != []) ''
|
||||
for plugin in ${concatStringsSep " " cfg.pluginPackages}; do
|
||||
|
@ -592,19 +604,10 @@ let
|
|||
done
|
||||
''}
|
||||
ln -sf "${tt-rss-config}" "${cfg.root}/config.php"
|
||||
chown -R "${cfg.user}" "${cfg.root}"
|
||||
chmod -R 755 "${cfg.root}"
|
||||
''
|
||||
|
||||
+ (optionalString (cfg.database.type == "pgsql") ''
|
||||
${optionalString (cfg.database.host == null && cfg.database.password == null) ''
|
||||
if ! [ -e ${cfg.root}/.db-created ]; then
|
||||
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createuser ${cfg.database.user}
|
||||
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createdb -O ${cfg.database.user} ${cfg.database.name}
|
||||
touch ${cfg.root}/.db-created
|
||||
fi
|
||||
''}
|
||||
|
||||
exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \
|
||||
| tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//')
|
||||
|
||||
|
@ -628,18 +631,18 @@ let
|
|||
|
||||
serviceConfig = {
|
||||
User = "${cfg.user}";
|
||||
Group = "tt_rss";
|
||||
ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon";
|
||||
StandardOutput = "syslog";
|
||||
StandardError = "syslog";
|
||||
PermissionsStartOnly = true;
|
||||
};
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = ["${dbService}"];
|
||||
after = ["network.target" "${dbService}"];
|
||||
requires = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
|
||||
after = [ "network.target" ] ++ optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
|
||||
};
|
||||
|
||||
services.mysql = optionalAttrs (cfg.database.type == "mysql") {
|
||||
services.mysql = mkIf mysqlLocal {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.mysql;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
|
@ -653,17 +656,22 @@ let
|
|||
];
|
||||
};
|
||||
|
||||
services.postgresql = optionalAttrs (cfg.database.type == "pgsql") {
|
||||
services.postgresql = mkIf pgsqlLocal {
|
||||
enable = mkDefault true;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{ name = cfg.user;
|
||||
ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
users = optionalAttrs (cfg.user == "tt_rss") {
|
||||
users.tt_rss = {
|
||||
description = "tt-rss service user";
|
||||
isSystemUser = true;
|
||||
group = "tt_rss";
|
||||
};
|
||||
groups.tt_rss = {};
|
||||
users.users.tt_rss = optionalAttrs (cfg.user == "tt_rss") {
|
||||
description = "tt-rss service user";
|
||||
isSystemUser = true;
|
||||
group = "tt_rss";
|
||||
};
|
||||
|
||||
users.groups.tt_rss = {};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,10 +21,9 @@ let
|
|||
else [{ip = "*"; port = 80;}];
|
||||
|
||||
getListen = cfg:
|
||||
let list = (lib.optional (cfg.port != 0) {ip = "*"; port = cfg.port;}) ++ cfg.listen;
|
||||
in if list == []
|
||||
then defaultListen cfg
|
||||
else list;
|
||||
if cfg.listen == []
|
||||
then defaultListen cfg
|
||||
else cfg.listen;
|
||||
|
||||
listenToString = l: "${l.ip}:${toString l.port}";
|
||||
|
||||
|
@ -638,7 +637,7 @@ in
|
|||
message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; }
|
||||
];
|
||||
|
||||
warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts);
|
||||
warnings = map (cfg: "apache-httpd's extraSubservices option is deprecated. Most existing subservices have been ported to the NixOS module system. Please update your configuration accordingly.") (lib.filter (cfg: cfg.extraSubservices != []) allHosts);
|
||||
|
||||
users.users = optionalAttrs (mainCfg.user == "wwwrun") (singleton
|
||||
{ name = "wwwrun";
|
||||
|
@ -672,7 +671,7 @@ in
|
|||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "keys.target" ];
|
||||
after = [ "network.target" "fs.target" "postgresql.service" "keys.target" ];
|
||||
after = [ "network.target" "fs.target" "keys.target" ];
|
||||
|
||||
path =
|
||||
[ httpd pkgs.coreutils pkgs.gnugrep ]
|
||||
|
|
|
@ -1,349 +0,0 @@
|
|||
{ config, lib, pkgs, serverInfo, php, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
httpd = serverInfo.serverConfig.package;
|
||||
|
||||
version24 = !versionOlder httpd.version "2.4";
|
||||
|
||||
allGranted = if version24 then ''
|
||||
Require all granted
|
||||
'' else ''
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
'';
|
||||
|
||||
mediawikiConfig = pkgs.writeText "LocalSettings.php"
|
||||
''
|
||||
<?php
|
||||
# Copied verbatim from the default (generated) LocalSettings.php.
|
||||
if( defined( 'MW_INSTALL_PATH' ) ) {
|
||||
$IP = MW_INSTALL_PATH;
|
||||
} else {
|
||||
$IP = dirname( __FILE__ );
|
||||
}
|
||||
|
||||
$path = array( $IP, "$IP/includes", "$IP/languages" );
|
||||
set_include_path( implode( PATH_SEPARATOR, $path ) . PATH_SEPARATOR . get_include_path() );
|
||||
|
||||
require_once( "$IP/includes/DefaultSettings.php" );
|
||||
|
||||
if ( $wgCommandLineMode ) {
|
||||
if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
|
||||
die( "This script must be run from the command line\n" );
|
||||
}
|
||||
}
|
||||
|
||||
$wgScriptPath = "${config.urlPrefix}";
|
||||
|
||||
# We probably need to set $wgSecretKey and $wgCacheEpoch.
|
||||
|
||||
# Paths to external programs.
|
||||
$wgDiff3 = "${pkgs.diffutils}/bin/diff3";
|
||||
$wgDiff = "${pkgs.diffutils}/bin/diff";
|
||||
$wgImageMagickConvertCommand = "${pkgs.imagemagick.out}/bin/convert";
|
||||
|
||||
#$wgDebugLogFile = "/tmp/mediawiki_debug_log.txt";
|
||||
|
||||
# Database configuration.
|
||||
$wgDBtype = "${config.dbType}";
|
||||
$wgDBserver = "${config.dbServer}";
|
||||
$wgDBuser = "${config.dbUser}";
|
||||
$wgDBpassword = "${config.dbPassword}";
|
||||
$wgDBname = "${config.dbName}";
|
||||
|
||||
# E-mail.
|
||||
$wgEmergencyContact = "${config.emergencyContact}";
|
||||
$wgPasswordSender = "${config.passwordSender}";
|
||||
|
||||
$wgSitename = "${config.siteName}";
|
||||
|
||||
${optionalString (config.logo != "") ''
|
||||
$wgLogo = "${config.logo}";
|
||||
''}
|
||||
|
||||
${optionalString (config.articleUrlPrefix != "") ''
|
||||
$wgArticlePath = "${config.articleUrlPrefix}/$1";
|
||||
''}
|
||||
|
||||
${optionalString config.enableUploads ''
|
||||
$wgEnableUploads = true;
|
||||
$wgUploadDirectory = "${config.uploadDir}";
|
||||
''}
|
||||
|
||||
${optionalString (config.defaultSkin != "") ''
|
||||
$wgDefaultSkin = "${config.defaultSkin}";
|
||||
''}
|
||||
|
||||
${config.extraConfig}
|
||||
?>
|
||||
'';
|
||||
|
||||
# Unpack Mediawiki and put the config file in its root directory.
|
||||
mediawikiRoot = pkgs.stdenv.mkDerivation rec {
|
||||
name= "mediawiki-1.31.1";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
url = "https://releases.wikimedia.org/mediawiki/1.31/${name}.tar.gz";
|
||||
sha256 = "13x48clij21cmysjkpnx68vggchrdasqp7b290j87xlfgjhdhnnf";
|
||||
};
|
||||
|
||||
skins = config.skins;
|
||||
extensions = config.extensions;
|
||||
|
||||
buildPhase =
|
||||
''
|
||||
for skin in $skins; do
|
||||
cp -prvd $skin/* skins/
|
||||
done
|
||||
for extension in $extensions; do
|
||||
cp -prvd $extension/* extensions/
|
||||
done
|
||||
''; # */
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out
|
||||
cp -r * $out
|
||||
cp ${mediawikiConfig} $out/LocalSettings.php
|
||||
sed -i \
|
||||
-e 's|/bin/bash|${pkgs.bash}/bin/bash|g' \
|
||||
-e 's|/usr/bin/timeout|${pkgs.coreutils}/bin/timeout|g' \
|
||||
$out/includes/shell/limit.sh \
|
||||
$out/includes/GlobalFunctions.php
|
||||
'';
|
||||
};
|
||||
|
||||
mediawikiScripts = pkgs.runCommand "mediawiki-${config.id}-scripts" {
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do
|
||||
makeWrapper ${php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \
|
||||
--add-flags ${mediawikiRoot}/maintenance/$i
|
||||
done
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
extraConfig =
|
||||
''
|
||||
${optionalString config.enableUploads ''
|
||||
Alias ${config.urlPrefix}/images ${config.uploadDir}
|
||||
|
||||
<Directory ${config.uploadDir}>
|
||||
${allGranted}
|
||||
Options -Indexes
|
||||
</Directory>
|
||||
''}
|
||||
|
||||
${if config.urlPrefix != "" then "Alias ${config.urlPrefix} ${mediawikiRoot}" else ''
|
||||
RewriteEngine On
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
|
||||
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
|
||||
${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedDirs}
|
||||
${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedFiles}
|
||||
RewriteRule ${if config.enableUploads
|
||||
then "!^/images"
|
||||
else "^.*\$"
|
||||
} %{DOCUMENT_ROOT}/${if config.articleUrlPrefix == ""
|
||||
then ""
|
||||
else "${config.articleUrlPrefix}/"
|
||||
}index.php [L]
|
||||
''}
|
||||
|
||||
<Directory ${mediawikiRoot}>
|
||||
${allGranted}
|
||||
DirectoryIndex index.php
|
||||
</Directory>
|
||||
|
||||
${optionalString (config.articleUrlPrefix != "") ''
|
||||
Alias ${config.articleUrlPrefix} ${mediawikiRoot}/index.php
|
||||
''}
|
||||
'';
|
||||
|
||||
documentRoot = if config.urlPrefix == "" then mediawikiRoot else null;
|
||||
|
||||
enablePHP = true;
|
||||
|
||||
options = {
|
||||
|
||||
id = mkOption {
|
||||
default = "main";
|
||||
description = ''
|
||||
A unique identifier necessary to keep multiple MediaWiki server
|
||||
instances on the same machine apart. This is used to
|
||||
disambiguate the administrative scripts, which get names like
|
||||
mediawiki-$id-change-password.
|
||||
'';
|
||||
};
|
||||
|
||||
dbType = mkOption {
|
||||
default = "postgres";
|
||||
example = "mysql";
|
||||
description = "Database type.";
|
||||
};
|
||||
|
||||
dbName = mkOption {
|
||||
default = "mediawiki";
|
||||
description = "Name of the database that holds the MediaWiki data.";
|
||||
};
|
||||
|
||||
dbServer = mkOption {
|
||||
default = ""; # use a Unix domain socket
|
||||
example = "10.0.2.2";
|
||||
description = ''
|
||||
The location of the database server. Leave empty to use a
|
||||
database server running on the same machine through a Unix
|
||||
domain socket.
|
||||
'';
|
||||
};
|
||||
|
||||
dbUser = mkOption {
|
||||
default = "mediawiki";
|
||||
description = "The user name for accessing the database.";
|
||||
};
|
||||
|
||||
dbPassword = mkOption {
|
||||
default = "";
|
||||
example = "foobar";
|
||||
description = ''
|
||||
The password of the database user. Warning: this is stored in
|
||||
cleartext in the Nix store!
|
||||
'';
|
||||
};
|
||||
|
||||
emergencyContact = mkOption {
|
||||
default = serverInfo.serverConfig.adminAddr;
|
||||
example = "admin@example.com";
|
||||
description = ''
|
||||
Emergency contact e-mail address. Defaults to the Apache
|
||||
admin address.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordSender = mkOption {
|
||||
default = serverInfo.serverConfig.adminAddr;
|
||||
example = "password@example.com";
|
||||
description = ''
|
||||
E-mail address from which password confirmations originate.
|
||||
Defaults to the Apache admin address.
|
||||
'';
|
||||
};
|
||||
|
||||
siteName = mkOption {
|
||||
default = "MediaWiki";
|
||||
example = "Foobar Wiki";
|
||||
description = "Name of the wiki";
|
||||
};
|
||||
|
||||
logo = mkOption {
|
||||
default = "";
|
||||
example = "/images/logo.png";
|
||||
description = "The URL of the site's logo (which should be a 135x135px image).";
|
||||
};
|
||||
|
||||
urlPrefix = mkOption {
|
||||
default = "/w";
|
||||
description = ''
|
||||
The URL prefix under which the Mediawiki service appears.
|
||||
'';
|
||||
};
|
||||
|
||||
articleUrlPrefix = mkOption {
|
||||
default = "/wiki";
|
||||
example = "";
|
||||
description = ''
|
||||
The URL prefix under which article pages appear,
|
||||
e.g. http://server/wiki/Page. Leave empty to use the main URL
|
||||
prefix, e.g. http://server/w/index.php?title=Page.
|
||||
'';
|
||||
};
|
||||
|
||||
enableUploads = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable file uploads.";
|
||||
};
|
||||
|
||||
uploadDir = mkOption {
|
||||
default = throw "You must specify `uploadDir'.";
|
||||
example = "/data/mediawiki-upload";
|
||||
description = "The directory that stores uploaded files.";
|
||||
};
|
||||
|
||||
defaultSkin = mkOption {
|
||||
default = "";
|
||||
example = "nostalgia";
|
||||
description = "Set this value to change the default skin used by MediaWiki.";
|
||||
};
|
||||
|
||||
skins = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.path;
|
||||
description =
|
||||
''
|
||||
List of paths whose content is copied to the ‘skins’
|
||||
subdirectory of the MediaWiki installation.
|
||||
'';
|
||||
};
|
||||
|
||||
extensions = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.path;
|
||||
description =
|
||||
''
|
||||
List of paths whose content is copied to the 'extensions'
|
||||
subdirectory of the MediaWiki installation.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example =
|
||||
''
|
||||
$wgEnableEmail = false;
|
||||
'';
|
||||
description = ''
|
||||
Any additional text to be appended to MediaWiki's
|
||||
configuration file. This is a PHP script. For configuration
|
||||
settings, see <link xlink:href='https://www.mediawiki.org/wiki/Manual:Configuration_settings'/>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
extraPath = [ mediawikiScripts ];
|
||||
|
||||
# !!! Need to specify that Apache has a dependency on PostgreSQL!
|
||||
|
||||
startupScript = pkgs.writeScript "mediawiki_startup.sh"
|
||||
# Initialise the database automagically if we're using a Postgres
|
||||
# server on localhost.
|
||||
(optionalString (config.dbType == "postgres" && config.dbServer == "") ''
|
||||
if ! ${pkgs.postgresql}/bin/psql -l | grep -q ' ${config.dbName} ' ; then
|
||||
${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true
|
||||
${pkgs.postgresql}/bin/createdb "${config.dbName}" -O "${config.dbUser}"
|
||||
( echo 'CREATE LANGUAGE plpgsql;'
|
||||
cat ${mediawikiRoot}/maintenance/postgres/tables.sql
|
||||
echo 'CREATE TEXT SEARCH CONFIGURATION public.default ( COPY = pg_catalog.english );'
|
||||
echo COMMIT
|
||||
) | ${pkgs.postgresql}/bin/psql -U "${config.dbUser}" "${config.dbName}"
|
||||
fi
|
||||
${php}/bin/php ${mediawikiRoot}/maintenance/update.php
|
||||
'');
|
||||
|
||||
robotsEntries = optionalString (config.articleUrlPrefix != "")
|
||||
''
|
||||
User-agent: *
|
||||
Disallow: ${config.urlPrefix}/
|
||||
Disallow: ${config.articleUrlPrefix}/Special:Search
|
||||
Disallow: ${config.articleUrlPrefix}/Special:Random
|
||||
'';
|
||||
|
||||
}
|
|
@ -24,14 +24,6 @@ with lib;
|
|||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
description = ''
|
||||
Port for the server. Option will be removed, use <option>listen</option> instead.
|
||||
'';
|
||||
};
|
||||
|
||||
listen = mkOption {
|
||||
type = types.listOf (types.submodule (
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue