3
0
Fork 0
forked from mirrors/nixpkgs

Merge branch 'staging' into upstream-wasm-cross-nixpkgs-4

This commit is contained in:
Divam Narula 2020-08-16 10:13:57 +05:30 committed by GitHub
commit 818d24c9db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1494 changed files with 29458 additions and 14356 deletions

View file

@ -66,14 +66,24 @@ insert_final_newline = unset
[nixos/modules/services/networking/ircd-hybrid/*.{conf,in}]
trim_trailing_whitespace = unset
[nixos/tests/systemd-networkd-vrf.nix]
trim_trailing_whitespace = unset
[pkgs/applications/editors/emacs-modes/recipes-archive-melpa.json]
indent_size = unset
[pkgs/build-support/dotnetenv/Wrapper/**.*]
[pkgs/build-support/dotnetenv/Wrapper/**]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
[pkgs/build-support/upstream-updater/**]
trim_trailing_whitespace = unset
[pkgs/development/compilers/elm/registry.dat]
end_of_line = unset
insert_final_newline = unset
[pkgs/development/lisp-modules/quicklisp-to-nix.nix]
indent_size = unset

5
.github/CODEOWNERS vendored
View file

@ -202,3 +202,8 @@
# Blockchains
/pkgs/applications/blockchains @mmahut
# Go
/pkgs/development/compilers/go @kalbasit @Mic92 @zowoq
/pkgs/development/go-modules @kalbasit @Mic92 @zowoq
/pkgs/development/go-packages @kalbasit @Mic92 @zowoq

View file

@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View file

@ -1,24 +0,0 @@
name: "Checking EditorConfig"
on:
pull_request:
branches:
- master
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: technote-space/get-diff-action@v2.0.3
- name: Checking EditorConfig
env:
VERSION: "2.1.0"
OS: "linux"
ARCH: "amd64"
run: |
curl -sSf -O -L -C - https://github.com/editorconfig-checker/editorconfig-checker/releases/download/$VERSION/ec-$OS-$ARCH.tar.gz && \
tar xzf ec-$OS-$ARCH.tar.gz && \
./bin/ec-$OS-$ARCH -disable-indentation ${{ env.GIT_DIFF }}

View file

@ -1,31 +0,0 @@
name: "Wait for ofborg"
on:
pull_request:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Wait for ofborg CI
run: |
# wait for ~30min...
# ..in future a better fix would be to make ofborg mark CI as pending right away.
for i in $(seq 360); do
res=$(curl --silent \
-H "Accept: application/vnd.github.antiope-preview+json" \
-H "Authorization: token ${GITHUB_TOKEN}" \
"https://api.github.com/repos/NixOS/nixpkgs/commits/${COMMIT}/check-runs" | \
jq ".check_runs | map(.app) | map(.id) | contains([${OFBORG_APP_ID}])")
if [[ "$res" == "true" ]]; then
exit 0
fi
sleep 5
echo "."
done
echo "Timeout!"
exit 1
# ofborg is not checking forks.
if: github.repository_owner == 'NixOS'
env:
GITHUB_TOKEN: ${{ github.token }}
COMMIT: ${{ github.event.pull_request.head.sha }}
OFBORG_APP_ID: 20500

View file

@ -40,7 +40,9 @@ pet = buildGoModule rec {
subPackages = [ "." ]; <co xml:id='ex-buildGoModule-2' />
runVend = true; <co xml:id='ex-buildGoModule-3' />
deleteVendor = true; <co xml:id='ex-buildGoModule-3' />
runVend = true; <co xml:id='ex-buildGoModule-4' />
meta = with lib; {
description = "Simple command-line snippet manager, written in Go";
@ -67,6 +69,11 @@ pet = buildGoModule rec {
</para>
</callout>
<callout arearefs='ex-buildGoModule-3'>
<para>
<varname>deleteVendor</varname> removes the pre-existing vendor directory and fetches the dependencies. This should only be used if the dependencies included in the vendor folder are broken or incomplete.
</para>
</callout>
<callout arearefs='ex-buildGoModule-4'>
<para>
<varname>runVend</varname> runs the vend command to generate the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build.
</para>

View file

@ -640,8 +640,8 @@ and in this case the `python38` interpreter is automatically used.
### Interpreters
Versions 2.7, 3.5, 3.6, 3.7 and 3.8 of the CPython interpreter are available as
respectively `python27`, `python35`, `python36`, `python37` and `python38`. The
Versions 2.7, 3.6, 3.7 and 3.8 of the CPython interpreter are available as
respectively `python27`, `python36`, `python37` and `python38`. The
aliases `python2` and `python3` correspond to respectively `python27` and
`python38`. The default interpreter, `python`, maps to `python2`. The PyPy
interpreters compatible with Python 2.7 and 3 are available as `pypy27` and
@ -689,15 +689,16 @@ attribute set is created for each available Python interpreter. The available
sets are
* `pkgs.python27Packages`
* `pkgs.python35Packages`
* `pkgs.python36Packages`
* `pkgs.python37Packages`
* `pkgs.python38Packages`
* `pkgs.python39Packages`
* `pkgs.pypyPackages`
and the aliases
* `pkgs.python2Packages` pointing to `pkgs.python27Packages`
* `pkgs.python3Packages` pointing to `pkgs.python37Packages`
* `pkgs.python3Packages` pointing to `pkgs.python38Packages`
* `pkgs.pythonPackages` pointing to `pkgs.python2Packages`
#### `buildPythonPackage` function

View file

@ -178,26 +178,40 @@ self: super:
<para>
<link
xlink:href="https://software.intel.com/en-us/mkl">Intel
MKL</link> (only works on x86 architecture, unfree)
MKL</link> (only works on the x86_64 architecture, unfree)
</para>
<para>
The Nixpkgs attribute is <literal>mkl</literal>.
</para>
</listitem>
<listitem>
<para>
<link
xlink:href="https://developer.amd.com/amd-aocl/blas-library/">AMD
BLIS/LIBFLAME</link> (optimized for modern AMD x86_64 CPUs)
</para>
<para>
The AMD BLIS library, with attribute <literal>amd-blis</literal>,
provides a BLAS implementation. The complementary AMD LIBFLAME
library, with attribute <literal>amd-libflame</literal>, provides
a LAPACK implementation.
</para>
</listitem>
</itemizedlist>
<para>
Introduced in <link
xlink:href="https://github.com/NixOS/nixpkgs/pull/83888">PR
#83888</link>, we are able to override the blas and lapack
packages to use different implementations, through the
blasProvider and lapackProvider argument. This can be used
#83888</link>, we are able to override the <literal>blas</literal>
and <literal>lapack</literal> packages to use different implementations,
through the <literal>blasProvider</literal> and
<literal>lapackProvider</literal> argument. This can be used
to select a different provider. BLAS providers will have
symlinks in <literal>$out/lib/libblas.so.3</literal> and
<literal>$out/lib/libcblas.so.3</literal> to their respective
BLAS libraries. Likewise, LAPACK providers will have symlinks
in <literal>$out/lib/liblapack.so.3</literal> and
<literal>$out/lib/liblapacke.so.3</literal> to their respective
LAPCK libraries. For example, Intel MKL is both a BLAS and
LAPACK libraries. For example, Intel MKL is both a BLAS and
LAPACK provider. An overlay can be created to use Intel MKL
that looks like:
</para>
@ -216,8 +230,9 @@ self: super:
<para>
This overlay uses Intels MKL library for both BLAS and LAPACK
interfaces. Note that the same can be accomplished at runtime
using <literal>LD_LIBRARY_PATH</literal> of libblas.so.3 and
liblapack.so.3. For instance:
using <literal>LD_LIBRARY_PATH</literal> of
<literal>libblas.so.3</literal> and
<literal>liblapack.so.3</literal>. For instance:
</para>
<programlisting>
$ LD_LIBRARY_PATH=$(nix-build -A mkl)/lib:$LD_LIBRARY_PATH nix-shell -p octave --run octave

View file

@ -110,6 +110,11 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
fullName = ''BSD 4-clause "Original" or "Old" License'';
};
bsdProtection = spdx {
spdxId = "BSD-Protection";
fullName = "BSD Protection License";
};
bsl11 = {
fullName = "Business Source License 1.1";
url = "https://mariadb.com/bsl11";

View file

@ -38,7 +38,7 @@ let
"js-ghcjs"
"aarch64-genode" "x86_64-genode"
"aarch64-genode" "i686-genode" "x86_64-genode"
];
allParsed = map parse.mkSystemFromString all;

View file

@ -15,14 +15,14 @@ in with lib.systems.doubles; lib.runTests {
testall = mseteq all (linux ++ darwin ++ freebsd ++ openbsd ++ netbsd ++ illumos ++ wasi ++ windows ++ embedded ++ js ++ genode ++ redox);
testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-none" "armv7a-linux" "armv7l-linux" "arm-none" "armv7a-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ];
testmips = mseteq mips [ "mipsel-linux" ];
testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ];
testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ];
testdarwin = mseteq darwin [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ];
testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ];
testgenode = mseteq genode [ "aarch64-genode" "x86_64-genode" ];
testgenode = mseteq genode [ "aarch64-genode" "i686-genode" "x86_64-genode" ];
testredox = mseteq redox [ "x86_64-redox" ];
testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */);
testillumos = mseteq illumos [ "x86_64-solaris" ];

View file

@ -42,7 +42,7 @@
*/
{
"0x4A6F" = {
email = "0x4A6F@shackspace.de";
email = "mail-maintainer@0x4A6F.dev";
name = "Joachim Ernst";
github = "0x4A6F";
githubId = 9675338;
@ -1446,6 +1446,12 @@
fingerprint = "099E 3F97 FA08 3D47 8C75 EBEC E0EB AD78 F019 0BD9";
}];
};
chiroptical = {
email = "chiroptical@gmail.com";
github = "chiroptical";
githubId = 3086255;
name = "Barry Moore II";
};
chkno = {
email = "chuck@intelligence.org";
github = "chkno";
@ -1760,6 +1766,16 @@
githubId = 490965;
name = "Craig Swank";
};
cust0dian = {
email = "serg@effectful.software";
github = "cust0dian";
githubId = 389387;
name = "Serg Nesterov";
keys = [{
longkeyid = "rsa4096/0x1512F6EB84AECC8C";
fingerprint = "6E7D BA30 DB5D BA60 693C 3BE3 1512 F6EB 84AE CC8C";
}];
};
cwoac = {
email = "oliver@codersoffortune.net";
github = "cwoac";
@ -2170,6 +2186,16 @@
githubId = 974130;
name = "David Pätzel";
};
dpausp = {
email = "dpausp@posteo.de";
github = "dpausp";
githubId = 1965950;
name = "Tobias Stenzel";
keys = [{
longkeyid = "rsa2048/0x78C7DD40DF23FB16";
fingerprint = "4749 0887 CF3B 85A1 6355 C671 78C7 DD40 DF23 FB16";
}];
};
dpflug = {
email = "david@pflug.email";
github = "dpflug";
@ -2404,6 +2430,12 @@
githubId = 1753498;
name = "Dejan Lukan";
};
elliottvillars = {
email = "elliottvillars@gmail.com";
github = "elliottvillars";
githubId = 48104179;
name = "Elliott Villars";
};
eliasp = {
email = "mail@eliasprobst.eu";
github = "eliasp";
@ -3198,6 +3230,12 @@
githubId = 6768842;
name = "Joris Guyonvarch";
};
gvolpe = {
email = "volpegabriel@gmail.com";
github = "gvolpe";
githubId = 443978;
name = "Gabriel Volpe";
};
hakuch = {
email = "hakuch@gmail.com";
github = "hakuch";
@ -3916,6 +3954,12 @@
githubId = 8735102;
name = "John Ramsden";
};
johntitor = {
email = "huyuumi.dev@gmail.com";
github = "JohnTitor";
githubId = 25030997;
name = "Yuki Okushi";
};
jojosch = {
name = "Johannes Schleifenbaum";
email = "johannes@js-webcoding.de";
@ -4623,6 +4667,12 @@
fingerprint = "7FE2 113A A08B 695A C8B8 DDE6 AE53 B4C2 E58E DD45";
}];
};
lf- = {
email = "nix-maint@lfcode.ca";
github = "lf-";
githubId = 6652840;
name = "Jade";
};
lheckemann = {
email = "git@sphalerite.org";
github = "lheckemann";
@ -7180,6 +7230,16 @@
githubId = 132835;
name = "Samuel Dionne-Riel";
};
samuelgrf = {
email = "git@samuelgrf.com";
github = "samuelgrf";
githubId = 67663538;
name = "Samuel Gräfenstein";
keys = [{
longkeyid = "rsa4096/0xEF76A063F15C63C8";
fingerprint = "FF24 5832 8FAF 4660 18C6 186E EF76 A063 F15C 63C8";
}];
};
samuelrivas = {
email = "samuelrivas@gmail.com";
github = "samuelrivas";
@ -9065,6 +9125,16 @@
email = "zef@zef.me";
name = "Zef Hemel";
};
zeratax = {
email = "mail@zera.tax";
github = "ZerataX";
githubId = 5024958;
name = "Jona Abdinghoff";
keys = [{
longkeyid = "rsa4096/0x8333735E784DF9D4";
fingerprint = "44F7 B797 9D3A 27B1 89E0 841E 8333 735E 784D F9D4";
}];
};
zfnmxt = {
name = "zfnmxt";
email = "zfnmxt@zfnmxt.com";
@ -9257,4 +9327,10 @@
github = "deifactor";
githubId = 30192992;
};
fzakaria = {
name = "Farid Zakaria";
email = "farid.m.zakaria@gmail.com";
github = "fzakaria";
githubId = 605070;
};
}

View file

@ -79,5 +79,4 @@ say,,,,,
std__debug,std._debug,,,,
std_normalize,std.normalize,,,,
stdlib,,,,,vyp
pulseaudio,,,,,doronbehar
vstruct,,,,,

1 # nix name luarocks name server version luaversion maintainers
79 std__debug std._debug
80 std_normalize std.normalize
81 stdlib vyp
pulseaudio doronbehar
82 vstruct

View file

@ -59,6 +59,16 @@ with lib.maintainers; {
scope = "Maintain GNOME desktop environment and platform.";
};
jitsi = {
members = [
mmilata
petabyteboy
prusnak
ryantm
];
scope = "Maintain Jitsi.";
};
matrix = {
members = [
ma27

View file

@ -100,6 +100,35 @@ ROCR_EXT_DIR=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A rocm-runtime-ext`/lib
Image support Yes</screen>
</para>
</section>
<section xml:id="sec-gpu-accel-opencl-intel">
<title>Intel</title>
<para>
<link
xlink:href="https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units#Gen8">Intel
Gen8 and later GPUs</link> are supported by the Intel NEO OpenCL
runtime that is provided by the
<package>intel-compute-runtime</package> package. For Gen7 GPUs,
the deprecated Beignet runtime can be used, which is provided
by the <package>beignet</package> package. The proprietary Intel
OpenCL runtime, in the <package>intel-ocl</package> package, is
an alternative for Gen7 GPUs.
</para>
<para>
The <package>intel-compute-runtime</package>, <package>beignet</package>,
or <package>intel-ocl</package> package can be added to
<xref linkend="opt-hardware.opengl.extraPackages"/> to enable OpenCL
support. For example, for Gen8 and later GPUs, the following
configuration can be used:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
intel-compute-runtime
];</programlisting>
</para>
</section>
</section>
<section xml:id="sec-gpu-accel-vulkan">
@ -190,4 +219,63 @@ GPU1:
</para>
</section>
</section>
<section xml:id="sec-gpu-accel-common-issues">
<title>Common issues</title>
<section xml:id="sec-gpu-accel-common-issues-permissions">
<title>User permissions</title>
<para>
Except where noted explicitly, it should not be necessary to
adjust user permissions to use these acceleration APIs. In the default
configuration, GPU devices have world-read/write permissions
(<filename>/dev/dri/renderD*</filename>) or are tagged as
<code>uaccess</code> (<filename>/dev/dri/card*</filename>). The
access control lists of devices with the <varname>uaccess</varname>
tag will be updated automatically when a user logs in through
<command>systemd-logind</command>. For example, if the user
<emphasis>jane</emphasis> is logged in, the access control list
should look as follows:
<screen><prompt>$</prompt> getfacl /dev/dri/card0
# file: dev/dri/card0
# owner: root
# group: video
user::rw-
user:jane:rw-
group::rw-
mask::rw-
other::---</screen>
If you disabled (this functionality of) <command>systemd-logind</command>,
you may need to add the user to the <code>video</code> group and
log in again.
</para>
</section>
<section xml:id="sec-gpu-accel-common-issues-mixing-nixpkgs">
<title>Mixing different versions of nixpkgs</title>
<para>
The <emphasis>Installable Client Driver</emphasis> (ICD)
mechanism used by OpenCL and Vulkan loads runtimes into its address
space using <code>dlopen</code>. Mixing an ICD loader mechanism and
runtimes from different version of nixpkgs may not work. For example,
if the ICD loader uses an older version of <package>glibc</package>
than the runtime, the runtime may not be loadable due to
missing symbols. Unfortunately, the loader will generally be quiet
about such issues.
</para>
<para>
If you suspect that you are running into library version mismatches
between an ICL loader and a runtime, you could run an application with
the <code>LD_DEBUG</code> variable set to get more diagnostic
information. For example, OpenCL can be tested with
<code>LD_DEBUG=files clinfo</code>, which should report missing
symbols.
</para>
</section>
</section>
</chapter>

View file

@ -216,12 +216,12 @@ start_all()
</varlistentry>
<varlistentry>
<term>
<methodname>send_keys</methodname>
<methodname>send_key</methodname>
</term>
<listitem>
<para>
Simulate pressing keys on the virtual keyboard, e.g.,
<literal>send_keys("ctrl-alt-delete")</literal>.
<literal>send_key("ctrl-alt-delete")</literal>.
</para>
</listitem>
</varlistentry>
@ -232,7 +232,7 @@ start_all()
<listitem>
<para>
Simulate typing a sequence of characters on the virtual keyboard, e.g.,
<literal>send_keys("foobar\n")</literal> will type the string
<literal>send_chars("foobar\n")</literal> will type the string
<literal>foobar</literal> followed by the Enter key.
</para>
</listitem>

View file

@ -42,6 +42,11 @@
PHP now defaults to PHP 7.4, updated from 7.3.
</para>
</listitem>
<listitem>
<para>
PHP 7.2 is no longer supported due to upstream not supporting this version for the entire lifecycle of the 20.09 release.
</para>
</listitem>
<listitem>
<para>
Python 3 now defaults to Python 3.8 instead of 3.7.
@ -109,6 +114,17 @@ systemd.services.mysql.serviceConfig.ProtectHome = lib.mkForce "read-only";
systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
</programlisting>
</para>
<para>
The MySQL service no longer runs its <literal>systemd</literal> service startup script as <literal>root</literal> anymore. A dedicated non <literal>root</literal>
super user account is required for operation. This means users with an existing MySQL or MariaDB database server are required to run the following SQL statements
as a super admin user before upgrading:
<programlisting>
CREATE USER IF NOT EXISTS 'mysql'@'localhost' identified with unix_socket;
GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
</programlisting>
If you use MySQL instead of MariaDB please replace <literal>unix_socket</literal> with <literal>auth_socket</literal>. If you have changed the value of <xref linkend="opt-services.mysql.user"/>
from the default of <literal>mysql</literal> to a different user please change <literal>'mysql'@'localhost'</literal> to the corresponding user instead.
</para>
</listitem>
<listitem>
<para>
@ -135,6 +151,11 @@ systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
The various documented workarounds to use steam have been converted to a module. <varname>programs.steam.enable</varname> enables steam, controller support and the workarounds.
</para>
</listitem>
<listitem>
<para>
Support for built-in LCDs in various pieces of Logitech hardware (keyboards and USB speakers). <varname>hardware.logitech.lcd.enable</varname> enables support for all hardware supported by the g15daemon project.
</para>
</listitem>
</itemizedlist>
</section>
@ -518,6 +539,46 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<listitem>
<para>
In the <literal>resilio</literal> module, <xref linkend="opt-services.resilio.httpListenAddr"/> has been changed to listen to <literal>[::1]</literal> instead of <literal>0.0.0.0</literal>.
</para>
</listitem>
<listitem>
<para>
Users of <link xlink:href="http://openafs.org">OpenAFS 1.6</link> must
upgrade their services to OpenAFS 1.8! In this release, the OpenAFS package
version 1.6.24 is marked broken but can be used during transition to
OpenAFS 1.8.x. Use the options
<option>services.openafsClient.packages.module</option>,
<option>services.openafsClient.packages.programs</option> and
<option>services.openafsServer.package</option> to select a different
OpenAFS package. OpenAFS 1.6 will be removed in the next release. The
package <literal>openafs</literal> and the service options will then
silently point to the OpenAFS 1.8 release.
</para>
<para>
See also the OpenAFS <link
xlink:href="http://docs.openafs.org/AdminGuide/index.html">Administrator
Guide</link> for instructions. Beware of the following when updating
servers:
<itemizedlist>
<listitem>
<para>
The storage format of the server key has changed and the key must be converted before running the new release.
</para>
</listitem>
<listitem>
<para>
When updating multiple database servers, turn off the database servers
from the highest IP down to the lowest with resting periods in
between. Start up in reverse order. Do not concurrently run database
servers working with different OpenAFS releases!
</para>
</listitem>
<listitem>
<para>
Update servers first, then clients.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
@ -544,21 +605,42 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
to be used for every display-manager in NixOS.
</para>
</listitem>
<listitem>
<listitem>
<para>
The <literal>bitcoind</literal> module has changed to multi-instance, using submodules.
Therefore, it is now mandatory to name each instance, e.g.:
Therefore, it is now mandatory to name each instance.
To use this new multi-instance config with an existing bitcoind data directory and user,
you have to adjust the original config, e.g.:
<programlisting>
services.bitcoind = {
enable = true;
};
services.bitcoind = {
enable = true;
extraConfig = "...";
...
};
</programlisting>
requires a name now:
To something similar:
<programlisting>
services.bitcoind."example-mainnet" = {
enable = true;
};
services.bitcoind.mainnet = {
enable = true;
dataDir = "/var/lib/bitcoind";
user = "bitcoin";
extraConfig = "...";
...
};
</programlisting>
The key settings are:
<itemizedlist>
<listitem>
<para>
<literal>dataDir</literal> - to continue using the same data directory.
</para>
</listitem>
<listitem>
<para>
<literal>user</literal> - to continue using the same user so that bitcoind maintains access to its files.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
@ -567,6 +649,48 @@ services.bitcoind."example-mainnet" = {
When updating Graylog from a version before 3.3.3 make sure to check the Graylog <link xlink:href="https://www.graylog.org/post/announcing-graylog-v3-3-3">release info</link> for information on how to avoid the issue.
</para>
</listitem>
<listitem>
<para>
The <literal>dokuwiki</literal> module has changed to multi-instance, using submodules.
Therefore, it is now mandatory to name each instance. Moreover, forcing SSL by default has been dropped, so
<literal>nginx.forceSSL</literal> and <literal>nginx.enableACME</literal> are no longer set to <literal>true</literal>.
To continue using your service with the original SSL settings, you have to adjust the original config, e.g.:
<programlisting>
services.dokuwiki = {
enable = true;
...
};
</programlisting>
To something similar:
<programlisting>
services.dokuwiki."mywiki" = {
enable = true;
nginx = {
forceSSL = true;
enableACME = true;
};
...
};
</programlisting>
The base package has also been upgraded to the 2020-07-29 "Hogfather" release. Plugins might be incompatible or require upgrading.
</para>
</listitem>
<listitem>
<para>
The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your
<xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.09</literal> or below
should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly
set this value to maintain compatibility:
<programlisting>
services.postgresql.dataDir = "/var/db/postgresql";
</programlisting>
</para>
</listitem>
<listitem>
<para>
The USBGuard module now removes options and instead hardcodes values for <literal>IPCAccessControlFiles</literal>, <literal>ruleFiles</literal>, and <literal>auditFilePath</literal>. Audit logs can be found in the journal.
</para>
</listitem>
</itemizedlist>
</section>
@ -602,6 +726,11 @@ services.bitcoind."example-mainnet" = {
The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
</para>
</listitem>
<listitem>
<para>
<literal>buildGoModule</literal> <literal>doCheck</literal> now defaults to <literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
Packages built using <literal>buildRustPackage</literal> now use <literal>release</literal>
@ -659,6 +788,37 @@ services.bitcoind."example-mainnet" = {
was removed, as udev gained native support to handle FIDO security tokens.
</para>
</listitem>
<listitem>
<para>
The <literal>services.transmission</literal> module
was enhanced with the new options:
<xref linkend="opt-services.transmission.credentialsFile"/>,
<xref linkend="opt-services.transmission.openFirewall"/>,
and <xref linkend="opt-services.transmission.performanceNetParameters"/>.
</para>
<para>
<literal>transmission-daemon</literal> is now started with additional systemd sandbox/hardening options for better security.
Please <link xlink:href="https://github.com/NixOS/nixpkgs/issues">report</link>
any use case where this is not working well.
In particular, the <literal>RootDirectory</literal> option newly set
forbids uploading or downloading a torrent outside of the default directory
configured at <link linkend="opt-services.transmission.settings">settings.download-dir</link>.
If you really need Transmission to access other directories,
you must include those directories into the <literal>BindPaths</literal> of the service:
<programlisting>
systemd.services.transmission.serviceConfig.BindPaths = [ "/path/to/alternative/download-dir" ];
</programlisting>
</para>
<para>
Also, connection to the RPC (Remote Procedure Call) of <literal>transmission-daemon</literal>
is now only available on the local network interface by default.
Use:
<programlisting>
services.transmission.settings.rpc-bind-address = "0.0.0.0";
</programlisting>
to get the previous behavior of listening on all network interfaces.
</para>
</listitem>
<listitem>
<para>
With this release <literal>systemd-networkd</literal> (when enabled through <xref linkend="opt-networking.useNetworkd"/>)
@ -741,6 +901,12 @@ services.bitcoind."example-mainnet" = {
There are no functional changes, however this may require updating some configurations to use correct types for all attributes.
</para>
</listitem>
<listitem>
<para>
The <literal>fontconfig</literal> module stopped generating fontconfig 2.10.x config and cache.
Fontconfig 2.10.x was removed from Nixpkgs - it hasn't been used in any nixpkgs package anymore.
</para>
</listitem>
</itemizedlist>
</section>
</section>

View file

@ -46,7 +46,10 @@ pkgs.stdenv.mkDerivation {
(
GLOBIGNORE=".:.."
shopt -u dotglob
cp -a --reflink=auto ./files/* -t ./rootImage/
for f in ./files/*; do
cp -a --reflink=auto -t ./rootImage/ "$f"
done
)
# Also include a manifest of the closures in a format suitable for nix-store --load-db

View file

@ -36,7 +36,7 @@ let
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; }
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
);
# Generate DocBook documentation for a list of packages. This is
@ -48,7 +48,7 @@ let
# - a list: that will be interpreted as an attribute path from `pkgs`,
# - an attrset: that can specify `name`, `path`, `package`, `comment`
# (either of `name`, `path` is required, the rest are optional).
genRelatedPackages = packages:
genRelatedPackages = packages: optName:
let
unpack = p: if lib.isString p then { name = p; }
else if lib.isList p then { path = p; }
@ -58,7 +58,7 @@ let
title = args.title or null;
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [ args.name ];
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}' found while evaluating `relatedPackages' of option `${optName}'") pkgs);
in "<listitem>"
+ "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
+ lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"

View file

@ -8,17 +8,17 @@ use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
sub new {
my ($class) = @_;
my $logFile = defined $ENV{LOGFILE} ? "$ENV{LOGFILE}" : "/dev/null";
my $log = new XML::Writer(OUTPUT => new IO::File(">$logFile"));
my $self = {
log => $log,
logQueue => Thread::Queue->new()
};
$self->{log}->startTag("logfile");
bless $self, $class;
return $self;
}

View file

@ -1 +1 @@
azure
azure

View file

@ -20,7 +20,7 @@ $ ./upload-image.sh ./examples/basic/image.nix
+ nix-build ./examples/basic/image.nix --out-link azure
/nix/store/qdpzknpskzw30vba92mb24xzll1dqsmd-azure-image
...
95.5 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 2-sec Throughput (Mb/s): 932.9565
95.5 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 2-sec Throughput (Mb/s): 932.9565
...
/subscriptions/aff271ee-e9be-4441-b9bb-42f5af4cbaeb/resourceGroups/nixos-images/providers/Microsoft.Compute/images/azure-image-todo-makethisbetter
```

View file

@ -37,8 +37,8 @@ if ! az disk show -g "${group}" -n "${img_name}" &>/dev/null; then
)"
azcopy copy "${img_file}" "${sasurl}" \
--blob-type PageBlob
--blob-type PageBlob
az disk revoke-access \
--resource-group "${group}" \
--name "${img_name}"

View file

@ -7,18 +7,18 @@ with lib;
type = types.bool;
default = true;
description = ''
Whether to install files to support the
Whether to install files to support the
<link xlink:href="https://www.freedesktop.org/software/appstream/docs/index.html">AppStream metadata specification</link>.
'';
};
};
config = mkIf config.appstream.enable {
environment.pathsToLink = [
environment.pathsToLink = [
# per component metadata
"/share/metainfo"
"/share/metainfo"
# legacy path for above
"/share/appdata"
"/share/appdata"
];
};

View file

@ -1,11 +1,6 @@
/*
NixOS support 2 fontconfig versions, "support" and "latest".
- "latest" refers to default fontconfig package (pkgs.fontconfig).
configuration files are linked to /etc/fonts/VERSION/conf.d/
- "support" refers to supportPkg (pkgs."fontconfig_${supportVersion}").
configuration files are linked to /etc/fonts/conf.d/
Configuration files are linked to /etc/fonts/${pkgs.fontconfig.configVersion}/conf.d/
This module generates a package containing configuration files and link it in /etc/fonts.
@ -22,40 +17,21 @@ let
cfg = config.fonts.fontconfig;
fcBool = x: "<bool>" + (boolToString x) + "</bool>";
# back-supported fontconfig version and package
# version is used for font cache generation
supportVersion = "210";
supportPkg = pkgs."fontconfig_${supportVersion}";
# latest fontconfig version and package
# version is used for configuration folder name, /etc/fonts/VERSION/
# note: format differs from supportVersion and can not be used with makeCacheConf
latestVersion = pkgs.fontconfig.configVersion;
latestPkg = pkgs.fontconfig;
# supported version fonts.conf
supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; };
pkg = pkgs.fontconfig;
# configuration file to read fontconfig cache
# version dependent
# priority 0
cacheConfSupport = makeCacheConf { version = supportVersion; };
cacheConfLatest = makeCacheConf {};
cacheConf = makeCacheConf {};
# generate the font cache setting file for a fontconfig version
# use latest when no version is passed
# generate the font cache setting file
# When cross-compiling, we cant generate the cache, so we skip the
# <cachedir> part. fontconfig still works but is a little slower in
# looking things up.
makeCacheConf = { version ? null }:
makeCacheConf = { }:
let
fcPackage = if version == null
then "fontconfig"
else "fontconfig_${version}";
makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
cache = makeCache pkgs.${fcPackage};
cache32 = makeCache pkgs.pkgsi686Linux.${fcPackage};
cache = makeCache pkgs.fontconfig;
cache32 = makeCache pkgs.pkgsi686Linux.fontconfig;
in
pkgs.writeText "fc-00-nixos-cache.conf" ''
<?xml version='1.0'?>
@ -200,59 +176,52 @@ let
confPkg = pkgs.runCommand "fontconfig-conf" {
preferLocalBuild = true;
} ''
support_folder=$out/etc/fonts/conf.d
latest_folder=$out/etc/fonts/${latestVersion}/conf.d
mkdir -p $support_folder
mkdir -p $latest_folder
dst=$out/etc/fonts/${pkg.configVersion}/conf.d
mkdir -p $dst
# fonts.conf
ln -s ${supportFontsConf} $support_folder/../fonts.conf
ln -s ${latestPkg.out}/etc/fonts/fonts.conf \
$latest_folder/../fonts.conf
ln -s ${pkg.out}/etc/fonts/fonts.conf \
$dst/../fonts.conf
# TODO: remove this legacy symlink once people stop using packages built before #95358 was merged
ln -s /etc/fonts/${pkg.configVersion}/fonts.conf \
$out/etc/fonts/fonts.conf
# fontconfig default config files
ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \
$support_folder/
# Latest fontconfig is configured to look for the upstream defaults inside the package.
ln -s ${pkg.out}/etc/fonts/conf.d/*.conf \
$dst/
# update 51-local.conf path to look at local.conf
rm $dst/51-local.conf
substitute ${pkg.out}/etc/fonts/conf.d/51-local.conf \
$dst/51-local.conf \
--replace local.conf /etc/fonts/${pkg.configVersion}/local.conf
# 00-nixos-cache.conf
ln -s ${cacheConfSupport} \
$support_folder/00-nixos-cache.conf
ln -s ${cacheConfLatest} $latest_folder/00-nixos-cache.conf
ln -s ${cacheConf} $dst/00-nixos-cache.conf
# 10-nixos-rendering.conf
ln -s ${renderConf} $support_folder/10-nixos-rendering.conf
ln -s ${renderConf} $latest_folder/10-nixos-rendering.conf
ln -s ${renderConf} $dst/10-nixos-rendering.conf
# 50-user.conf
${optionalString (!cfg.includeUserConf) ''
rm $support_folder/50-user.conf
''}
# Since latest fontconfig looks for default files inside the package,
# we had to move this one elsewhere to be able to exclude it here.
${optionalString cfg.includeUserConf ''
ln -s ${latestPkg.out}/etc/fonts/conf.d.bak/50-user.conf $latest_folder/50-user.conf
rm $dst/50-user.conf
''}
# local.conf (indirect priority 51)
${optionalString (cfg.localConf != "") ''
ln -s ${localConf} $support_folder/../local.conf
ln -s ${localConf} $latest_folder/../local.conf
ln -s ${localConf} $dst/../local.conf
''}
# 52-nixos-default-fonts.conf
ln -s ${defaultFontsConf} $support_folder/52-nixos-default-fonts.conf
ln -s ${defaultFontsConf} $latest_folder/52-nixos-default-fonts.conf
ln -s ${defaultFontsConf} $dst/52-nixos-default-fonts.conf
# 53-no-bitmaps.conf
ln -s ${rejectBitmaps} $support_folder/53-no-bitmaps.conf
ln -s ${rejectBitmaps} $latest_folder/53-no-bitmaps.conf
ln -s ${rejectBitmaps} $dst/53-no-bitmaps.conf
${optionalString (!cfg.allowType1) ''
# 53-nixos-reject-type1.conf
ln -s ${rejectType1} $support_folder/53-nixos-reject-type1.conf
ln -s ${rejectType1} $latest_folder/53-nixos-reject-type1.conf
ln -s ${rejectType1} $dst/53-nixos-reject-type1.conf
''}
'';

View file

@ -25,4 +25,4 @@ in
services.udev.packages = [ pkgs.libbladeRF ];
users.groups.bladerf = {};
};
}
}

View file

@ -43,7 +43,6 @@ in
serviceConfig = {
ExecStart = "${cfg.package}/bin/ckb-next-daemon ${optionalString (cfg.gid != null) "--gid=${builtins.toString cfg.gid}"}";
Restart = "on-failure";
StandardOutput = "syslog";
};
};
};

View file

@ -5,24 +5,92 @@ with lib;
let
cfg = config.hardware.logitech;
in {
options.hardware.logitech = {
enable = mkEnableOption "Logitech Devices";
vendor = "046d";
enableGraphical = mkOption {
type = types.bool;
default = false;
description = "Enable graphical support applications.";
daemon = "g15daemon";
in
{
imports = [
(mkRenamedOptionModule [ "hardware" "logitech" "enable" ] [ "hardware" "logitech" "wireless" "enable" ])
(mkRenamedOptionModule [ "hardware" "logitech" "enableGraphical" ] [ "hardware" "logitech" "wireless" "enableGraphical" ])
];
options.hardware.logitech = {
lcd = {
enable = mkEnableOption "Logitech LCD Devices";
startWhenNeeded = mkOption {
type = types.bool;
default = true;
description = ''
Only run the service when an actual supported device is plugged.
'';
};
devices = mkOption {
type = types.listOf types.str;
default = [ "0a07" "c222" "c225" "c227" "c251" ];
description = ''
List of USB device ids supported by g15daemon.
</para>
<para>
You most likely do not need to change this.
'';
};
};
wireless = {
enable = mkEnableOption "Logitech Wireless Devices";
enableGraphical = mkOption {
type = types.bool;
default = false;
description = "Enable graphical support applications.";
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.ltunify
] ++ lib.optional cfg.enableGraphical pkgs.solaar;
config = lib.mkIf (cfg.wireless.enable || cfg.lcd.enable) {
environment.systemPackages = []
++ lib.optional cfg.wireless.enable pkgs.ltunify
++ lib.optional cfg.wireless.enableGraphical pkgs.solaar;
# ltunifi and solaar both provide udev rules but the most up-to-date have been split
# out into a dedicated derivation
services.udev.packages = with pkgs; [ logitech-udev-rules ];
services.udev = {
# ltunifi and solaar both provide udev rules but the most up-to-date have been split
# out into a dedicated derivation
packages = []
++ lib.optional cfg.wireless.enable pkgs.logitech-udev-rules
++ lib.optional cfg.lcd.enable pkgs.g15daemon;
extraRules = ''
# nixos: hardware.logitech.lcd
'' + lib.concatMapStringsSep "\n" (
dev:
''ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="${vendor}", ATTRS{idProduct}=="${dev}", TAG+="systemd", ENV{SYSTEMD_WANTS}+="${daemon}.service"''
) cfg.lcd.devices;
};
systemd.services."${daemon}" = lib.mkIf cfg.lcd.enable {
description = "Logitech LCD Support Daemon";
documentation = [ "man:g15daemon(1)" ];
wantedBy = lib.mkIf (! cfg.lcd.startWhenNeeded) "multi-user.target";
serviceConfig = {
Type = "forking";
ExecStart = "${pkgs.g15daemon}/bin/g15daemon";
# we patch it to write to /run/g15daemon/g15daemon.pid instead of
# /run/g15daemon.pid so systemd will do the cleanup for us.
PIDFile = "/run/${daemon}/g15daemon.pid";
PrivateTmp = true;
PrivateNetwork = true;
ProtectHome = "tmpfs";
ProtectSystem = "full"; # strict doesn't work
RuntimeDirectory = daemon;
Restart = "on-failure";
};
};
};
}

View file

@ -2,7 +2,7 @@
with lib;
let
let
cfg = config.hardware.tuxedo-keyboard;
tuxedo-keyboard = config.boot.kernelPackages.tuxedo-keyboard;
in
@ -27,7 +27,7 @@ in
'';
};
config = mkIf cfg.enable
config = mkIf cfg.enable
{
boot.kernelModules = ["tuxedo_keyboard"];
boot.extraModulePackages = [ tuxedo-keyboard ];

View file

@ -2,7 +2,7 @@
with lib;
let
let
cfg = config.i18n.inputMethod.uim;
in
{

View file

@ -417,6 +417,14 @@ in
'';
};
isoImage.squashfsCompression = mkOption {
default = "xz -Xdict-size 100%";
description = ''
Compression settings to use for the squashfs nix store.
'';
example = "zstd -Xcompression-level 6";
};
isoImage.edition = mkOption {
default = "";
description = ''
@ -614,6 +622,7 @@ in
# Create the squashfs image that contains the Nix store.
system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
storeContents = config.isoImage.storeContents;
comp = config.isoImage.squashfsCompression;
};
# Individual files to be included on the CD, outside of the Nix

View file

@ -63,7 +63,7 @@ Activate the system: look for a directory in nix/store similar to:
Having found it, activate that nixos system *twice*:
chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
This runs a 'hostname' command. Restore your old hostname with:
hostname OLDHOSTNAME

View file

@ -331,6 +331,7 @@
./services/development/bloop.nix
./services/development/hoogle.nix
./services/development/jupyter/default.nix
./services/development/jupyterhub/default.nix
./services/development/lorri.nix
./services/editors/emacs.nix
./services/editors/infinoted.nix
@ -488,6 +489,7 @@
./services/misc/parsoid.nix
./services/misc/plex.nix
./services/misc/tautulli.nix
./services/misc/pinnwand.nix
./services/misc/pykms.nix
./services/misc/radarr.nix
./services/misc/redmine.nix
@ -646,6 +648,8 @@
./services/networking/iperf3.nix
./services/networking/ircd-hybrid/default.nix
./services/networking/iwd.nix
./services/networking/jicofo.nix
./services/networking/jitsi-videobridge.nix
./services/networking/keepalived/default.nix
./services/networking/keybase.nix
./services/networking/kippo.nix
@ -674,6 +678,7 @@
./services/networking/nat.nix
./services/networking/ndppd.nix
./services/networking/networkmanager.nix
./services/networking/nextdns.nix
./services/networking/nftables.nix
./services/networking/ngircd.nix
./services/networking/nghttpx/default.nix
@ -835,6 +840,7 @@
./services/ttys/gpm.nix
./services/ttys/kmscon.nix
./services/wayland/cage.nix
./services/video/mirakurun.nix
./services/web-apps/atlassian/confluence.nix
./services/web-apps/atlassian/crowd.nix
./services/web-apps/atlassian/jira.nix
@ -852,6 +858,7 @@
./services/web-apps/icingaweb2/module-monitoring.nix
./services/web-apps/ihatemoney
./services/web-apps/jirafeau.nix
./services/web-apps/jitsi-meet.nix
./services/web-apps/limesurvey.nix
./services/web-apps/mattermost.nix
./services/web-apps/mediawiki.nix
@ -922,6 +929,7 @@
./services/x11/gdk-pixbuf.nix
./services/x11/imwheel.nix
./services/x11/redshift.nix
./services/x11/urserver.nix
./services/x11/urxvtd.nix
./services/x11/window-managers/awesome.nix
./services/x11/window-managers/default.nix

View file

@ -18,7 +18,7 @@ in
'';
};
};
};
};
###### implementation
@ -26,7 +26,7 @@ in
environment.pathsToLink = [ "/share/autojump" ];
environment.systemPackages = [ pkgs.autojump ];
programs.bash.interactiveShellInit = "source ${pkgs.autojump}/share/autojump/autojump.bash";
programs.bash.interactiveShellInit = "source ${pkgs.autojump}/share/autojump/autojump.bash";
programs.zsh.interactiveShellInit = mkIf prg.zsh.enable "source ${pkgs.autojump}/share/autojump/autojump.zsh";
programs.fish.interactiveShellInit = mkIf prg.fish.enable "source ${pkgs.autojump}/share/autojump/autojump.fish";
};

View file

@ -80,4 +80,4 @@ in {
];
})
];
}
}

View file

@ -25,7 +25,7 @@ in
''';
}
'';
description =
description =
''
Configure freetds database entries. Each attribute denotes
a section within freetds.conf, and the value (a string) is the config
@ -47,7 +47,7 @@ in
environment.variables.FREETDS = "/etc/freetds.conf";
environment.variables.SYBASE = "${pkgs.freetds}";
environment.etc."freetds.conf" = { text =
environment.etc."freetds.conf" = { text =
(concatStrings (mapAttrsToList (name: value:
''
[${name}]

View file

@ -170,7 +170,6 @@ in {
Restart = "always";
RestartSec = 30;
BusName = "com.intel.tss2.Tabrmd";
StandardOutput = "syslog";
ExecStart = "${cfg.abrmd.package}/bin/tpm2-abrmd";
User = "tss";
Group = "nogroup";

View file

@ -23,7 +23,7 @@ let
<listen-socket>
<port>${toString cfg.listen.port}</port>
<bind-address>${cfg.listen.address}</bind-address>
</listen-socket>
</listen-socket>
<security>
<chroot>0</chroot>
@ -70,7 +70,7 @@ in {
description = "Base directory used for logging.";
default = "/var/log/icecast";
};
listen = {
port = mkOption {
type = types.int;

View file

@ -18,7 +18,7 @@ let
Pid Directory = "/run";
${fd_cfg.extraClientConfig}
}
${concatStringsSep "\n" (mapAttrsToList (name: value: ''
Director {
Name = "${name}";
@ -26,7 +26,7 @@ let
Monitor = "${value.monitor}";
}
'') fd_cfg.director)}
Messages {
Name = Standard;
syslog = all, !skipped, !restored
@ -35,7 +35,7 @@ let
'';
sd_cfg = config.services.bacula-sd;
sd_conf = pkgs.writeText "bacula-sd.conf"
sd_conf = pkgs.writeText "bacula-sd.conf"
''
Storage {
Name = "${sd_cfg.name}";
@ -80,7 +80,7 @@ let
'';
dir_cfg = config.services.bacula-dir;
dir_conf = pkgs.writeText "bacula-dir.conf"
dir_conf = pkgs.writeText "bacula-dir.conf"
''
Director {
Name = "${dir_cfg.name}";
@ -125,10 +125,10 @@ let
The password is plain text. It is not generated through any special
process but as noted above, it is better to use random text for
security reasons.
security reasons.
'';
};
monitor = mkOption {
default = "no";
example = "yes";
@ -140,7 +140,7 @@ let
Please note that if this director is being used by a Monitor, we
highly recommend to set this directive to yes to avoid serious
security problems.
security problems.
'';
};
};
@ -163,7 +163,7 @@ let
type of autochanger, what you specify here can vary. This directive
is optional. See the Using AutochangersAutochangersChapter chapter of
this manual for more details of using this and the following
autochanger directives.
autochanger directives.
'';
};
@ -200,7 +200,7 @@ let
Extra configuration to be passed in Autochanger directive.
'';
example = ''
'';
};
};
@ -222,7 +222,7 @@ let
if you are archiving to disk storage. In this case, you must supply
the full absolute path to the directory. When specifying a tape
device, it is preferable that the "non-rewind" variant of the device
file name be given.
file name be given.
'';
};
@ -290,7 +290,7 @@ in {
Whether to enable the Bacula File Daemon.
'';
};
name = mkOption {
default = "${config.networking.hostName}-fd";
description = ''
@ -300,7 +300,7 @@ in {
Clients. This directive is required.
'';
};
port = mkOption {
default = 9102;
type = types.int;
@ -310,7 +310,7 @@ in {
the Client resource of the Director's configuration file.
'';
};
director = mkOption {
default = {};
description = ''
@ -349,14 +349,14 @@ in {
Whether to enable Bacula Storage Daemon.
'';
};
name = mkOption {
default = "${config.networking.hostName}-sd";
description = ''
Specifies the Name of the Storage daemon.
'';
};
port = mkOption {
default = 9103;
type = types.int;
@ -410,7 +410,7 @@ in {
console = all
'';
};
};
services.bacula-dir = {
@ -429,7 +429,7 @@ in {
required.
'';
};
port = mkOption {
default = 9101;
type = types.int;
@ -442,7 +442,7 @@ in {
specify DirAddresses (N.B plural) directive.
'';
};
password = mkOption {
# TODO: required?
description = ''

View file

@ -55,7 +55,7 @@ in
Configuration for the rclone remote being used for backup.
See the remote's specific options under rclone's docs at
<link xlink:href="https://rclone.org/docs/"/>. When specifying
option names, use the "config" name specified in the docs.
option names, use the "config" name specified in the docs.
For example, to set <literal>--b2-hard-delete</literal> for a B2
remote, use <literal>hard_delete = true</literal> in the
attribute set.

View file

@ -18,7 +18,7 @@ in {
};
host = mkOption {
description = "Remote host where snapshots should be sent.";
description = "Remote host where snapshots should be sent. <literal>lz4</literal> is expected to be installed on this host.";
example = "example.com";
type = types.str;
};

View file

@ -60,4 +60,4 @@ in
};
};
}
}

View file

@ -93,4 +93,4 @@ in
};
};
}
}

View file

@ -6,12 +6,10 @@ let
cfg = config.services.mysql;
mysql = cfg.package;
isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb;
isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb;
mysqldOptions =
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}";
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}";
settingsFile = pkgs.writeText "my.cnf" (
generators.toINI { listsAsDuplicateKeys = true; } cfg.settings +
@ -22,7 +20,7 @@ in
{
imports = [
(mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd")
(mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd.")
(mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.")
];
@ -46,25 +44,31 @@ in
type = types.nullOr types.str;
default = null;
example = literalExample "0.0.0.0";
description = "Address to bind to. The default is to bind to all addresses";
description = "Address to bind to. The default is to bind to all addresses.";
};
port = mkOption {
type = types.int;
default = 3306;
description = "Port of MySQL";
description = "Port of MySQL.";
};
user = mkOption {
type = types.str;
default = "mysql";
description = "User account under which MySQL runs";
description = "User account under which MySQL runs.";
};
group = mkOption {
type = types.str;
default = "mysql";
description = "Group under which MySQL runs.";
};
dataDir = mkOption {
type = types.path;
example = "/var/lib/mysql";
description = "Location where MySQL stores its table files";
description = "Location where MySQL stores its table files.";
};
configFile = mkOption {
@ -171,7 +175,7 @@ in
initialScript = mkOption {
type = types.nullOr types.path;
default = null;
description = "A file containing SQL statements to be executed on the first startup. Can be used for granting certain permissions on the database";
description = "A file containing SQL statements to be executed on the first startup. Can be used for granting certain permissions on the database.";
};
ensureDatabases = mkOption {
@ -259,33 +263,33 @@ in
serverId = mkOption {
type = types.int;
default = 1;
description = "Id of the MySQL server instance. This number must be unique for each instance";
description = "Id of the MySQL server instance. This number must be unique for each instance.";
};
masterHost = mkOption {
type = types.str;
description = "Hostname of the MySQL master server";
description = "Hostname of the MySQL master server.";
};
slaveHost = mkOption {
type = types.str;
description = "Hostname of the MySQL slave server";
description = "Hostname of the MySQL slave server.";
};
masterUser = mkOption {
type = types.str;
description = "Username of the MySQL replication user";
description = "Username of the MySQL replication user.";
};
masterPassword = mkOption {
type = types.str;
description = "Password of the MySQL replication user";
description = "Password of the MySQL replication user.";
};
masterPort = mkOption {
type = types.int;
default = 3306;
description = "Port number on which the MySQL master server runs";
description = "Port number on which the MySQL master server runs.";
};
};
};
@ -317,29 +321,33 @@ in
binlog-ignore-db = [ "information_schema" "performance_schema" "mysql" ];
})
(mkIf (!isMariaDB) {
plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so";
plugin-load-add = "auth_socket.so";
})
];
users.users.mysql = {
description = "MySQL server user";
group = "mysql";
uid = config.ids.uids.mysql;
users.users = optionalAttrs (cfg.user == "mysql") {
mysql = {
description = "MySQL server user";
group = cfg.group;
uid = config.ids.uids.mysql;
};
};
users.groups.mysql.gid = config.ids.gids.mysql;
users.groups = optionalAttrs (cfg.group == "mysql") {
mysql.gid = config.ids.gids.mysql;
};
environment.systemPackages = [mysql];
environment.systemPackages = [ cfg.package ];
environment.etc."my.cnf".source = cfg.configFile;
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
"z '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
"d '${cfg.dataDir}' 0700 '${cfg.user}' '${cfg.group}' - -"
"z '${cfg.dataDir}' 0700 '${cfg.user}' '${cfg.group}' - -"
];
systemd.services.mysql = let
hasNotify = (cfg.package == pkgs.mariadb);
hasNotify = isMariaDB;
in {
description = "MySQL Server";
@ -357,125 +365,127 @@ in
preStart = if isMariaDB then ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions}
${cfg.package}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions}
touch ${cfg.dataDir}/mysql_init
fi
'' else ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
touch ${cfg.dataDir}/mysql_init
fi
'';
postStart = let
# The super user account to use on *first* run of MySQL server
superUser = if isMariaDB then cfg.user else "root";
in ''
${optionalString (!hasNotify) ''
# Wait until the MySQL server is available for use
count=0
while [ ! -e /run/mysqld/mysqld.sock ]
do
if [ $count -eq 30 ]
then
echo "Tried 30 times, giving up..."
exit 1
fi
echo "MySQL daemon not yet started. Waiting for 1 second..."
count=$((count++))
sleep 1
done
''}
if [ -f ${cfg.dataDir}/mysql_init ]
then
# While MariaDB comes with a 'mysql' super user account since 10.4.x, MySQL does not
# Since we don't want to run this service as 'root' we need to ensure the account exists on first run
( echo "CREATE USER IF NOT EXISTS '${cfg.user}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};"
echo "GRANT ALL PRIVILEGES ON *.* TO '${cfg.user}'@'localhost' WITH GRANT OPTION;"
) | ${cfg.package}/bin/mysql -u ${superUser} -N
${concatMapStrings (database: ''
# Create initial databases
if ! test -e "${cfg.dataDir}/${database.name}"; then
echo "Creating initial database: ${database.name}"
( echo 'create database `${database.name}`;'
${optionalString (database.schema != null) ''
echo 'use `${database.name}`;'
# TODO: this silently falls through if database.schema does not exist,
# we should catch this somehow and exit, but can't do it here because we're in a subshell.
if [ -f "${database.schema}" ]
then
cat ${database.schema}
elif [ -d "${database.schema}" ]
then
cat ${database.schema}/mysql-databases/*.sql
fi
''}
) | ${cfg.package}/bin/mysql -u ${superUser} -N
fi
'') cfg.initialDatabases}
${optionalString (cfg.replication.role == "master")
''
# Set up the replication master
( echo "use mysql;"
echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;"
echo "SET PASSWORD FOR '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' = PASSWORD('${cfg.replication.masterPassword}');"
echo "GRANT REPLICATION SLAVE ON *.* TO '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}';"
) | ${cfg.package}/bin/mysql -u ${superUser} -N
''}
${optionalString (cfg.replication.role == "slave")
''
# Set up the replication slave
( echo "stop slave;"
echo "change master to master_host='${cfg.replication.masterHost}', master_user='${cfg.replication.masterUser}', master_password='${cfg.replication.masterPassword}';"
echo "start slave;"
) | ${cfg.package}/bin/mysql -u ${superUser} -N
''}
${optionalString (cfg.initialScript != null)
''
# Execute initial script
# using toString to avoid copying the file to nix store if given as path instead of string,
# as it might contain credentials
cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u ${superUser} -N
''}
rm ${cfg.dataDir}/mysql_init
fi
${optionalString (cfg.ensureDatabases != []) ''
(
${concatMapStrings (database: ''
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
'') cfg.ensureDatabases}
) | ${cfg.package}/bin/mysql -N
''}
${concatMapStrings (user:
''
( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};"
${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';"
'') user.ensurePermissions)}
) | ${cfg.package}/bin/mysql -N
'') cfg.ensureUsers}
'';
serviceConfig = {
Type = if hasNotify then "notify" else "simple";
Restart = "on-abort";
RestartSec = "5s";
# The last two environment variables are used for starting Galera clusters
ExecStart = "${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION";
ExecStartPost =
let
setupScript = pkgs.writeScript "mysql-setup" ''
#!${pkgs.runtimeShell} -e
${optionalString (!hasNotify) ''
# Wait until the MySQL server is available for use
count=0
while [ ! -e /run/mysqld/mysqld.sock ]
do
if [ $count -eq 30 ]
then
echo "Tried 30 times, giving up..."
exit 1
fi
echo "MySQL daemon not yet started. Waiting for 1 second..."
count=$((count++))
sleep 1
done
''}
if [ -f ${cfg.dataDir}/mysql_init ]
then
${concatMapStrings (database: ''
# Create initial databases
if ! test -e "${cfg.dataDir}/${database.name}"; then
echo "Creating initial database: ${database.name}"
( echo 'create database `${database.name}`;'
${optionalString (database.schema != null) ''
echo 'use `${database.name}`;'
# TODO: this silently falls through if database.schema does not exist,
# we should catch this somehow and exit, but can't do it here because we're in a subshell.
if [ -f "${database.schema}" ]
then
cat ${database.schema}
elif [ -d "${database.schema}" ]
then
cat ${database.schema}/mysql-databases/*.sql
fi
''}
) | ${mysql}/bin/mysql -u root -N
fi
'') cfg.initialDatabases}
${optionalString (cfg.replication.role == "master")
''
# Set up the replication master
( echo "use mysql;"
echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;"
echo "SET PASSWORD FOR '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' = PASSWORD('${cfg.replication.masterPassword}');"
echo "GRANT REPLICATION SLAVE ON *.* TO '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}';"
) | ${mysql}/bin/mysql -u root -N
''}
${optionalString (cfg.replication.role == "slave")
''
# Set up the replication slave
( echo "stop slave;"
echo "change master to master_host='${cfg.replication.masterHost}', master_user='${cfg.replication.masterUser}', master_password='${cfg.replication.masterPassword}';"
echo "start slave;"
) | ${mysql}/bin/mysql -u root -N
''}
${optionalString (cfg.initialScript != null)
''
# Execute initial script
# using toString to avoid copying the file to nix store if given as path instead of string,
# as it might contain credentials
cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N
''}
rm ${cfg.dataDir}/mysql_init
fi
${optionalString (cfg.ensureDatabases != []) ''
(
${concatMapStrings (database: ''
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
'') cfg.ensureDatabases}
) | ${mysql}/bin/mysql -u root -N
''}
${concatMapStrings (user:
''
( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};"
${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';"
'') user.ensurePermissions)}
) | ${mysql}/bin/mysql -u root -N
'') cfg.ensureUsers}
'';
in
# ensureDatbases & ensureUsers depends on this script being run as root
# when the user has secured their mysql install
"+${setupScript}";
ExecStart = "${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION";
# User and group
User = cfg.user;
Group = "mysql";
Group = cfg.group;
# Runtime directory and mode
RuntimeDirectory = "mysqld";
RuntimeDirectoryMode = "0755";

View file

@ -21,7 +21,7 @@ let
listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}'
port = ${toString cfg.port}
${cfg.extraConfig}
'';
'';
groupAccessAvailable = versionAtLeast postgresql.version "11.0";
@ -55,9 +55,13 @@ in
dataDir = mkOption {
type = types.path;
defaultText = "/var/lib/postgresql/\${config.services.postgresql.package.psqlSchema}";
example = "/var/lib/postgresql/11";
description = ''
Data directory for PostgreSQL.
The data directory for PostgreSQL. If left as the default value
this directory will automatically be created before the PostgreSQL server starts, otherwise
the sysadmin is responsible for ensuring the directory exists with appropriate ownership
and permissions.
'';
};
@ -249,10 +253,7 @@ in
else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql_9_5
else throw "postgresql_9_4 was removed, please upgrade your postgresql version.");
services.postgresql.dataDir =
mkDefault (if versionAtLeast config.system.stateVersion "17.09"
then "/var/lib/postgresql/${cfg.package.psqlSchema}"
else "/var/db/postgresql");
services.postgresql.dataDir = mkDefault "/var/lib/postgresql/${cfg.package.psqlSchema}";
services.postgresql.authentication = mkAfter
''
@ -291,40 +292,28 @@ in
preStart =
''
# Create data directory.
if ! test -e ${cfg.dataDir}/PG_VERSION; then
mkdir -m 0700 -p ${cfg.dataDir}
# Cleanup the data directory.
rm -f ${cfg.dataDir}/*.conf
chown -R postgres:postgres ${cfg.dataDir}
fi
''; # */
script =
''
# Initialise the database.
if ! test -e ${cfg.dataDir}/PG_VERSION; then
# Initialise the database.
initdb -U ${cfg.superUser} ${concatStringsSep " " cfg.initdbArgs}
# See postStart!
touch "${cfg.dataDir}/.first_startup"
fi
ln -sfn "${configFile}" "${cfg.dataDir}/postgresql.conf"
${optionalString (cfg.recoveryConfig != null) ''
ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \
"${cfg.dataDir}/recovery.conf"
''}
${optionalString (!groupAccessAvailable) ''
# postgresql pre 11.0 doesn't start if state directory mode is group accessible
chmod 0700 "${cfg.dataDir}"
''}
exec postgres
'';
serviceConfig =
serviceConfig = mkMerge [
{ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = "postgres";
Group = "postgres";
PermissionsStartOnly = true;
RuntimeDirectory = "postgresql";
Type = if versionAtLeast cfg.package.version "9.6"
then "notify"
@ -338,36 +327,48 @@ in
# Give Postgres a decent amount of time to clean up after
# receiving systemd's SIGINT.
TimeoutSec = 120;
};
# Wait for PostgreSQL to be ready to accept connections.
postStart =
''
PSQL="${pkgs.utillinux}/bin/runuser -u ${cfg.superUser} -- psql --port=${toString cfg.port}"
ExecStart = "${postgresql}/bin/postgres";
while ! $PSQL -d postgres -c "" 2> /dev/null; do
if ! kill -0 "$MAINPID"; then exit 1; fi
sleep 0.1
done
# Wait for PostgreSQL to be ready to accept connections.
ExecStartPost =
let
setupScript = pkgs.writeScript "postgresql-setup" (''
#!${pkgs.runtimeShell} -e
if test -e "${cfg.dataDir}/.first_startup"; then
${optionalString (cfg.initialScript != null) ''
$PSQL -f "${cfg.initialScript}" -d postgres
''}
rm -f "${cfg.dataDir}/.first_startup"
fi
'' + optionalString (cfg.ensureDatabases != []) ''
${concatMapStrings (database: ''
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}"'
'') cfg.ensureDatabases}
'' + ''
${concatMapStrings (user: ''
$PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc 'CREATE USER "${user.name}"'
${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
$PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"'
'') user.ensurePermissions)}
'') cfg.ensureUsers}
'';
PSQL="${pkgs.utillinux}/bin/runuser -u ${cfg.superUser} -- psql --port=${toString cfg.port}"
while ! $PSQL -d postgres -c "" 2> /dev/null; do
if ! kill -0 "$MAINPID"; then exit 1; fi
sleep 0.1
done
if test -e "${cfg.dataDir}/.first_startup"; then
${optionalString (cfg.initialScript != null) ''
$PSQL -f "${cfg.initialScript}" -d postgres
''}
rm -f "${cfg.dataDir}/.first_startup"
fi
'' + optionalString (cfg.ensureDatabases != []) ''
${concatMapStrings (database: ''
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${database}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${database}"'
'') cfg.ensureDatabases}
'' + ''
${concatMapStrings (user: ''
$PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${user.name}'" | grep -q 1 || $PSQL -tAc 'CREATE USER "${user.name}"'
${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
$PSQL -tAc 'GRANT ${permission} ON ${database} TO "${user.name}"'
'') user.ensurePermissions)}
'') cfg.ensureUsers}
'');
in
"+${setupScript}";
}
(mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") {
StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}";
StateDirectoryMode = if groupAccessAvailable then "0750" else "0700";
})
];
unitConfig.RequiresMountsFor = "${cfg.dataDir}";
};

View file

@ -35,7 +35,7 @@ in
Name of the Erlang node.
'';
};
anonymousUserCreation = mkOption {
type = types.bool;
default = false;

View file

@ -0,0 +1,190 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jupyterhub;
kernels = (pkgs.jupyter-kernel.create {
definitions = if cfg.kernels != null
then cfg.kernels
else pkgs.jupyter-kernel.default;
});
jupyterhubConfig = pkgs.writeText "jupyterhub_config.py" ''
c.JupyterHub.bind_url = "http://${cfg.host}:${toString cfg.port}"
c.JupyterHub.authentication_class = "${cfg.authentication}"
c.JupyterHub.spawner_class = "${cfg.spawner}"
c.SystemdSpawner.default_url = '/lab'
c.SystemdSpawner.cmd = "${cfg.jupyterlabEnv}/bin/jupyterhub-singleuser"
c.SystemdSpawner.environment = {
'JUPYTER_PATH': '${kernels}'
}
${cfg.extraConfig}
'';
in {
meta.maintainers = with maintainers; [ costrouc ];
options.services.jupyterhub = {
enable = mkEnableOption "Jupyterhub development server";
authentication = mkOption {
type = types.str;
default = "jupyterhub.auth.PAMAuthenticator";
description = ''
Jupyterhub authentication to use
There are many authenticators available including: oauth, pam,
ldap, kerberos, etc.
'';
};
spawner = mkOption {
type = types.str;
default = "systemdspawner.SystemdSpawner";
description = ''
Jupyterhub spawner to use
There are many spawners available including: local process,
systemd, docker, kubernetes, yarn, batch, etc.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra contents appended to the jupyterhub configuration
Jupyterhub configuration is a normal python file using
Traitlets. https://jupyterhub.readthedocs.io/en/stable/getting-started/config-basics.html. The
base configuration of this module was designed to have sane
defaults for configuration but you can override anything since
this is a python file.
'';
example = literalExample ''
c.SystemdSpawner.mem_limit = '8G'
c.SystemdSpawner.cpu_limit = 2.0
'';
};
jupyterhubEnv = mkOption {
type = types.package;
default = (pkgs.python3.withPackages (p: with p; [
jupyterhub
jupyterhub-systemdspawner
]));
description = ''
Python environment to run jupyterhub
Customizing will affect the packages available in the hub and
proxy. This will allow packages to be available for the
extraConfig that you may need. This will not normally need to
be changed.
'';
};
jupyterlabEnv = mkOption {
type = types.package;
default = (pkgs.python3.withPackages (p: with p; [
jupyterhub
jupyterlab
]));
description = ''
Python environment to run jupyterlab
Customizing will affect the packages available in the
jupyterlab server and the default kernel provided. This is the
way to customize the jupyterlab extensions and jupyter
notebook extensions. This will not normally need to
be changed.
'';
};
kernels = mkOption {
type = types.nullOr (types.attrsOf(types.submodule (import ../jupyter/kernel-options.nix {
inherit lib;
})));
default = null;
example = literalExample ''
{
python3 = let
env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
ipykernel
pandas
scikitlearn
]));
in {
displayName = "Python 3 for machine learning";
argv = [
"''${env.interpreter}"
"-m"
"ipykernel_launcher"
"-f"
"{connection_file}"
];
language = "python";
logo32 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
logo64 = "''${env}/''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
};
}
'';
description = ''
Declarative kernel config
Kernels can be declared in any language that supports and has
the required dependencies to communicate with a jupyter server.
In python's case, it means that ipykernel package must always be
included in the list of packages of the targeted environment.
'';
};
port = mkOption {
type = types.port;
default = 8000;
description = ''
Port number Jupyterhub will be listening on
'';
};
host = mkOption {
type = types.str;
default = "0.0.0.0";
description = ''
Bind IP JupyterHub will be listening on
'';
};
stateDirectory = mkOption {
type = types.str;
default = "jupyterhub";
description = ''
Directory for jupyterhub state (token + database)
'';
};
};
config = mkMerge [
(mkIf cfg.enable {
systemd.services.jupyterhub = {
description = "Jupyterhub development server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Restart = "always";
ExecStart = "${cfg.jupyterhubEnv}/bin/jupyterhub --config ${jupyterhubConfig}";
User = "root";
StateDirectory = cfg.stateDirectory;
WorkingDirectory = "/var/lib/${cfg.stateDirectory}";
};
};
})
];
}

View file

@ -5,12 +5,12 @@ with lib;
let
cfg = config.services.minetest-server;
flag = val: name: if val != null then "--${name} ${val} " else "";
flags = [
(flag cfg.gameId "gameid")
(flag cfg.world "world")
(flag cfg.configPath "config")
(flag cfg.logPath "logfile")
(flag cfg.port "port")
flags = [
(flag cfg.gameId "gameid")
(flag cfg.world "world")
(flag cfg.configPath "config")
(flag cfg.logPath "logfile")
(flag cfg.port "port")
];
in
{
@ -26,7 +26,7 @@ in
type = types.nullOr types.str;
default = null;
description = ''
Id of the game to use. To list available games run
Id of the game to use. To list available games run
`minetestserver --gameid list`.
If only one game exists, this option can be null.
@ -59,7 +59,7 @@ in
type = types.nullOr types.path;
default = null;
description = ''
Path to logfile for logging.
Path to logfile for logging.
If set to null, logging will be output to stdout which means
all output will be catched by systemd.

View file

@ -7,7 +7,7 @@ let
worldSizeMap = { small = 1; medium = 2; large = 3; };
valFlag = name: val: optionalString (val != null) "-${name} \"${escape ["\\" "\""] (toString val)}\"";
boolFlag = name: val: optionalString val "-${name}";
flags = [
flags = [
(valFlag "port" cfg.port)
(valFlag "maxPlayers" cfg.maxPlayers)
(valFlag "password" cfg.password)

View file

@ -67,7 +67,7 @@ in {
type = types.bool;
default = false;
description = ''
Whether to build thinkfan with SMART support to read temperatures
Whether to build thinkfan with SMART support to read temperatures
directly from hard disks.
'';
};

View file

@ -10,7 +10,7 @@ in {
meta = {
doc = ./trezord.xml;
};
### interface
options = {
@ -40,7 +40,7 @@ in {
};
};
};
### implementation
config = mkIf cfg.enable {

View file

@ -53,4 +53,4 @@ with lib;
};
};
};
}
}

View file

@ -25,6 +25,8 @@ let
clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
smtpTlsSecurityLevel = if cfg.useDane then "dane" else "may";
mainCf = let
escape = replaceStrings ["$"] ["$$"];
mkList = items: "\n " + concatStringsSep ",\n " items;
@ -508,6 +510,14 @@ in
'';
};
useDane = mkOption {
type = types.bool;
default = false;
description = ''
Sets smtp_tls_security_level to "dane" rather than "may". See postconf(5) for details.
'';
};
sslCert = mkOption {
type = types.str;
default = "";
@ -809,13 +819,13 @@ in
// optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
// optionalAttrs (cfg.tlsTrustedAuthorities != "") {
smtp_tls_CAfile = cfg.tlsTrustedAuthorities;
smtp_tls_security_level = "may";
smtp_tls_security_level = smtpTlsSecurityLevel;
}
// optionalAttrs (cfg.sslCert != "") {
smtp_tls_cert_file = cfg.sslCert;
smtp_tls_key_file = cfg.sslKey;
smtp_tls_security_level = "may";
smtp_tls_security_level = smtpTlsSecurityLevel;
smtpd_tls_cert_file = cfg.sslCert;
smtpd_tls_key_file = cfg.sslKey;

View file

@ -162,6 +162,45 @@ in
<manvolnum>7</manvolnum></citerefentry>.
'';
};
backupDir = mkOption {
type = types.str;
default = "${cfg.stateDir}/dump";
description = "Path to the dump files.";
};
};
ssh = {
enable = mkOption {
type = types.bool;
default = true;
description = "Enable external SSH feature.";
};
clonePort = mkOption {
type = types.int;
default = 22;
example = 2222;
description = ''
SSH port displayed in clone URL.
The option is required to configure a service when the external visible port
differs from the local listening port i.e. if port forwarding is used.
'';
};
};
lfs = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enables git-lfs support.";
};
contentDir = mkOption {
type = types.str;
default = "${cfg.stateDir}/data/lfs";
description = "Where to store LFS files.";
};
};
appName = mkOption {
@ -200,6 +239,12 @@ in
description = "HTTP listen port.";
};
enableUnixSocket = mkOption {
type = types.bool;
default = false;
description = "Configure Gitea to listen on a unix socket instead of the default TCP port.";
};
cookieSecure = mkOption {
type = types.bool;
default = false;
@ -300,14 +345,34 @@ in
ROOT = cfg.repositoryRoot;
};
server = {
DOMAIN = cfg.domain;
HTTP_ADDR = cfg.httpAddress;
HTTP_PORT = cfg.httpPort;
ROOT_URL = cfg.rootUrl;
STATIC_ROOT_PATH = cfg.staticRootPath;
LFS_JWT_SECRET = "#jwtsecret#";
};
server = mkMerge [
{
DOMAIN = cfg.domain;
STATIC_ROOT_PATH = cfg.staticRootPath;
LFS_JWT_SECRET = "#jwtsecret#";
ROOT_URL = cfg.rootUrl;
}
(mkIf cfg.enableUnixSocket {
PROTOCOL = "unix";
HTTP_ADDR = "/run/gitea/gitea.sock";
})
(mkIf (!cfg.enableUnixSocket) {
HTTP_ADDR = cfg.httpAddress;
HTTP_PORT = cfg.httpPort;
})
(mkIf cfg.ssh.enable {
DISABLE_SSH = false;
SSH_PORT = cfg.ssh.clonePort;
})
(mkIf (!cfg.ssh.enable) {
DISABLE_SSH = true;
})
(mkIf cfg.lfs.enable {
LFS_START_SERVER = true;
LFS_CONTENT_PATH = cfg.lfs.contentDir;
})
];
session = {
COOKIE_NAME = "session";
@ -357,12 +422,26 @@ in
};
systemd.tmpfiles.rules = [
"d '${cfg.stateDir}' - ${cfg.user} gitea - -"
"d '${cfg.stateDir}/conf' - ${cfg.user} gitea - -"
"d '${cfg.stateDir}/custom' - ${cfg.user} gitea - -"
"d '${cfg.stateDir}/custom/conf' - ${cfg.user} gitea - -"
"d '${cfg.stateDir}/log' - ${cfg.user} gitea - -"
"d '${cfg.repositoryRoot}' - ${cfg.user} gitea - -"
"d '${cfg.dump.backupDir}' 0750 ${cfg.user} gitea - -"
"z '${cfg.dump.backupDir}' 0750 ${cfg.user} gitea - -"
"Z '${cfg.dump.backupDir}' - ${cfg.user} gitea - -"
"d '${cfg.lfs.contentDir}' 0750 ${cfg.user} gitea - -"
"z '${cfg.lfs.contentDir}' 0750 ${cfg.user} gitea - -"
"Z '${cfg.lfs.contentDir}' - ${cfg.user} gitea - -"
"d '${cfg.repositoryRoot}' 0750 ${cfg.user} gitea - -"
"z '${cfg.repositoryRoot}' 0750 ${cfg.user} gitea - -"
"Z '${cfg.repositoryRoot}' - ${cfg.user} gitea - -"
"d '${cfg.stateDir}' 0750 ${cfg.user} gitea - -"
"d '${cfg.stateDir}/conf' 0750 ${cfg.user} gitea - -"
"d '${cfg.stateDir}/custom' 0750 ${cfg.user} gitea - -"
"d '${cfg.stateDir}/custom/conf' 0750 ${cfg.user} gitea - -"
"d '${cfg.stateDir}/log' 0750 ${cfg.user} gitea - -"
"z '${cfg.stateDir}' 0750 ${cfg.user} gitea - -"
"z '${cfg.stateDir}/.ssh' 0700 ${cfg.user} gitea - -"
"z '${cfg.stateDir}/conf' 0750 ${cfg.user} gitea - -"
"z '${cfg.stateDir}/custom' 0750 ${cfg.user} gitea - -"
"z '${cfg.stateDir}/custom/conf' 0750 ${cfg.user} gitea - -"
"z '${cfg.stateDir}/log' 0750 ${cfg.user} gitea - -"
"Z '${cfg.stateDir}' - ${cfg.user} gitea - -"
# If we have a folder or symlink with gitea locales, remove it
@ -431,28 +510,39 @@ in
User = cfg.user;
Group = "gitea";
WorkingDirectory = cfg.stateDir;
ExecStart = "${gitea}/bin/gitea web";
ExecStart = "${gitea}/bin/gitea web --pid /run/gitea/gitea.pid";
Restart = "always";
# Filesystem
# Runtime directory and mode
RuntimeDirectory = "gitea";
RuntimeDirectoryMode = "0755";
# Access write directories
ReadWritePaths = [ cfg.dump.backupDir cfg.repositoryRoot cfg.stateDir cfg.lfs.contentDir ];
UMask = "0027";
# Capabilities
CapabilityBoundingSet = "";
# Security
NoNewPrivileges = true;
# Sandboxing
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectHostname = true;
ProtectClock = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
ReadWritePaths = cfg.stateDir;
# Caps
CapabilityBoundingSet = "";
NoNewPrivileges = true;
# Misc.
RestrictAddressFamilies = [ "AF_UNIX AF_INET AF_INET6" ];
LockPersonality = true;
RestrictRealtime = true;
PrivateMounts = true;
PrivateUsers = true;
MemoryDenyWriteExecute = true;
SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @raw-io @reboot @resources @setuid @swap";
RestrictRealtime = true;
RestrictSUIDSGID = true;
PrivateMounts = true;
# System Call Filtering
SystemCallArchitectures = "native";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @raw-io @reboot @resources @setuid @swap";
};
environment = {
@ -504,7 +594,7 @@ in
Type = "oneshot";
User = cfg.user;
ExecStart = "${gitea}/bin/gitea dump";
WorkingDirectory = cfg.stateDir;
WorkingDirectory = cfg.dump.backupDir;
};
};

View file

@ -618,26 +618,38 @@ in {
enable = true;
ensureUsers = singleton { name = cfg.databaseUsername; };
};
# The postgresql module doesn't currently support concepts like
# objects owners and extensions; for now we tack on what's needed
# here.
systemd.services.postgresql.postStart = mkAfter (optionalString databaseActuallyCreateLocally ''
set -eu
systemd.services.gitlab-postgresql = let pgsql = config.services.postgresql; in mkIf databaseActuallyCreateLocally {
after = [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
path = [ pgsql.package ];
script = ''
set -eu
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${cfg.databaseName}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${cfg.databaseName}" OWNER "${cfg.databaseUsername}"'
current_owner=$($PSQL -tAc "SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = '${cfg.databaseName}'")
if [[ "$current_owner" != "${cfg.databaseUsername}" ]]; then
$PSQL -tAc 'ALTER DATABASE "${cfg.databaseName}" OWNER TO "${cfg.databaseUsername}"'
if [[ -e "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}" ]]; then
echo "Reassigning ownership of database ${cfg.databaseName} to user ${cfg.databaseUsername} failed on last boot. Failing..."
exit 1
fi
touch "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}"
$PSQL "${cfg.databaseName}" -tAc "REASSIGN OWNED BY \"$current_owner\" TO \"${cfg.databaseUsername}\""
rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}"
fi
$PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm"
'');
PSQL="${pkgs.utillinux}/bin/runuser -u ${pgsql.superUser} -- psql --port=${toString pgsql.port}"
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${cfg.databaseName}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${cfg.databaseName}" OWNER "${cfg.databaseUsername}"'
current_owner=$($PSQL -tAc "SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = '${cfg.databaseName}'")
if [[ "$current_owner" != "${cfg.databaseUsername}" ]]; then
$PSQL -tAc 'ALTER DATABASE "${cfg.databaseName}" OWNER TO "${cfg.databaseUsername}"'
if [[ -e "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}" ]]; then
echo "Reassigning ownership of database ${cfg.databaseName} to user ${cfg.databaseUsername} failed on last boot. Failing..."
exit 1
fi
touch "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}"
$PSQL "${cfg.databaseName}" -tAc "REASSIGN OWNED BY \"$current_owner\" TO \"${cfg.databaseUsername}\""
rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}"
fi
$PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm"
'';
serviceConfig = {
Type = "oneshot";
};
};
# Use postfix to send out mails.
services.postfix.enable = mkDefault true;
@ -767,7 +779,7 @@ in {
};
systemd.services.gitlab = {
after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "postgresql.service" "redis.service" ];
after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "gitlab-postgresql.service" "redis.service" ];
requires = [ "gitlab-sidekiq.service" ];
wantedBy = [ "multi-user.target" ];
environment = gitlabEnv;

View file

@ -98,7 +98,7 @@ in
${pkgs.gollum}/bin/gollum \
--port ${toString cfg.port} \
--host ${cfg.address} \
--config ${builtins.toFile "gollum-config.rb" cfg.extraConfig} \
--config ${pkgs.writeText "gollum-config.rb" cfg.extraConfig} \
--ref ${cfg.branch} \
${optionalString cfg.mathjax "--mathjax"} \
${optionalString cfg.emoji "--emoji"} \

View file

@ -675,7 +675,7 @@ in {
}
];
users.users.matrix-synapse = {
users.users.matrix-synapse = {
group = "matrix-synapse";
home = cfg.dataDir;
createHome = true;

View file

@ -0,0 +1,78 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.pinnwand;
format = pkgs.formats.toml {};
configFile = format.generate "pinnwand.toml" cfg.settings;
in
{
options.services.pinnwand = {
enable = mkEnableOption "Pinnwand";
port = mkOption {
type = types.port;
description = "The port to listen on.";
default = 8000;
};
settings = mkOption {
type = format.type;
description = ''
Your <filename>pinnwand.toml</filename> as a Nix attribute set. Look up
possible options in the <link xlink:href="https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example">pinnwand.toml-example</link>.
'';
default = {
# https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example
database_uri = "sqlite:///var/lib/pinnwand/pinnwand.db";
preferred_lexeres = [];
paste_size = 262144;
paste_help = ''
<p>Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.</p><p>People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.</p>
'';
footer = ''
View <a href="//github.com/supakeen/pinnwand" target="_BLANK">source code</a>, the <a href="/removal">removal</a> or <a href="/expiry">expiry</a> stories, or read the <a href="/about">about</a> page.
'';
};
};
};
config = mkIf cfg.enable {
systemd.services.pinnwand = {
description = "Pinnwannd HTTP Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/";
serviceConfig = {
ExecStart = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile} http --port ${toString(cfg.port)}";
StateDirectory = "pinnwand";
StateDirectoryMode = "0700";
AmbientCapabilities = [];
CapabilityBoundingSet = "";
DevicePolicy = "closed";
DynamicUser = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = "@system-service";
UMask = "0077";
};
};
};
}

View file

@ -38,7 +38,7 @@ in
type = types.bool;
default = false;
description = ''
Whether to enable the Siproxd SIP
Whether to enable the Siproxd SIP
proxy/masquerading daemon.
'';
};
@ -111,7 +111,7 @@ in
type = types.int;
default = 300;
description = ''
Timeout for an RTP stream. If for the specified
Timeout for an RTP stream. If for the specified
number of seconds no data is relayed on an active
stream, it is considered dead and will be killed.
'';
@ -122,7 +122,7 @@ in
default = 46;
description = ''
DSCP (differentiated services) value to be assigned
to RTP packets. Allows QOS aware routers to handle
to RTP packets. Allows QOS aware routers to handle
different types traffic with different priorities.
'';
};
@ -132,7 +132,7 @@ in
default = 0;
description = ''
DSCP (differentiated services) value to be assigned
to SIP packets. Allows QOS aware routers to handle
to SIP packets. Allows QOS aware routers to handle
different types traffic with different priorities.
'';
};

View file

@ -11,7 +11,7 @@ in {
default = false;
description = ''
Enable the tzupdate timezone updating service. This provides
a one-shot service which can be activated with systemctl to
a one-shot service which can be activated with systemctl to
update the timezone.
'';
};
@ -21,7 +21,7 @@ in {
# We need to have imperative time zone management for this to work.
# This will give users an error if they have set an explicit time
# zone, which is better than silently overriding it.
time.timeZone = null;
time.timeZone = null;
# We provide a one-shot service which can be manually run. We could
# provide a service that runs on startup, but it's tricky to get

View file

@ -90,7 +90,7 @@ in {
default = [];
description = ''
Additional cadvisor options.
See <link xlink:href='https://github.com/google/cadvisor/blob/master/docs/runtime_options.md'/> for available options.
'';
};

View file

@ -97,11 +97,11 @@ let
"dd-agent/conf.d/nginx.yaml".source = nginxConfig;
}) //
(optionalAttrs (cfg.mongoConfig != null)
{
{
"dd-agent/conf.d/mongo.yaml".source = mongoConfig;
}) //
(optionalAttrs (cfg.processConfig != null)
{
{
"dd-agent/conf.d/process.yaml".source = processConfig;
}) //
(optionalAttrs (cfg.jmxConfig != null)

View file

@ -133,16 +133,6 @@ in {
}
];
systemd.tmpfiles.rules = [
"d /var/cache/netdata 0755 ${cfg.user} ${cfg.group} -"
"Z /var/cache/netdata - ${cfg.user} ${cfg.group} -"
"d /var/log/netdata 0755 ${cfg.user} ${cfg.group} -"
"Z /var/log/netdata - ${cfg.user} ${cfg.group} -"
"d /var/lib/netdata 0755 ${cfg.user} ${cfg.group} -"
"Z /var/lib/netdata - ${cfg.user} ${cfg.group} -"
"d /etc/netdata 0755 ${cfg.user} ${cfg.group} -"
"Z /etc/netdata - ${cfg.user} ${cfg.group} -"
];
systemd.services.netdata = {
description = "Real time performance monitoring";
after = [ "network.target" ];
@ -158,11 +148,40 @@ in {
# User and group
User = cfg.user;
Group = cfg.group;
# Runtime directory and mode
RuntimeDirectory = "netdata";
RuntimeDirectoryMode = "0755";
# Performance
LimitNOFILE = "30000";
# Runtime directory and mode
RuntimeDirectory = "netdata";
RuntimeDirectoryMode = "0750";
# State directory and mode
StateDirectory = "netdata";
StateDirectoryMode = "0750";
# Cache directory and mode
CacheDirectory = "netdata";
CacheDirectoryMode = "0750";
# Logs directory and mode
LogsDirectory = "netdata";
LogsDirectoryMode = "0750";
# Configuration directory and mode
ConfigurationDirectory = "netdata";
ConfigurationDirectoryMode = "0755";
# Capabilities
CapabilityBoundingSet = [
"CAP_DAC_OVERRIDE" # is required for freeipmi and slabinfo plugins
"CAP_DAC_READ_SEARCH" # is required for apps plugin
"CAP_FOWNER" # is required for freeipmi plugin
"CAP_SETPCAP" # is required for apps, perf and slabinfo plugins
"CAP_SYS_ADMIN" # is required for perf plugin
"CAP_SYS_PTRACE" # is required for apps plugin
"CAP_SYS_RESOURCE" # is required for ebpf plugin
"CAP_NET_RAW" # is required for fping app
];
# Sandboxing
ProtectSystem = "full";
ProtectHome = "read-only";
PrivateTmp = true;
ProtectControlGroups = true;
PrivateMounts = true;
};
};

View file

@ -18,7 +18,7 @@ let
${optionalString nm.enable ''
{
${pkgs.coreutils}/bin/cat << EOF
From: smartd on ${host} <root>
From: smartd on ${host} <${nm.sender}>
To: undisclosed-recipients:;
Subject: SMART error on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE
@ -129,6 +129,16 @@ in
description = "Whenever to send e-mail notifications.";
};
sender = mkOption {
default = "root";
example = "example@domain.tld";
type = types.str;
description = ''
Sender of the notification messages.
Acts as the value of <literal>email</literal> in the emails' <literal>From: ... </literal> field.
'';
};
recipient = mkOption {
default = "root";
type = types.str;

View file

@ -15,7 +15,7 @@ in
options = {
services.teamviewer.enable = mkEnableOption "TeamViewer daemon";
};
###### implementation

View file

@ -3,8 +3,9 @@
let
cfg = config.services.zabbixAgent;
inherit (lib) mkDefault mkEnableOption mkIf mkOption;
inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optionalString types;
inherit (lib.generators) toKeyValue;
user = "zabbix-agent";
group = "zabbix-agent";
@ -14,19 +15,15 @@ let
paths = attrValues cfg.modules;
};
configFile = pkgs.writeText "zabbix_agent.conf" ''
LogType = console
Server = ${cfg.server}
ListenIP = ${cfg.listen.ip}
ListenPort = ${toString cfg.listen.port}
${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
${cfg.extraConfig}
'';
configFile = pkgs.writeText "zabbix_agent.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
in
{
imports = [
(lib.mkRemovedOptionModule [ "services" "zabbixAgent" "extraConfig" ] "Use services.zabbixAgent.settings instead.")
];
# interface
options = {
@ -105,15 +102,18 @@ in
'';
};
# TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
extraConfig = mkOption {
default = "";
type = types.lines;
settings = mkOption {
type = with types; attrsOf (oneOf [ int str (listOf str) ]);
default = {};
description = ''
Configuration that is injected verbatim into the configuration file. Refer to
Zabbix Agent configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_agentd"/>
for details on supported values.
'';
example = {
Hostname = "example.org";
DebugLevel = 4;
};
};
};
@ -124,6 +124,17 @@ in
config = mkIf cfg.enable {
services.zabbixAgent.settings = mkMerge [
{
LogType = "console";
Server = cfg.server;
ListenIP = cfg.listen.ip;
ListenPort = cfg.listen.port;
LoadModule = builtins.attrNames cfg.modules;
}
(mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
];
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};

View file

@ -5,8 +5,9 @@ let
pgsql = config.services.postgresql;
mysql = config.services.mysql;
inherit (lib) mkDefault mkEnableOption mkIf mkOption;
inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optional optionalAttrs optionalString types;
inherit (lib.generators) toKeyValue;
user = "zabbix";
group = "zabbix";
@ -19,24 +20,7 @@ let
paths = attrValues cfg.modules;
};
configFile = pkgs.writeText "zabbix_proxy.conf" ''
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}"}
DBName = ${cfg.database.name}
DBUser = ${cfg.database.user}
${optionalString (cfg.database.passwordFile != null) "Include ${passwordFile}"}
${optionalString (mysqlLocal && cfg.database.socket != null) "DBSocket = ${cfg.database.socket}"}
SocketDir = ${runtimeDir}
FpingLocation = /run/wrappers/bin/fping
${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
${cfg.extraConfig}
'';
configFile = pkgs.writeText "zabbix_proxy.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
@ -44,6 +28,10 @@ let
in
{
imports = [
(lib.mkRemovedOptionModule [ "services" "zabbixProxy" "extraConfig" ] "Use services.zabbixProxy.settings instead.")
];
# interface
options = {
@ -182,15 +170,19 @@ in
'';
};
# TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
extraConfig = mkOption {
default = "";
type = types.lines;
settings = mkOption {
type = with types; attrsOf (oneOf [ int str (listOf str) ]);
default = {};
description = ''
Configuration that is injected verbatim into the configuration file. Refer to
Zabbix Proxy configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_proxy"/>
for details on supported values.
'';
example = {
CacheSize = "1G";
SSHKeyLocation = "/var/lib/zabbix/.ssh";
StartPingers = 32;
};
};
};
@ -213,6 +205,26 @@ in
}
];
services.zabbixProxy.settings = mkMerge [
{
LogType = "console";
ListenIP = cfg.listen.ip;
ListenPort = 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;
DBName = cfg.database.name;
DBUser = cfg.database.user;
SocketDir = runtimeDir;
FpingLocation = "/run/wrappers/bin/fping";
LoadModule = builtins.attrNames cfg.modules;
}
(mkIf (cfg.database.createLocally != true) { DBPort = cfg.database.port; })
(mkIf (cfg.database.passwordFile != null) { Include = [ "${passwordFile}" ]; })
(mkIf (mysqlLocal && cfg.database.socket != null) { DBSocket = cfg.database.socket; })
(mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
];
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};

View file

@ -5,8 +5,9 @@ let
pgsql = config.services.postgresql;
mysql = config.services.mysql;
inherit (lib) mkDefault mkEnableOption mkIf mkOption;
inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optional optionalAttrs optionalString types;
inherit (lib.generators) toKeyValue;
user = "zabbix";
group = "zabbix";
@ -19,24 +20,7 @@ let
paths = attrValues cfg.modules;
};
configFile = pkgs.writeText "zabbix_server.conf" ''
LogType = console
ListenIP = ${cfg.listen.ip}
ListenPort = ${toString cfg.listen.port}
# 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}"}
DBName = ${cfg.database.name}
DBUser = ${cfg.database.user}
${optionalString (cfg.database.passwordFile != null) "Include ${passwordFile}"}
${optionalString (mysqlLocal && cfg.database.socket != null) "DBSocket = ${cfg.database.socket}"}
PidFile = ${runtimeDir}/zabbix_server.pid
SocketDir = ${runtimeDir}
FpingLocation = /run/wrappers/bin/fping
${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
${cfg.extraConfig}
'';
configFile = pkgs.writeText "zabbix_server.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
@ -47,6 +31,7 @@ in
imports = [
(lib.mkRenamedOptionModule [ "services" "zabbixServer" "dbServer" ] [ "services" "zabbixServer" "database" "host" ])
(lib.mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.")
(lib.mkRemovedOptionModule [ "services" "zabbixServer" "extraConfig" ] "Use services.zabbixServer.settings instead.")
];
# interface
@ -176,15 +161,19 @@ in
'';
};
# TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
extraConfig = mkOption {
default = "";
type = types.lines;
settings = mkOption {
type = with types; attrsOf (oneOf [ int str (listOf str) ]);
default = {};
description = ''
Configuration that is injected verbatim into the configuration file. Refer to
Zabbix Server configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_server"/>
for details on supported values.
'';
example = {
CacheSize = "1G";
SSHKeyLocation = "/var/lib/zabbix/.ssh";
StartPingers = 32;
};
};
};
@ -204,6 +193,26 @@ in
}
];
services.zabbixServer.settings = mkMerge [
{
LogType = "console";
ListenIP = cfg.listen.ip;
ListenPort = cfg.listen.port;
# TODO: set to cfg.database.socket if database type is pgsql?
DBHost = optionalString (cfg.database.createLocally != true) cfg.database.host;
DBName = cfg.database.name;
DBUser = cfg.database.user;
PidFile = "${runtimeDir}/zabbix_server.pid";
SocketDir = runtimeDir;
FpingLocation = "/run/wrappers/bin/fping";
LoadModule = builtins.attrNames cfg.modules;
}
(mkIf (cfg.database.createLocally != true) { DBPort = cfg.database.port; })
(mkIf (cfg.database.passwordFile != null) { Include = [ "${passwordFile}" ]; })
(mkIf (mysqlLocal && cfg.database.socket != null) { DBSocket = cfg.database.socket; })
(mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
];
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};

View file

@ -25,6 +25,15 @@ let
then "/${lib.concatStringsSep "/" (lib.tail addr)}"
else null; # not valid for listen stream, skip
multiaddrToListenDatagram = addrRaw: let
addr = splitMulitaddr addrRaw;
s = builtins.elemAt addr;
in if s 0 == "ip4" && s 2 == "udp"
then "${s 1}:${s 3}"
else if s 0 == "ip6" && s 2 == "udp"
then "[${s 1}]:${s 3}"
else null; # not valid for listen datagram, skip
in {
###### interface
@ -96,6 +105,8 @@ in {
default = [
"/ip4/0.0.0.0/tcp/4001"
"/ip6/::/tcp/4001"
"/ip4/0.0.0.0/udp/4001/quic"
"/ip6/::/udp/4001/quic"
];
description = "Where IPFS listens for incoming p2p connections";
};
@ -266,9 +277,14 @@ in {
systemd.sockets.ipfs-gateway = {
wantedBy = [ "sockets.target" ];
socketConfig.ListenStream = let
fromCfg = multiaddrToListenStream cfg.gatewayAddress;
in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
socketConfig = {
ListenStream = let
fromCfg = multiaddrToListenStream cfg.gatewayAddress;
in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
ListenDatagram = let
fromCfg = multiaddrToListenDatagram cfg.gatewayAddress;
in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
};
};
systemd.sockets.ipfs-api = {

View file

@ -183,8 +183,8 @@ in
}
]) eachBitcoind);
environment.systemPackages = flatten (mapAttrsToList (bitcoindName: cfg: [
cfg.package
environment.systemPackages = flatten (mapAttrsToList (bitcoindName: cfg: [
cfg.package
]) eachBitcoind);
systemd.services = mapAttrs' (bitcoindName: cfg: (

View file

@ -269,4 +269,7 @@ in
users.groups = mapAttrs' (instanceName: cfg: (
nameValuePair "${cfg.group}" { })) eachBlockbook;
};
meta.maintainers = with maintainers; [ maintainers."1000101" ];
}

View file

@ -81,6 +81,7 @@ in {
NotifyAccess = "main";
ExecStart = "${getBin cfg.package}/bin/corerad -c=${cfg.configFile}";
Restart = "on-failure";
RestartKillSignal = "SIGHUP";
};
};
};

View file

@ -56,4 +56,4 @@ config = mkIf cfg.enable {
};
};
}

View file

@ -0,0 +1,152 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jicofo;
in
{
options.services.jicofo = with types; {
enable = mkEnableOption "Jitsi Conference Focus - component of Jitsi Meet";
xmppHost = mkOption {
type = str;
example = "localhost";
description = ''
Hostname of the XMPP server to connect to.
'';
};
xmppDomain = mkOption {
type = nullOr str;
example = "meet.example.org";
description = ''
Domain name of the XMMP server to which to connect as a component.
If null, <option>xmppHost</option> is used.
'';
};
componentPasswordFile = mkOption {
type = str;
example = "/run/keys/jicofo-component";
description = ''
Path to file containing component secret.
'';
};
userName = mkOption {
type = str;
default = "focus";
description = ''
User part of the JID for XMPP user connection.
'';
};
userDomain = mkOption {
type = str;
example = "auth.meet.example.org";
description = ''
Domain part of the JID for XMPP user connection.
'';
};
userPasswordFile = mkOption {
type = str;
example = "/run/keys/jicofo-user";
description = ''
Path to file containing password for XMPP user connection.
'';
};
bridgeMuc = mkOption {
type = str;
example = "jvbbrewery@internal.meet.example.org";
description = ''
JID of the internal MUC used to communicate with Videobridges.
'';
};
config = mkOption {
type = attrsOf str;
default = { };
example = literalExample ''
{
"org.jitsi.jicofo.auth.URL" = "XMPP:jitsi-meet.example.com";
}
'';
description = ''
Contents of the <filename>sip-communicator.properties</filename> configuration file for jicofo.
'';
};
};
config = mkIf cfg.enable {
services.jicofo.config = mapAttrs (_: v: mkDefault v) {
"org.jitsi.jicofo.BRIDGE_MUC" = cfg.bridgeMuc;
};
users.groups.jitsi-meet = {};
systemd.services.jicofo = let
jicofoProps = {
"-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "jicofo";
"-Djava.util.logging.config.file" = "/etc/jitsi/jicofo/logging.properties";
};
in
{
description = "JItsi COnference FOcus";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
restartTriggers = [
config.environment.etc."jitsi/jicofo/sip-communicator.properties".source
];
environment.JAVA_SYS_PROPS = concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") jicofoProps);
script = ''
${pkgs.jicofo}/bin/jicofo \
--host=${cfg.xmppHost} \
--domain=${if cfg.xmppDomain == null then cfg.xmppHost else cfg.xmppDomain} \
--secret=$(cat ${cfg.componentPasswordFile}) \
--user_name=${cfg.userName} \
--user_domain=${cfg.userDomain} \
--user_password=$(cat ${cfg.userPasswordFile})
'';
serviceConfig = {
Type = "exec";
DynamicUser = true;
User = "jicofo";
Group = "jitsi-meet";
CapabilityBoundingSet = "";
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictNamespaces = true;
LockPersonality = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
};
};
environment.etc."jitsi/jicofo/sip-communicator.properties".source =
pkgs.writeText "sip-communicator.properties" (
generators.toKeyValue {} cfg.config
);
environment.etc."jitsi/jicofo/logging.properties".source =
mkDefault "${pkgs.jicofo}/etc/jitsi/jicofo/logging.properties-journal";
};
meta.maintainers = lib.teams.jitsi.members;
}

View file

@ -0,0 +1,276 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jitsi-videobridge;
attrsToArgs = a: concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") a);
# HOCON is a JSON superset that videobridge2 uses for configuration.
# It can substitute environment variables which we use for passwords here.
# https://github.com/lightbend/config/blob/master/README.md
#
# Substitution for environment variable FOO is represented as attribute set
# { __hocon_envvar = "FOO"; }
toHOCON = x: if isAttrs x && x ? __hocon_envvar then ("\${" + x.__hocon_envvar + "}")
else if isAttrs x then "{${ concatStringsSep "," (mapAttrsToList (k: v: ''"${k}":${toHOCON v}'') x) }}"
else if isList x then "[${ concatMapStringsSep "," toHOCON x }]"
else builtins.toJSON x;
# We're passing passwords in environment variables that have names generated
# from an attribute name, which may not be a valid bash identifier.
toVarName = s: "XMPP_PASSWORD_" + stringAsChars (c: if builtins.match "[A-Za-z0-9]" c != null then c else "_") s;
defaultJvbConfig = {
videobridge = {
ice = {
tcp = {
enabled = true;
port = 4443;
};
udp.port = 10000;
};
stats = {
enabled = true;
transports = [ { type = "muc"; } ];
};
apis.xmpp-client.configs = flip mapAttrs cfg.xmppConfigs (name: xmppConfig: {
hostname = xmppConfig.hostName;
domain = xmppConfig.domain;
username = xmppConfig.userName;
password = { __hocon_envvar = toVarName name; };
muc_jids = xmppConfig.mucJids;
muc_nickname = xmppConfig.mucNickname;
disable_certificate_verification = xmppConfig.disableCertificateVerification;
});
};
};
# Allow overriding leaves of the default config despite types.attrs not doing any merging.
jvbConfig = recursiveUpdate defaultJvbConfig cfg.config;
in
{
options.services.jitsi-videobridge = with types; {
enable = mkEnableOption "Jitsi Videobridge, a WebRTC compatible video router";
config = mkOption {
type = attrs;
default = { };
example = literalExample ''
{
videobridge = {
ice.udp.port = 5000;
websockets = {
enabled = true;
server-id = "jvb1";
};
};
}
'';
description = ''
Videobridge configuration.
See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/src/main/resources/reference.conf" />
for default configuration with comments.
'';
};
xmppConfigs = mkOption {
description = ''
XMPP servers to connect to.
See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/doc/muc.md" /> for more information.
'';
default = { };
example = literalExample ''
{
"localhost" = {
hostName = "localhost";
userName = "jvb";
domain = "auth.xmpp.example.org";
passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
mucJids = "jvbbrewery@internal.xmpp.example.org";
};
}
'';
type = attrsOf (submodule ({ name, ... }: {
options = {
hostName = mkOption {
type = str;
example = "xmpp.example.org";
description = ''
Hostname of the XMPP server to connect to. Name of the attribute set is used by default.
'';
};
domain = mkOption {
type = nullOr str;
default = null;
example = "auth.xmpp.example.org";
description = ''
Domain part of JID of the XMPP user, if it is different from hostName.
'';
};
userName = mkOption {
type = str;
default = "jvb";
description = ''
User part of the JID.
'';
};
passwordFile = mkOption {
type = str;
example = "/run/keys/jitsi-videobridge-xmpp1";
description = ''
File containing the password for the user.
'';
};
mucJids = mkOption {
type = str;
example = "jvbbrewery@internal.xmpp.example.org";
description = ''
JID of the MUC to join. JiCoFo needs to be configured to join the same MUC.
'';
};
mucNickname = mkOption {
# Upstream DEBs use UUID, let's use hostname instead.
type = str;
description = ''
Videobridges use the same XMPP account and need to be distinguished by the
nickname (aka resource part of the JID). By default, system hostname is used.
'';
};
disableCertificateVerification = mkOption {
type = bool;
default = false;
description = ''
Whether to skip validation of the server's certificate.
'';
};
};
config = {
hostName = mkDefault name;
mucNickname = mkDefault (builtins.replaceStrings [ "." ] [ "-" ] (
config.networking.hostName + optionalString (config.networking.domain != null) ".${config.networking.domain}"
));
};
}));
};
nat = {
localAddress = mkOption {
type = nullOr str;
default = null;
example = "192.168.1.42";
description = ''
Local address when running behind NAT.
'';
};
publicAddress = mkOption {
type = nullOr str;
default = null;
example = "1.2.3.4";
description = ''
Public address when running behind NAT.
'';
};
};
extraProperties = mkOption {
type = attrsOf str;
default = { };
description = ''
Additional Java properties passed to jitsi-videobridge.
'';
};
openFirewall = mkOption {
type = bool;
default = false;
description = ''
Whether to open ports in the firewall for the videobridge.
'';
};
};
config = mkIf cfg.enable {
users.groups.jitsi-meet = {};
services.jitsi-videobridge.extraProperties = optionalAttrs (cfg.nat.localAddress != null) {
"org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS" = cfg.nat.localAddress;
"org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS" = cfg.nat.publicAddress;
};
systemd.services.jitsi-videobridge2 = let
jvbProps = {
"-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
"-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "videobridge";
"-Djava.util.logging.config.file" = "/etc/jitsi/videobridge/logging.properties";
"-Dconfig.file" = pkgs.writeText "jvb.conf" (toHOCON jvbConfig);
} // (mapAttrs' (k: v: nameValuePair "-D${k}" v) cfg.extraProperties);
in
{
aliases = [ "jitsi-videobridge.service" ];
description = "Jitsi Videobridge";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment.JAVA_SYS_PROPS = attrsToArgs jvbProps;
script = (concatStrings (mapAttrsToList (name: xmppConfig:
"export ${toVarName name}=$(cat ${xmppConfig.passwordFile})\n"
) cfg.xmppConfigs))
+ ''
${pkgs.jitsi-videobridge}/bin/jitsi-videobridge --apis=none
'';
serviceConfig = {
Type = "exec";
DynamicUser = true;
User = "jitsi-videobridge";
Group = "jitsi-meet";
CapabilityBoundingSet = "";
NoNewPrivileges = true;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectHostname = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictNamespaces = true;
LockPersonality = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
TasksMax = 65000;
LimitNPROC = 65000;
LimitNOFILE = 65000;
};
};
environment.etc."jitsi/videobridge/logging.properties".source =
mkDefault "${pkgs.jitsi-videobridge}/etc/jitsi/videobridge/logging.properties-journal";
# (from videobridge2 .deb)
# this sets the max, so that we can bump the JVB UDP single port buffer size.
boot.kernel.sysctl."net.core.rmem_max" = mkDefault 10485760;
boot.kernel.sysctl."net.core.netdev_max_backlog" = mkDefault 100000;
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall
[ jvbConfig.videobridge.ice.tcp.port ];
networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall
[ jvbConfig.videobridge.ice.udp.port ];
assertions = [{
message = "publicAddress must be set if and only if localAddress is set";
assertion = (cfg.nat.publicAddress == null) == (cfg.nat.localAddress == null);
}];
};
meta.maintainers = lib.teams.jitsi.members;
}

View file

@ -5,7 +5,7 @@ in
with lib;
{
options.services.mstpd = {
enable = mkOption {
default = false;
type = types.bool;

View file

@ -0,0 +1,44 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.nextdns;
in {
options = {
services.nextdns = {
enable = mkOption {
type = types.bool;
default = false;
description = "Whether to enable the NextDNS DNS/53 to DoH Proxy service.";
};
arguments = mkOption {
type = types.listOf types.str;
default = [];
example = [ "-config" "10.0.3.0/24=abcdef" ];
description = "Additional arguments to be passed to nextdns run.";
};
};
};
# https://github.com/nextdns/nextdns/blob/628ea509eaaccd27adb66337db03e5b56f6f38a8/host/service/systemd/service.go
config = mkIf cfg.enable {
systemd.services.nextdns = {
description = "NextDNS DNS/53 to DoH Proxy";
environment = {
SERVICE_RUN_MODE = "1";
};
serviceConfig = {
StartLimitInterval = 5;
StartLimitBurst = 10;
ExecStart = "${pkgs.nextdns}/bin/nextdns run ${escapeShellArgs config.services.nextdns.arguments}";
RestartSec = 120;
LimitMEMLOCK = "infinity";
};
after = [ "network.target" ];
before = [ "nss-lookup.target" ];
wants = [ "nss-lookup.target" ];
wantedBy = [ "multi-user.target" ];
};
};
}

View file

@ -60,7 +60,7 @@ let
# NB: nghttpx doesn't accept "tls", you must omit "no-tls" for
# the default behavior of turning on TLS.
params1 = lib.remove "tls" params0;
sections = [ host] ++ params1;
formattedSections = lib.concatStringsSep ";" sections;
in
@ -90,7 +90,7 @@ in
{ imports = [
./nghttpx-options.nix
];
config = lib.mkIf cfg.enable {
users.groups.nghttpx = { };
@ -98,7 +98,7 @@ in
group = config.users.groups.nghttpx.name;
isSystemUser = true;
};
systemd.services = {
nghttpx = {

View file

@ -23,7 +23,7 @@ in {
### Documentation
# meta.doc = ./onedrive.xml;
### Interface
### Interface
options.services.onedrive = {
enable = lib.mkOption {

View file

@ -772,7 +772,7 @@ in
};
disco_items = {
${ lib.concatStringsSep "\n" (builtins.map (x: ''{ "${x.url}", "${x.description}"};'') discoItems)}
${ lib.concatStringsSep "\n" (builtins.map (x: ''{ "${x.url}", "${x.description}"};'') discoItems)}
};
allow_registration = ${toLua cfg.allowRegistration}

View file

@ -76,9 +76,9 @@ in
networking.supplicant = mkOption {
type = with types; attrsOf (submodule {
options = {
configFile = {
path = mkOption {
type = types.nullOr types.path;
default = null;
@ -89,7 +89,7 @@ in
precedence over options defined in <literal>configFile</literal>.
'';
};
writable = mkOption {
type = types.bool;
default = false;
@ -98,9 +98,9 @@ in
<literal>wpa_supplicant</literal>.
'';
};
};
extraConf = mkOption {
type = types.lines;
default = "";
@ -126,7 +126,7 @@ in
use the <literal>configFile</literal> instead.
'';
};
extraCmdArgs = mkOption {
type = types.str;
default = "";
@ -134,21 +134,21 @@ in
description =
"Command line arguments to add when executing <literal>wpa_supplicant</literal>.";
};
driver = mkOption {
type = types.nullOr types.str;
default = "nl80211,wext";
description = "Force a specific wpa_supplicant driver.";
};
bridge = mkOption {
type = types.str;
default = "";
description = "Name of the bridge interface that wpa_supplicant should listen at.";
};
userControlled = {
enable = mkOption {
type = types.bool;
default = false;
@ -159,20 +159,20 @@ in
access points.
'';
};
socketDir = mkOption {
type = types.str;
default = "/run/wpa_supplicant";
description = "Directory of sockets for controlling wpa_supplicant.";
};
group = mkOption {
type = types.str;
default = "wheel";
example = "network";
description = "Members of this group can control wpa_supplicant.";
};
};
};
});

View file

@ -106,7 +106,9 @@ in
Restart = "always";
};
};
};
meta.maintainers = with maintainers; [ maintainers."1000101" ];
};
}

View file

@ -5,12 +5,12 @@ with lib;
let cfg = config.services.networking.websockify; in {
options = {
services.networking.websockify = {
enable = mkOption {
enable = mkOption {
description = "Whether to enable websockify to forward websocket connections to TCP connections.";
default = false;
default = false;
type = types.bool;
type = types.bool;
};
sslCert = mkOption {

View file

@ -21,11 +21,11 @@ in
type = types.bool;
default = false;
description = ''
Whether to enable to haveged entropy daemon, which refills
Whether to enable to haveged entropy daemon, which refills
/dev/random when low.
'';
};
refill_threshold = mkOption {
type = types.int;
default = 1024;
@ -34,16 +34,16 @@ in
haveged should refill the entropy pool.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
systemd.services.haveged =
{ description = "Entropy Harvesting Daemon";
unitConfig.Documentation = "man:haveged(8)";
@ -63,5 +63,5 @@ in
};
};
}

View file

@ -234,7 +234,6 @@ in
ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
NotifyAccess = "main";
KillSignal = "SIGQUIT";
StandardError = "syslog";
};
};

View file

@ -1,37 +1,39 @@
{config, lib, pkgs, ... }:
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.usbguard;
# valid policy options
policy = (types.enum [ "allow" "block" "reject" "keep" "apply-policy" ]);
defaultRuleFile = "/var/lib/usbguard/rules.conf";
# decide what file to use for rules
ruleFile = if cfg.rules != null then pkgs.writeText "usbguard-rules" cfg.rules else cfg.ruleFile;
ruleFile = if cfg.rules != null then pkgs.writeText "usbguard-rules" cfg.rules else defaultRuleFile;
daemonConf = ''
# generated by nixos/modules/services/security/usbguard.nix
RuleFile=${ruleFile}
ImplicitPolicyTarget=${cfg.implictPolicyTarget}
PresentDevicePolicy=${cfg.presentDevicePolicy}
PresentControllerPolicy=${cfg.presentControllerPolicy}
InsertedDevicePolicy=${cfg.insertedDevicePolicy}
RestoreControllerDeviceState=${if cfg.restoreControllerDeviceState then "true" else "false"}
# this does not seem useful for endusers to change
DeviceManagerBackend=uevent
IPCAllowedUsers=${concatStringsSep " " cfg.IPCAllowedUsers}
IPCAllowedGroups=${concatStringsSep " " cfg.IPCAllowedGroups}
IPCAccessControlFiles=${cfg.IPCAccessControlFiles}
DeviceRulesWithPort=${if cfg.deviceRulesWithPort then "true" else "false"}
AuditFilePath=${cfg.auditFilePath}
'';
# generated by nixos/modules/services/security/usbguard.nix
RuleFile=${ruleFile}
ImplicitPolicyTarget=${cfg.implictPolicyTarget}
PresentDevicePolicy=${cfg.presentDevicePolicy}
PresentControllerPolicy=${cfg.presentControllerPolicy}
InsertedDevicePolicy=${cfg.insertedDevicePolicy}
RestoreControllerDeviceState=${if cfg.restoreControllerDeviceState then "true" else "false"}
# this does not seem useful for endusers to change
DeviceManagerBackend=uevent
IPCAllowedUsers=${concatStringsSep " " cfg.IPCAllowedUsers}
IPCAllowedGroups=${concatStringsSep " " cfg.IPCAllowedGroups}
IPCAccessControlFiles=/var/lib/usbguard/IPCAccessControl.d/
DeviceRulesWithPort=${if cfg.deviceRulesWithPort then "true" else "false"}
# HACK: that way audit logs still land in the journal
AuditFilePath=/dev/null
'';
daemonConfFile = pkgs.writeText "usbguard-daemon-conf" daemonConf;
daemonConfFile = pkgs.writeText "usbguard-daemon-conf" daemonConf;
in {
in
{
###### interface
@ -49,22 +51,6 @@ in {
'';
};
ruleFile = mkOption {
type = types.path;
default = "/var/lib/usbguard/rules.conf";
description = ''
The USBGuard daemon will use this file to load the policy rule set
from it and to write new rules received via the IPC interface.
Running the command <literal>usbguard generate-policy</literal> as
root will generate a config for your currently plugged in devices.
For a in depth guide consult the official documentation.
Setting the <literal>rules</literal> option will ignore the
<literal>ruleFile</literal> option.
'';
};
rules = mkOption {
type = types.nullOr types.lines;
default = null;
@ -72,16 +58,20 @@ in {
allow with-interface equals { 08:*:* }
'';
description = ''
The USBGuard daemon will load this policy rule set. Modifying it via
the IPC interface won't work if you use this option, since the
contents of this option will be written into the nix-store it will be
read-only.
The USBGuard daemon will load this as the policy rule set.
As these rules are NixOS managed they are immutable and can't
be changed by the IPC interface.
You can still use <literal> usbguard generate-policy</literal> to
generate rules, but you would have to insert them here.
If you do not set this option, the USBGuard daemon will load
it's policy rule set from <literal>${defaultRuleFile}</literal>.
This file can be changed manually or via the IPC interface.
Setting the <literal>rules</literal> option will ignore the
<literal>ruleFile</literal> option.
Running <literal>usbguard generate-policy</literal> as root will
generate a config for your currently plugged in devices.
For more details see <citerefentry>
<refentrytitle>usbguard-rules.conf</refentrytitle>
<manvolnum>5</manvolnum></citerefentry>.
'';
};
@ -155,17 +145,6 @@ in {
'';
};
IPCAccessControlFiles = mkOption {
type = types.path;
default = "/var/lib/usbguard/IPCAccessControl.d/";
description = ''
The files at this location will be interpreted by the daemon as IPC
access control definition files. See the IPC ACCESS CONTROL section
in <citerefentry><refentrytitle>usbguard-daemon.conf</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for more details.
'';
};
deviceRulesWithPort = mkOption {
type = types.bool;
default = false;
@ -173,14 +152,6 @@ in {
Generate device specific rules including the "via-port" attribute.
'';
};
auditFilePath = mkOption {
type = types.path;
default = "/var/log/usbguard/usbguard-audit.log";
description = ''
USBGuard audit events log file path.
'';
};
};
};
@ -197,17 +168,19 @@ in {
wantedBy = [ "basic.target" ];
wants = [ "systemd-udevd.service" ];
# make sure an empty rule file and required directories exist
preStart = ''
mkdir -p $(dirname "${cfg.ruleFile}") $(dirname "${cfg.auditFilePath}") "${cfg.IPCAccessControlFiles}" \
&& ([ -f "${cfg.ruleFile}" ] || touch ${cfg.ruleFile})
'';
# make sure an empty rule file exists
preStart = ''[ -f "${ruleFile}" ] || touch ${ruleFile}'';
serviceConfig = {
Type = "simple";
ExecStart = ''${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}'';
Restart = "on-failure";
StateDirectory = [
"usbguard"
"usbguard/IPCAccessControl.d"
];
AmbientCapabilities = "";
CapabilityBoundingSet = "CAP_CHOWN CAP_FOWNER";
DeviceAllow = "/dev/null rw";
@ -223,8 +196,8 @@ in {
ProtectKernelModules = true;
ProtectSystem = true;
ReadOnlyPaths = "-/";
ReadWritePaths = "-/dev/shm -${dirOf cfg.auditFilePath} -/tmp -${dirOf cfg.ruleFile}";
RestrictAddressFamilies = "AF_UNIX AF_NETLINK";
ReadWritePaths = "-/dev/shm -/tmp";
RestrictAddressFamilies = [ "AF_UNIX" "AF_NETLINK" ];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
@ -233,4 +206,9 @@ in {
};
};
};
imports = [
(mkRemovedOptionModule [ "services" "usbguard" "ruleFile" ] "The usbguard module now uses ${defaultRuleFile} as ruleFile. Alternatively, use services.usbguard.rules to configure rules.")
(mkRemovedOptionModule [ "services" "usbguard" "IPCAccessControlFiles" ] "The usbguard module now hardcodes IPCAccessControlFiles to /var/lib/usbguard/IPCAccessControl.d.")
(mkRemovedOptionModule [ "services" "usbguard" "auditFilePath" ] "Removed usbguard module audit log files. Audit logs can be found in the systemd journal.")
];
}

View file

@ -106,7 +106,6 @@ in
path = optional ecfg.enableNotifications pkgs.dbus;
serviceConfig = {
StandardOutput = "null";
StandardError = "syslog";
ExecStart = ''
${pkgs.earlyoom}/bin/earlyoom \
-m ${toString ecfg.freeMemThreshold} \

View file

@ -1,52 +1,51 @@
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, options, ... }:
with lib;
let
cfg = config.services.transmission;
inherit (config.environment) etc;
apparmor = config.security.apparmor.enable;
homeDir = cfg.home;
downloadDirPermissions = cfg.downloadDirPermissions;
downloadDir = "${homeDir}/Downloads";
incompleteDir = "${homeDir}/.incomplete";
settingsDir = "${homeDir}/config";
settingsFile = pkgs.writeText "settings.json" (builtins.toJSON fullSettings);
# for users in group "transmission" to have access to torrents
fullSettings = { umask = 2; download-dir = downloadDir; incomplete-dir = incompleteDir; } // cfg.settings;
preStart = pkgs.writeScript "transmission-pre-start" ''
#!${pkgs.runtimeShell}
set -ex
cp -f ${settingsFile} ${settingsDir}/settings.json
'';
rootDir = "/run/transmission";
homeDir = "/var/lib/transmission";
settingsDir = ".config/transmission-daemon";
downloadsDir = "Downloads";
incompleteDir = ".incomplete";
# TODO: switch to configGen.json once RFC0042 is implemented
settingsFile = pkgs.writeText "settings.json" (builtins.toJSON cfg.settings);
in
{
options = {
services.transmission = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether or not to enable the headless Transmission BitTorrent daemon.
enable = mkEnableOption ''the headless Transmission BitTorrent daemon.
Transmission daemon can be controlled via the RPC interface using
transmission-remote or the WebUI (http://localhost:9091/ by default).
Transmission daemon can be controlled via the RPC interface using
transmission-remote, the WebUI (http://127.0.0.1:9091/ by default),
or other clients like stig or tremc.
Torrents are downloaded to ${downloadDir} by default and are
accessible to users in the "transmission" group.
'';
};
Torrents are downloaded to ${homeDir}/${downloadsDir} by default and are
accessible to users in the "transmission" group'';
settings = mkOption {
settings = mkOption rec {
# TODO: switch to types.config.json as prescribed by RFC0042 once it's implemented
type = types.attrs;
apply = recursiveUpdate default;
default =
{
download-dir = downloadDir;
incomplete-dir = incompleteDir;
download-dir = "${cfg.home}/${downloadsDir}";
incomplete-dir = "${cfg.home}/${incompleteDir}";
incomplete-dir-enabled = true;
message-level = 1;
peer-port = 51413;
peer-port-random-high = 65535;
peer-port-random-low = 49152;
peer-port-random-on-start = false;
rpc-bind-address = "127.0.0.1";
rpc-port = 9091;
script-torrent-done-enabled = false;
script-torrent-done-filename = "";
umask = 2; # 0o002 in decimal as expected by Transmission
utp-enabled = true;
};
example =
{
@ -56,11 +55,12 @@ in
rpc-whitelist = "127.0.0.1,192.168.*.*";
};
description = ''
Attribute set whos fields overwrites fields in settings.json (each
time the service starts). String values must be quoted, integer and
Attribute set whose fields overwrites fields in
<literal>.config/transmission-daemon/settings.json</literal>
(each time the service starts). String values must be quoted, integer and
boolean values must not.
See https://github.com/transmission/transmission/wiki/Editing-Configuration-Files
See <link xlink:href="https://github.com/transmission/transmission/wiki/Editing-Configuration-Files">Transmission's Wiki</link>
for documentation.
'';
};
@ -70,22 +70,32 @@ in
default = "770";
example = "775";
description = ''
The permissions to set for download-dir and incomplete-dir.
They will be applied on every service start.
The permissions set by <literal>systemd.activationScripts.transmission-daemon</literal>
on the directories <link linkend="opt-services.transmission.settings">settings.download-dir</link>
and <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link>.
Note that you may also want to change
<link linkend="opt-services.transmission.settings">settings.umask</link>.
'';
};
port = mkOption {
type = types.int;
default = 9091;
description = "TCP port number to run the RPC/web interface.";
type = types.port;
description = ''
TCP port number to run the RPC/web interface.
If instead you want to change the peer port,
use <link linkend="opt-services.transmission.settings">settings.peer-port</link>
or <link linkend="opt-services.transmission.settings">settings.peer-port-random-on-start</link>.
'';
};
home = mkOption {
type = types.path;
default = "/var/lib/transmission";
default = homeDir;
description = ''
The directory where transmission will create files.
The directory where Transmission will create <literal>${settingsDir}</literal>.
as well as <literal>${downloadsDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.download-dir</link> is changed,
and <literal>${incompleteDir}/</literal> unless <link linkend="opt-services.transmission.settings">settings.incomplete-dir</link> is changed.
'';
};
@ -100,32 +110,174 @@ in
default = "transmission";
description = "Group account under which Transmission runs.";
};
credentialsFile = mkOption {
type = types.path;
description = ''
Path to a JSON file to be merged with the settings.
Useful to merge a file which is better kept out of the Nix store
because it contains sensible data like <link linkend="opt-services.transmission.settings">settings.rpc-password</link>.
'';
default = "/dev/null";
example = "/var/lib/secrets/transmission/settings.json";
};
openFirewall = mkEnableOption "opening of the peer port(s) in the firewall";
performanceNetParameters = mkEnableOption ''tweaking of kernel parameters
to open many more connections at the same time.
Note that you may also want to increase
<link linkend="opt-services.transmission.settings">settings.peer-limit-global</link>.
And be aware that these settings are quite aggressive
and might not suite your regular desktop use.
For instance, SSH sessions may time out more easily'';
};
};
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [
"d '${homeDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
"d '${settingsDir}' 0700 '${cfg.user}' '${cfg.group}' - -"
"d '${fullSettings.download-dir}' '${downloadDirPermissions}' '${cfg.user}' '${cfg.group}' - -"
"d '${fullSettings.incomplete-dir}' '${downloadDirPermissions}' '${cfg.user}' '${cfg.group}' - -"
# Note that using systemd.tmpfiles would not work here
# because it would fail when creating a directory
# with a different owner than its parent directory, by saying:
# Detected unsafe path transition /home/foo → /home/foo/Downloads during canonicalization of /home/foo/Downloads
# when /home/foo is not owned by cfg.user.
# Note also that using an ExecStartPre= wouldn't work either
# because BindPaths= needs these directories before.
system.activationScripts.transmission-daemon = ''
install -d -m 700 '${cfg.home}/${settingsDir}'
chown -R '${cfg.user}:${cfg.group}' ${cfg.home}/${settingsDir}
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.download-dir}'
'' + optionalString cfg.settings.incomplete-dir-enabled ''
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.incomplete-dir}'
'';
assertions = [
{ assertion = builtins.match "^/.*" cfg.home != null;
message = "`services.transmission.home' must be an absolute path.";
}
{ assertion = types.path.check cfg.settings.download-dir;
message = "`services.transmission.settings.download-dir' must be an absolute path.";
}
{ assertion = types.path.check cfg.settings.incomplete-dir;
message = "`services.transmission.settings.incomplete-dir' must be an absolute path.";
}
{ assertion = cfg.settings.script-torrent-done-filename == "" || types.path.check cfg.settings.script-torrent-done-filename;
message = "`services.transmission.settings.script-torrent-done-filename' must be an absolute path.";
}
{ assertion = types.port.check cfg.settings.rpc-port;
message = "${toString cfg.settings.rpc-port} is not a valid port number for `services.transmission.settings.rpc-port`.";
}
# In case both port and settings.rpc-port are explicitely defined: they must be the same.
{ assertion = !options.services.transmission.port.isDefined || cfg.port == cfg.settings.rpc-port;
message = "`services.transmission.port' is not equal to `services.transmission.settings.rpc-port'";
}
];
services.transmission.settings =
optionalAttrs options.services.transmission.port.isDefined { rpc-port = cfg.port; };
systemd.services.transmission = {
description = "Transmission BitTorrent Service";
after = [ "network.target" ] ++ optional apparmor "apparmor.service";
requires = mkIf apparmor [ "apparmor.service" ];
requires = optional apparmor "apparmor.service";
wantedBy = [ "multi-user.target" ];
environment.CURL_CA_BUNDLE = etc."ssl/certs/ca-certificates.crt".source;
# 1) Only the "transmission" user and group have access to torrents.
# 2) Optionally update/force specific fields into the configuration file.
serviceConfig.ExecStartPre = preStart;
serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port} --config-dir ${settingsDir}";
serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
serviceConfig.User = cfg.user;
serviceConfig.Group = cfg.group;
# NOTE: transmission has an internal umask that also must be set (in settings.json)
serviceConfig.UMask = "0002";
serviceConfig = {
# Use "+" because credentialsFile may not be accessible to User= or Group=.
ExecStartPre = [("+" + pkgs.writeShellScript "transmission-prestart" ''
set -eu${lib.optionalString (cfg.settings.message-level >= 3) "x"}
${pkgs.jq}/bin/jq --slurp add ${settingsFile} '${cfg.credentialsFile}' |
install -D -m 600 -o '${cfg.user}' -g '${cfg.group}' /dev/stdin \
'${cfg.home}/${settingsDir}/settings.json'
'')];
ExecStart="${pkgs.transmission}/bin/transmission-daemon -f";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = cfg.user;
Group = cfg.group;
# Create rootDir in the host's mount namespace.
RuntimeDirectory = [(baseNameOf rootDir)];
RuntimeDirectoryMode = "755";
# Avoid mounting rootDir in the own rootDir of ExecStart='s mount namespace.
InaccessiblePaths = ["-+${rootDir}"];
# This is for BindPaths= and BindReadOnlyPaths=
# to allow traversal of directories they create in RootDirectory=.
UMask = "0066";
# Using RootDirectory= makes it possible
# to use the same paths download-dir/incomplete-dir
# (which appear in user's interfaces) without requiring cfg.user
# to have access to their parent directories,
# by using BindPaths=/BindReadOnlyPaths=.
# Note that TemporaryFileSystem= could have been used instead
# but not without adding some BindPaths=/BindReadOnlyPaths=
# that would only be needed for ExecStartPre=,
# because RootDirectoryStartOnly=true would not help.
RootDirectory = rootDir;
RootDirectoryStartOnly = true;
MountAPIVFS = true;
BindPaths =
[ "${cfg.home}/${settingsDir}"
cfg.settings.download-dir
] ++
optional cfg.settings.incomplete-dir-enabled
cfg.settings.incomplete-dir;
BindReadOnlyPaths = [
# No confinement done of /nix/store here like in systemd-confinement.nix,
# an AppArmor profile is provided to get a confinement based upon paths and rights.
builtins.storeDir
"-/etc/hosts"
"-/etc/ld-nix.so.preload"
"-/etc/localtime"
] ++
optional (cfg.settings.script-torrent-done-enabled &&
cfg.settings.script-torrent-done-filename != "")
cfg.settings.script-torrent-done-filename;
# The following options are only for optimizing:
# systemd-analyze security transmission
AmbientCapabilities = "";
CapabilityBoundingSet = "";
# ProtectClock= adds DeviceAllow=char-rtc r
DeviceAllow = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateNetwork = mkDefault false;
PrivateTmp = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
# ProtectHome=true would not allow BindPaths= to work accross /home,
# and ProtectHome=tmpfs would break statfs(),
# preventing transmission-daemon to report the available free space.
# However, RootDirectory= is used, so this is not a security concern
# since there would be nothing in /home but any BindPaths= wanted by the user.
ProtectHome = "read-only";
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "strict";
RemoveIPC = true;
# AF_UNIX may become usable one day:
# https://github.com/transmission/transmission/issues/441
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallFilter = [
"@system-service"
# Groups in @system-service which do not contain a syscall
# listed by perf stat -e 'syscalls:sys_enter_*' transmission-daemon -f
# in tests, and seem likely not necessary for transmission-daemon.
"~@aio" "~@chown" "~@keyring" "~@memlock" "~@resources" "~@setuid" "~@timer"
# In the @privileged group, but reached when querying infos through RPC (eg. with stig).
"quotactl"
];
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
};
};
# It's useful to have transmission in path, e.g. for remote control
@ -133,70 +285,153 @@ in
users.users = optionalAttrs (cfg.user == "transmission") ({
transmission = {
name = "transmission";
group = cfg.group;
uid = config.ids.uids.transmission;
description = "Transmission BitTorrent user";
home = homeDir;
createHome = true;
home = cfg.home;
};
});
users.groups = optionalAttrs (cfg.group == "transmission") ({
transmission = {
name = "transmission";
gid = config.ids.gids.transmission;
};
});
# AppArmor profile
networking.firewall = mkIf cfg.openFirewall (
if cfg.settings.peer-port-random-on-start
then
{ allowedTCPPortRanges =
[ { from = cfg.settings.peer-port-random-low;
to = cfg.settings.peer-port-random-high;
}
];
allowedUDPPortRanges =
[ { from = cfg.settings.peer-port-random-low;
to = cfg.settings.peer-port-random-high;
}
];
}
else
{ allowedTCPPorts = [ cfg.settings.peer-port ];
allowedUDPPorts = [ cfg.settings.peer-port ];
}
);
boot.kernel.sysctl = mkMerge [
# Transmission uses a single UDP socket in order to implement multiple uTP sockets,
# and thus expects large kernel buffers for the UDP socket,
# https://trac.transmissionbt.com/browser/trunk/libtransmission/tr-udp.c?rev=11956.
# at least up to the values hardcoded here:
(mkIf cfg.settings.utp-enabled {
"net.core.rmem_max" = mkDefault "4194304"; # 4MB
"net.core.wmem_max" = mkDefault "1048576"; # 1MB
})
(mkIf cfg.performanceNetParameters {
# Increase the number of available source (local) TCP and UDP ports to 49151.
# Usual default is 32768 60999, ie. 28231 ports.
# Find out your current usage with: ss -s
"net.ipv4.ip_local_port_range" = "16384 65535";
# Timeout faster generic TCP states.
# Usual default is 600.
# Find out your current usage with: watch -n 1 netstat -nptuo
"net.netfilter.nf_conntrack_generic_timeout" = 60;
# Timeout faster established but inactive connections.
# Usual default is 432000.
"net.netfilter.nf_conntrack_tcp_timeout_established" = 600;
# Clear immediately TCP states after timeout.
# Usual default is 120.
"net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 1;
# Increase the number of trackable connections.
# Usual default is 262144.
# Find out your current usage with: conntrack -C
"net.netfilter.nf_conntrack_max" = 1048576;
})
];
security.apparmor.profiles = mkIf apparmor [
(pkgs.writeText "apparmor-transmission-daemon" ''
#include <tunables/global>
include <tunables/global>
${pkgs.transmission}/bin/transmission-daemon {
#include <abstractions/base>
#include <abstractions/nameservice>
include <abstractions/base>
include <abstractions/nameservice>
${getLib pkgs.glibc}/lib/*.so mr,
${getLib pkgs.libevent}/lib/libevent*.so* mr,
${getLib pkgs.curl}/lib/libcurl*.so* mr,
${getLib pkgs.openssl}/lib/libssl*.so* mr,
${getLib pkgs.openssl}/lib/libcrypto*.so* mr,
${getLib pkgs.zlib}/lib/libz*.so* mr,
${getLib pkgs.libssh2}/lib/libssh2*.so* mr,
${getLib pkgs.systemd}/lib/libsystemd*.so* mr,
${getLib pkgs.xz}/lib/liblzma*.so* mr,
${getLib pkgs.libgcrypt}/lib/libgcrypt*.so* mr,
${getLib pkgs.libgpgerror}/lib/libgpg-error*.so* mr,
${getLib pkgs.nghttp2}/lib/libnghttp2*.so* mr,
${getLib pkgs.c-ares}/lib/libcares*.so* mr,
${getLib pkgs.libcap}/lib/libcap*.so* mr,
${getLib pkgs.attr}/lib/libattr*.so* mr,
${getLib pkgs.lz4}/lib/liblz4*.so* mr,
${getLib pkgs.libkrb5}/lib/lib*.so* mr,
${getLib pkgs.keyutils}/lib/libkeyutils*.so* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
${getLib pkgs.gcc.cc.lib}/lib/libstdc++.so.* mr,
${getLib pkgs.gcc.cc.lib}/lib/libgcc_s.so.* mr,
@{PROC}/sys/kernel/random/uuid r,
@{PROC}/sys/vm/overcommit_memory r,
${pkgs.openssl.out}/etc/** r,
${pkgs.transmission}/share/transmission/** r,
owner ${settingsDir}/** rw,
${fullSettings.download-dir}/** rw,
${optionalString fullSettings.incomplete-dir-enabled ''
${fullSettings.incomplete-dir}/** rw,
# NOTE: https://github.com/NixOS/nixpkgs/pull/93457
# will remove the need for these by fixing <abstractions/base>
r ${etc."hosts".source},
r /etc/ld-nix.so.preload,
${lib.optionalString (builtins.hasAttr "ld-nix.so.preload" etc) ''
r ${etc."ld-nix.so.preload".source},
${concatMapStrings (p: optionalString (p != "") ("mr ${p},\n"))
(splitString "\n" config.environment.etc."ld-nix.so.preload".text)}
''}
r ${etc."ssl/certs/ca-certificates.crt".source},
r ${pkgs.tzdata}/share/zoneinfo/**,
r ${pkgs.stdenv.cc.libc}/share/i18n/**,
r ${pkgs.stdenv.cc.libc}/share/locale/**,
mr ${getLib pkgs.stdenv.cc.cc}/lib/*.so*,
mr ${getLib pkgs.stdenv.cc.libc}/lib/*.so*,
mr ${getLib pkgs.attr}/lib/libattr*.so*,
mr ${getLib pkgs.c-ares}/lib/libcares*.so*,
mr ${getLib pkgs.curl}/lib/libcurl*.so*,
mr ${getLib pkgs.keyutils}/lib/libkeyutils*.so*,
mr ${getLib pkgs.libcap}/lib/libcap*.so*,
mr ${getLib pkgs.libevent}/lib/libevent*.so*,
mr ${getLib pkgs.libgcrypt}/lib/libgcrypt*.so*,
mr ${getLib pkgs.libgpgerror}/lib/libgpg-error*.so*,
mr ${getLib pkgs.libkrb5}/lib/lib*.so*,
mr ${getLib pkgs.libssh2}/lib/libssh2*.so*,
mr ${getLib pkgs.lz4}/lib/liblz4*.so*,
mr ${getLib pkgs.nghttp2}/lib/libnghttp2*.so*,
mr ${getLib pkgs.openssl}/lib/libcrypto*.so*,
mr ${getLib pkgs.openssl}/lib/libssl*.so*,
mr ${getLib pkgs.systemd}/lib/libsystemd*.so*,
mr ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so*,
mr ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so*,
mr ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so*,
mr ${getLib pkgs.xz}/lib/liblzma*.so*,
mr ${getLib pkgs.zlib}/lib/libz*.so*,
r @{PROC}/sys/kernel/random/uuid,
r @{PROC}/sys/vm/overcommit_memory,
# @{pid} is not a kernel variable yet but a regexp
#r @{PROC}/@{pid}/environ,
r @{PROC}/@{pid}/mounts,
rwk /tmp/tr_session_id_*,
r ${pkgs.openssl.out}/etc/**,
r ${config.systemd.services.transmission.environment.CURL_CA_BUNDLE},
r ${pkgs.transmission}/share/transmission/**,
owner rw ${cfg.home}/${settingsDir}/**,
rw ${cfg.settings.download-dir}/**,
${optionalString cfg.settings.incomplete-dir-enabled ''
rw ${cfg.settings.incomplete-dir}/**,
''}
profile dirs {
rw ${cfg.settings.download-dir}/**,
${optionalString cfg.settings.incomplete-dir-enabled ''
rw ${cfg.settings.incomplete-dir}/**,
''}
}
${optionalString (cfg.settings.script-torrent-done-enabled &&
cfg.settings.script-torrent-done-filename != "") ''
# Stack transmission_directories profile on top of
# any existing profile for script-torrent-done-filename
# FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
# https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
''}
# FIXME: enable customizing using https://github.com/NixOS/nixpkgs/pull/93457
# include <local/transmission-daemon>
}
'')
];
};
meta.maintainers = with lib.maintainers; [ julm ];
}

View file

@ -0,0 +1,165 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.mirakurun;
mirakurun = pkgs.mirakurun;
username = config.users.users.mirakurun.name;
groupname = config.users.users.mirakurun.group;
settingsFmt = pkgs.formats.yaml {};
in
{
options = {
services.mirakurun = {
enable = mkEnableOption mirakurun.meta.description;
port = mkOption {
type = with types; nullOr port;
default = 40772;
description = ''
Port to listen on. If null, it won't listen on any port.
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Open ports in the firewall for Mirakurun.
'';
};
serverSettings = mkOption {
type = settingsFmt.type;
default = {};
example = literalExample ''
{
highWaterMark = 25165824;
overflowTimeLimit = 30000;
};
'';
description = ''
Options for server.yml.
Documentation:
<link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/>
'';
};
tunerSettings = mkOption {
type = with types; nullOr settingsFmt.type;
default = null;
example = literalExample ''
[
{
name = "tuner-name";
types = [ "GR" "BS" "CS" "SKY" ];
dvbDevicePath = "/dev/dvb/adapterX/dvrX";
}
];
'';
description = ''
Options which are added to tuners.yml. If none is specified, it will
automatically be generated at runtime.
Documentation:
<link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/>
'';
};
channelSettings = mkOption {
type = with types; nullOr settingsFmt.type;
default = null;
example = literalExample ''
[
{
name = "channel";
types = "GR";
channel = "0";
}
];
'';
description = ''
Options which are added to channels.yml. If none is specified, it
will automatically be generated at runtime.
Documentation:
<link xlink:href="https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.md"/>
'';
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ mirakurun ];
environment.etc = {
"mirakurun/server.yml".source = settingsFmt.generate "server.yml" cfg.serverSettings;
"mirakurun/tuners.yml" = mkIf (cfg.tunerSettings != null) {
source = settingsFmt.generate "tuners.yml" cfg.tunerSettings;
mode = "0644";
user = username;
group = groupname;
};
"mirakurun/channels.yml" = mkIf (cfg.channelSettings != null) {
source = settingsFmt.generate "channels.yml" cfg.channelSettings;
mode = "0644";
user = username;
group = groupname;
};
};
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = mkIf (cfg.port != null) [ cfg.port ];
};
users.users.mirakurun = {
description = "Mirakurun user";
group = "video";
isSystemUser = true;
};
services.mirakurun.serverSettings = {
logLevel = mkDefault 2;
path = mkDefault "/var/run/mirakurun/mirakurun.sock";
port = mkIf (cfg.port != null) (mkDefault cfg.port);
};
systemd.tmpfiles.rules = [
"d '/etc/mirakurun' - ${username} ${groupname} - -"
];
systemd.services.mirakurun = {
description = mirakurun.meta.description;
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${mirakurun}/bin/mirakurun";
User = username;
Group = groupname;
RuntimeDirectory="mirakurun";
StateDirectory="mirakurun";
Nice = -10;
IOSchedulingClass = "realtime";
IOSchedulingPriority = 7;
};
environment = {
SERVER_CONFIG_PATH = "/etc/mirakurun/server.yml";
TUNERS_CONFIG_PATH = "/etc/mirakurun/tuners.yml";
CHANNELS_CONFIG_PATH = "/etc/mirakurun/channels.yml";
SERVICES_DB_PATH = "/var/lib/mirakurun/services.json";
PROGRAMS_DB_PATH = "/var/lib/mirakurun/programs.json";
NODE_ENV = "production";
};
restartTriggers = let
getconf = target: config.environment.etc."mirakurun/${target}.yml".source;
targets = [
"server"
] ++ optional (cfg.tunerSettings != null) "tuners"
++ optional (cfg.channelSettings != null) "channels";
in (map getconf targets);
};
};
}

View file

@ -73,8 +73,6 @@ in {
TTYVTDisallocate = "yes";
# Fail to start if not controlling the virtual terminal.
StandardInput = "tty-fail";
StandardOutput = "syslog";
StandardError = "syslog";
# Set up a full (custom) user session for the user, required by Cage.
PAMName = "cage";
};

View file

@ -2,7 +2,7 @@
let
inherit (lib) mkEnableOption mkForce mkIf mkMerge mkOption optionalAttrs recursiveUpdate types;
inherit (lib) mkEnableOption mkForce mkIf mkMerge mkOption optionalAttrs recursiveUpdate types maintainers;
inherit (lib) concatMapStringsSep flatten mapAttrs mapAttrs' mapAttrsToList nameValuePair concatMapStringSep;
eachSite = config.services.dokuwiki;
@ -95,7 +95,7 @@ let
aclFile = mkOption {
type = with types; nullOr str;
default = if (config.aclUse && config.acl == null) then "/var/lib/dokuwiki/${name}/users.auth.php" else null;
default = if (config.aclUse && config.acl == null) then "/var/lib/dokuwiki/${name}/acl.auth.php" else null;
description = ''
Location of the dokuwiki acl rules. Mutually exclusive with services.dokuwiki.acl
Mutually exclusive with services.dokuwiki.acl which is preferred.
@ -249,22 +249,19 @@ let
nginx = mkOption {
type = types.submodule (
recursiveUpdate
(import ../web-servers/nginx/vhost-options.nix { inherit config lib; })
{
# Enable encryption by default,
options.forceSSL.default = true;
options.enableACME.default = true;
}
(import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) {}
);
default = {forceSSL = true; enableACME = true;};
default = {};
example = {
serverAliases = [
"wiki.\${config.networking.domain}"
];
enableACME = false;
# To enable encryption and let let's encrypt take care of certificate
forceSSL = true;
enableACME = true;
};
description = ''
With this option, you can customize the nginx virtualHost which already has sensible defaults for DokuWiki.
With this option, you can customize the nginx virtualHost settings.
'';
};
};
@ -276,7 +273,7 @@ in
services.dokuwiki = mkOption {
type = types.attrsOf (types.submodule siteOpts);
default = {};
description = "Sepcification of one or more dokuwiki sites to service.";
description = "Sepcification of one or more dokuwiki sites to serve.";
};
};
@ -385,4 +382,7 @@ in
isSystemUser = true;
};
};
meta.maintainers = with maintainers; [ maintainers."1000101" ];
}

View file

@ -0,0 +1,333 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jitsi-meet;
# The configuration files are JS of format "var <<string>> = <<JSON>>;". In order to
# override only some settings, we need to extract the JSON, use jq to merge it with
# the config provided by user, and then reconstruct the file.
overrideJs =
source: varName: userCfg: appendExtra:
let
extractor = pkgs.writeText "extractor.js" ''
var fs = require("fs");
eval(fs.readFileSync(process.argv[2], 'utf8'));
process.stdout.write(JSON.stringify(eval(process.argv[3])));
'';
userJson = pkgs.writeText "user.json" (builtins.toJSON userCfg);
in (pkgs.runCommand "${varName}.js" { } ''
${pkgs.nodejs}/bin/node ${extractor} ${source} ${varName} > default.json
(
echo "var ${varName} = "
${pkgs.jq}/bin/jq -s '.[0] * .[1]' default.json ${userJson}
echo ";"
echo ${escapeShellArg appendExtra}
) > $out
'');
# Essential config - it's probably not good to have these as option default because
# types.attrs doesn't do merging. Let's merge explicitly, can still be overriden if
# user desires.
defaultCfg = {
hosts = {
domain = cfg.hostName;
muc = "conference.${cfg.hostName}";
focus = "focus.${cfg.hostName}";
};
bosh = "//${cfg.hostName}/http-bind";
};
in
{
options.services.jitsi-meet = with types; {
enable = mkEnableOption "Jitsi Meet - Secure, Simple and Scalable Video Conferences";
hostName = mkOption {
type = str;
example = "meet.example.org";
description = ''
Hostname of the Jitsi Meet instance.
'';
};
config = mkOption {
type = attrs;
default = { };
example = literalExample ''
{
enableWelcomePage = false;
defaultLang = "fi";
}
'';
description = ''
Client-side web application settings that override the defaults in <filename>config.js</filename>.
See <link xlink:href="https://github.com/jitsi/jitsi-meet/blob/master/config.js" /> for default
configuration with comments.
'';
};
extraConfig = mkOption {
type = lines;
default = "";
description = ''
Text to append to <filename>config.js</filename> web application config file.
Can be used to insert JavaScript logic to determine user's region in cascading bridges setup.
'';
};
interfaceConfig = mkOption {
type = attrs;
default = { };
example = literalExample ''
{
SHOW_JITSI_WATERMARK = false;
SHOW_WATERMARK_FOR_GUESTS = false;
}
'';
description = ''
Client-side web-app interface settings that override the defaults in <filename>interface_config.js</filename>.
See <link xlink:href="https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js" /> for
default configuration with comments.
'';
};
videobridge = {
enable = mkOption {
type = bool;
default = true;
description = ''
Whether to enable Jitsi Videobridge instance and configure it to connect to Prosody.
Additional configuration is possible with <option>services.jitsi-videobridge</option>.
'';
};
passwordFile = mkOption {
type = nullOr str;
default = null;
example = "/run/keys/videobridge";
description = ''
File containing password to the Prosody account for videobridge.
If <literal>null</literal>, a file with password will be generated automatically. Setting
this option is useful if you plan to connect additional videobridges to the XMPP server.
'';
};
};
jicofo.enable = mkOption {
type = bool;
default = true;
description = ''
Whether to enable JiCoFo instance and configure it to connect to Prosody.
Additional configuration is possible with <option>services.jicofo</option>.
'';
};
nginx.enable = mkOption {
type = bool;
default = true;
description = ''
Whether to enable nginx virtual host that will serve the javascript application and act as
a proxy for the XMPP server. Further nginx configuration can be done by adapting
<option>services.nginx.virtualHosts.&lt;hostName&gt;</option>.
When this is enabled, ACME will be used to retrieve a TLS certificate by default. To disable
this, set the <option>services.nginx.virtualHosts.&lt;hostName&gt;.enableACME</option> to
<literal>false</literal> and if appropriate do the same for
<option>services.nginx.virtualHosts.&lt;hostName&gt;.forceSSL</option>.
'';
};
prosody.enable = mkOption {
type = bool;
default = true;
description = ''
Whether to configure Prosody to relay XMPP messages between Jitsi Meet components. Turn this
off if you want to configure it manually.
'';
};
};
config = mkIf cfg.enable {
services.prosody = mkIf cfg.prosody.enable {
enable = mkDefault true;
xmppComplianceSuite = mkDefault false;
modules = {
admin_adhoc = mkDefault false;
bosh = mkDefault true;
ping = mkDefault true;
roster = mkDefault true;
saslauth = mkDefault true;
tls = mkDefault true;
};
muc = [
{
domain = "conference.${cfg.hostName}";
name = "Jitsi Meet MUC";
roomLocking = false;
roomDefaultPublicJids = true;
extraConfig = ''
storage = "memory"
'';
}
{
domain = "internal.${cfg.hostName}";
name = "Jitsi Meet Videobridge MUC";
extraConfig = ''
storage = "memory"
admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" }
'';
#-- muc_room_cache_size = 1000
}
];
extraModules = [ "pubsub" ];
extraConfig = mkAfter ''
Component "focus.${cfg.hostName}"
component_secret = os.getenv("JICOFO_COMPONENT_SECRET")
'';
virtualHosts.${cfg.hostName} = {
enabled = true;
domain = cfg.hostName;
extraConfig = ''
authentication = "anonymous"
c2s_require_encryption = false
admins = { "focus@auth.${cfg.hostName}" }
'';
ssl = {
cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
key = "/var/lib/jitsi-meet/jitsi-meet.key";
};
};
virtualHosts."auth.${cfg.hostName}" = {
enabled = true;
domain = "auth.${cfg.hostName}";
extraConfig = ''
authentication = "internal_plain"
'';
ssl = {
cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
key = "/var/lib/jitsi-meet/jitsi-meet.key";
};
};
};
systemd.services.prosody.serviceConfig = mkIf cfg.prosody.enable {
EnvironmentFile = [ "/var/lib/jitsi-meet/secrets-env" ];
SupplementaryGroups = [ "jitsi-meet" ];
};
users.groups.jitsi-meet = {};
systemd.tmpfiles.rules = [
"d '/var/lib/jitsi-meet' 0750 root jitsi-meet - -"
];
systemd.services.jitsi-meet-init-secrets = {
wantedBy = [ "multi-user.target" ];
before = [ "jicofo.service" "jitsi-videobridge2.service" ] ++ (optional cfg.prosody.enable "prosody.service");
serviceConfig = {
Type = "oneshot";
};
script = let
secrets = [ "jicofo-component-secret" "jicofo-user-secret" ] ++ (optional (cfg.videobridge.passwordFile == null) "videobridge-secret");
videobridgeSecret = if cfg.videobridge.passwordFile != null then cfg.videobridge.passwordFile else "/var/lib/jitsi-meet/videobridge-secret";
in
''
cd /var/lib/jitsi-meet
${concatMapStringsSep "\n" (s: ''
if [ ! -f ${s} ]; then
tr -dc a-zA-Z0-9 </dev/urandom | head -c 64 > ${s}
chown root:jitsi-meet ${s}
chmod 640 ${s}
fi
'') secrets}
# for easy access in prosody
echo "JICOFO_COMPONENT_SECRET=$(cat jicofo-component-secret)" > secrets-env
chown root:jitsi-meet secrets-env
chmod 640 secrets-env
''
+ optionalString cfg.prosody.enable ''
${config.services.prosody.package}/bin/prosodyctl register focus auth.${cfg.hostName} "$(cat /var/lib/jitsi-meet/jicofo-user-secret)"
${config.services.prosody.package}/bin/prosodyctl register jvb auth.${cfg.hostName} "$(cat ${videobridgeSecret})"
# generate self-signed certificates
if [ ! -f /var/lib/jitsi-meet.crt ]; then
${getBin pkgs.openssl}/bin/openssl req \
-x509 \
-newkey rsa:4096 \
-keyout /var/lib/jitsi-meet/jitsi-meet.key \
-out /var/lib/jitsi-meet/jitsi-meet.crt \
-days 36500 \
-nodes \
-subj '/CN=${cfg.hostName}/CN=auth.${cfg.hostName}'
chmod 640 /var/lib/jitsi-meet/jitsi-meet.{crt,key}
chown root:jitsi-meet /var/lib/jitsi-meet/jitsi-meet.{crt,key}
fi
'';
};
services.nginx = mkIf cfg.nginx.enable {
enable = mkDefault true;
virtualHosts.${cfg.hostName} = {
enableACME = mkDefault true;
forceSSL = mkDefault true;
root = pkgs.jitsi-meet;
extraConfig = ''
ssi on;
'';
locations."@root_path".extraConfig = ''
rewrite ^/(.*)$ / break;
'';
locations."~ ^/([^/\\?&:'\"]+)$".tryFiles = "$uri @root_path";
locations."=/http-bind" = {
proxyPass = "http://localhost:5280/http-bind";
extraConfig = ''
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
'';
};
locations."=/external_api.js" = mkDefault {
alias = "${pkgs.jitsi-meet}/libs/external_api.min.js";
};
locations."=/config.js" = mkDefault {
alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (recursiveUpdate defaultCfg cfg.config) cfg.extraConfig;
};
locations."=/interface_config.js" = mkDefault {
alias = overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig "";
};
};
};
services.jitsi-videobridge = mkIf cfg.videobridge.enable {
enable = true;
xmppConfigs."localhost" = {
userName = "jvb";
domain = "auth.${cfg.hostName}";
passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
mucJids = "jvbbrewery@internal.${cfg.hostName}";
disableCertificateVerification = true;
};
};
services.jicofo = mkIf cfg.jicofo.enable {
enable = true;
xmppHost = "localhost";
xmppDomain = cfg.hostName;
userDomain = "auth.${cfg.hostName}";
userName = "focus";
userPasswordFile = "/var/lib/jitsi-meet/jicofo-user-secret";
componentPasswordFile = "/var/lib/jitsi-meet/jicofo-component-secret";
bridgeMuc = "jvbbrewery@internal.${cfg.hostName}";
config = {
"org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED" = "true";
};
};
};
meta.maintainers = lib.teams.jitsi.members;
}

View file

@ -45,6 +45,12 @@ let
inherit (config.system) stateVersion;
in {
imports = [
( mkRemovedOptionModule [ "services" "nextcloud" "nginx" "enable" ]
"The nextcloud module dropped support for other webservers than nginx.")
];
options.services.nextcloud = {
enable = mkEnableOption "nextcloud";
hostName = mkOption {
@ -91,16 +97,6 @@ in {
'';
};
nginx.enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable nginx virtual host management.
Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
'';
};
webfinger = mkOption {
type = types.bool;
default = false;
@ -468,10 +464,18 @@ in {
script = ''
chmod og+x ${cfg.home}
ln -sf ${cfg.package}/apps ${cfg.home}/
mkdir -p ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
chown -R nextcloud:nginx ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
# create nextcloud directories.
# if the directories exist already with wrong permissions, we fix that
for dir in ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps; do
if [ ! -e $dir ]; then
install -o nextcloud -g nextcloud -d $dir
elif [ $(stat -c "%G" $dir) != "nextcloud" ]; then
chgrp -R nextcloud $dir
fi
done
ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
# Do not install if already installed
if [[ ! -e ${cfg.home}/config/config.php ]]; then
@ -484,6 +488,7 @@ in {
${occSetTrustedDomainsCmd}
'';
serviceConfig.Type = "oneshot";
serviceConfig.User = "nextcloud";
};
nextcloud-cron = {
environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
@ -502,7 +507,7 @@ in {
services.phpfpm = {
pools.nextcloud = {
user = "nextcloud";
group = "nginx";
group = "nextcloud";
phpOptions = phpOptionsStr;
phpPackage = phpPackage;
phpEnv = {
@ -510,128 +515,123 @@ in {
PATH = "/run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin";
};
settings = mapAttrs (name: mkDefault) {
"listen.owner" = "nginx";
"listen.group" = "nginx";
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
} // cfg.poolSettings;
extraConfig = cfg.poolConfig;
};
};
users.extraUsers.nextcloud = {
users.users.nextcloud = {
home = "${cfg.home}";
group = "nginx";
group = "nextcloud";
createHome = true;
};
users.groups.nextcloud.members = [ "nextcloud" config.services.nginx.user ];
environment.systemPackages = [ occ ];
}
(mkIf cfg.nginx.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.hostName} = {
root = cfg.package;
locations = {
"= /robots.txt" = {
priority = 100;
extraConfig = ''
allow all;
log_not_found off;
access_log off;
'';
};
"/" = {
priority = 200;
extraConfig = "rewrite ^ /index.php;";
};
"~ ^/store-apps" = {
priority = 201;
extraConfig = "root ${cfg.home};";
};
"= /.well-known/carddav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"= /.well-known/caldav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"~ ^\\/(?:build|tests|config|lib|3rdparty|templates|data)\\/" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^\\/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^\\/(?:index|remote|public|cron|core/ajax\\/update|status|ocs\\/v[12]|updater\\/.+|ocs-provider\\/.+|ocm-provider\\/.+)\\.php(?:$|\\/)" = {
priority = 500;
extraConfig = ''
include ${config.services.nginx.package}/conf/fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(\\/.*)$;
try_files $fastcgi_script_name =404;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass unix:${fpm.socket};
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_read_timeout 120s;
'';
};
"~ ^\\/(?:updater|ocs-provider|ocm-provider)(?:$|\\/)".extraConfig = ''
try_files $uri/ =404;
index index.php;
'';
"~ \\.(?:css|js|woff2?|svg|gif)$".extraConfig = ''
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
access_log off;
'';
"~ \\.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$".extraConfig = ''
try_files $uri /index.php$request_uri;
access_log off;
'';
};
services.nginx.enable = mkDefault true;
services.nginx.virtualHosts.${cfg.hostName} = {
root = cfg.package;
locations = {
"= /robots.txt" = {
priority = 100;
extraConfig = ''
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
client_max_body_size ${cfg.maxUploadSize};
fastcgi_buffers 64 4K;
fastcgi_hide_header X-Powered-By;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
${optionalString cfg.webfinger ''
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
''}
allow all;
log_not_found off;
access_log off;
'';
};
"/" = {
priority = 200;
extraConfig = "rewrite ^ /index.php;";
};
"~ ^/store-apps" = {
priority = 201;
extraConfig = "root ${cfg.home};";
};
"= /.well-known/carddav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"= /.well-known/caldav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"~ ^\\/(?:build|tests|config|lib|3rdparty|templates|data)\\/" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^\\/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^\\/(?:index|remote|public|cron|core/ajax\\/update|status|ocs\\/v[12]|updater\\/.+|ocs-provider\\/.+|ocm-provider\\/.+)\\.php(?:$|\\/)" = {
priority = 500;
extraConfig = ''
include ${config.services.nginx.package}/conf/fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(\\/.*)$;
try_files $fastcgi_script_name =404;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass unix:${fpm.socket};
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_read_timeout 120s;
'';
};
"~ ^\\/(?:updater|ocs-provider|ocm-provider)(?:$|\\/)".extraConfig = ''
try_files $uri/ =404;
index index.php;
'';
"~ \\.(?:css|js|woff2?|svg|gif)$".extraConfig = ''
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
access_log off;
'';
"~ \\.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$".extraConfig = ''
try_files $uri /index.php$request_uri;
access_log off;
'';
};
extraConfig = ''
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
client_max_body_size ${cfg.maxUploadSize};
fastcgi_buffers 64 4K;
fastcgi_hide_header X-Powered-By;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
${optionalString cfg.webfinger ''
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
''}
'';
};
})
}
]);
meta.doc = ./nextcloud.xml;

View file

@ -29,7 +29,6 @@
services.nextcloud = {
<link linkend="opt-services.nextcloud.enable">enable</link> = true;
<link linkend="opt-services.nextcloud.hostName">hostName</link> = "nextcloud.tld";
<link linkend="opt-services.nextcloud.nginx.enable">nginx.enable</link> = true;
config = {
<link linkend="opt-services.nextcloud.config.dbtype">dbtype</link> = "pgsql";
<link linkend="opt-services.nextcloud.config.dbuser">dbuser</link> = "nextcloud";
@ -61,9 +60,8 @@
</para>
<para>
The options <literal>hostName</literal> and <literal>nginx.enable</literal>
are used internally to configure an HTTP server using
<literal><link xlink:href="https://php-fpm.org/">PHP-FPM</link></literal>
The <literal>hostName</literal> option is 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 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.

View file

@ -33,7 +33,7 @@ in
description = "
Which hostname to set the vHost to that is proxying to sks.
";
};
};
hkpAddress = mkOption {
default = builtins.head sksCfg.hkpAddress;

View file

@ -83,7 +83,7 @@ in
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
config = lib.mkIf cfg.enable (lib.mkMerge [
{
meta.maintainers = with lib.maintainers; [ kampka ];

View file

@ -632,8 +632,6 @@ let
User = "${cfg.user}";
Group = "tt_rss";
ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon --quiet";
StandardOutput = "syslog";
StandardError = "syslog";
Restart = "on-failure";
RestartSec = "60";
SyslogIdentifier = "tt-rss";

View file

@ -28,11 +28,11 @@ stop()
if test "\$1" = start
then
trap stop 15
start
elif test "\$1" = stop
then
stop
stop
elif test "\$1" = init
then
echo "Are you sure you want to create a new server instance (old server instance will be lost!)?"
@ -42,21 +42,21 @@ then
then
exit 1
fi
rm -rf $serverDir
mkdir -p $serverDir
cd $serverDir
cp -av $jboss/server/default .
sed -i -e "s|deploy/|$deployDir|" default/conf/jboss-service.xml
if ! test "$useJK" = ""
then
sed -i -e 's|<attribute name="UseJK">false</attribute>|<attribute name="UseJK">true</attribute>|' default/deploy/jboss-web.deployer/META-INF/jboss-service.xml
sed -i -e 's|<Engine name="jboss.web" defaultHost="localhost">|<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1">|' default/deploy/jboss-web.deployer/server.xml
fi
# Make files accessible for the server user
chown -R $user $serverDir
for i in \`find $serverDir -type d\`
do

View file

@ -704,7 +704,10 @@ in
'';
serviceConfig = {
ExecStart = execCommand;
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
ExecReload = [
"${execCommand} -t"
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
];
Restart = "always";
RestartSec = "10s";
StartLimitInterval = "1min";
@ -761,8 +764,7 @@ in
serviceConfig.TimeoutSec = 60;
script = ''
if /run/current-system/systemd/bin/systemctl -q is-active nginx.service ; then
${execCommand} -t && \
/run/current-system/systemd/bin/systemctl reload nginx.service
/run/current-system/systemd/bin/systemctl reload nginx.service
fi
'';
serviceConfig.RemainAfterExit = true;

View file

@ -51,7 +51,7 @@ in
Whether or not to enable SSL (https) support.
'';
};
certDirectory = mkOption {
type = types.nullOr types.path;
default = null;

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