forked from mirrors/nixpkgs
Merge branch 'staging' into upstream-wasm-cross-nixpkgs-4
This commit is contained in:
commit
818d24c9db
|
@ -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
5
.github/CODEOWNERS
vendored
|
@ -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
|
||||
|
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
|
@ -1,6 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
24
.github/workflows/editorconfig.yml
vendored
24
.github/workflows/editorconfig.yml
vendored
|
@ -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 }}
|
31
.github/workflows/wait-ofborg.yml
vendored
31
.github/workflows/wait-ofborg.yml
vendored
|
@ -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
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 Intel’s 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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -38,7 +38,7 @@ let
|
|||
|
||||
"js-ghcjs"
|
||||
|
||||
"aarch64-genode" "x86_64-genode"
|
||||
"aarch64-genode" "i686-genode" "x86_64-genode"
|
||||
];
|
||||
|
||||
allParsed = map parse.mkSystemFromString all;
|
||||
|
|
|
@ -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" ];
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -79,5 +79,4 @@ say,,,,,
|
|||
std__debug,std._debug,,,,
|
||||
std_normalize,std.normalize,,,,
|
||||
stdlib,,,,,vyp
|
||||
pulseaudio,,,,,doronbehar
|
||||
vstruct,,,,,
|
||||
|
|
|
|
@ -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
|
||||
|
|
|
@ -100,6 +100,35 @@ ROCR_EXT_DIR=`nix-build '<nixpkgs>' --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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
azure
|
||||
azure
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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"
|
||||
];
|
||||
};
|
||||
|
||||
|
|
|
@ -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 can’t 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
|
||||
''}
|
||||
'';
|
||||
|
||||
|
|
|
@ -25,4 +25,4 @@ in
|
|||
services.udev.packages = [ pkgs.libbladeRF ];
|
||||
users.groups.bladerf = {};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 ];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
with lib;
|
||||
|
||||
let
|
||||
let
|
||||
cfg = config.i18n.inputMethod.uim;
|
||||
in
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -80,4 +80,4 @@ in {
|
|||
];
|
||||
})
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}]
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = ''
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -60,4 +60,4 @@ in
|
|||
};
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,4 +93,4 @@ in
|
|||
};
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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}";
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ in
|
|||
Name of the Erlang node.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
anonymousUserCreation = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
|
190
nixos/modules/services/development/jupyterhub/default.nix
Normal file
190
nixos/modules/services/development/jupyterhub/default.nix
Normal 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}";
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ in {
|
|||
meta = {
|
||||
doc = ./trezord.xml;
|
||||
};
|
||||
|
||||
|
||||
### interface
|
||||
|
||||
options = {
|
||||
|
@ -40,7 +40,7 @@ in {
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
|
|
@ -53,4 +53,4 @@ with lib;
|
|||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"} \
|
||||
|
|
|
@ -675,7 +675,7 @@ in {
|
|||
}
|
||||
];
|
||||
|
||||
users.users.matrix-synapse = {
|
||||
users.users.matrix-synapse = {
|
||||
group = "matrix-synapse";
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
|
|
78
nixos/modules/services/misc/pinnwand.nix
Normal file
78
nixos/modules/services/misc/pinnwand.nix
Normal 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";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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.
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,7 +15,7 @@ in
|
|||
options = {
|
||||
|
||||
services.teamviewer.enable = mkEnableOption "TeamViewer daemon";
|
||||
|
||||
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
|
|
@ -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 ];
|
||||
};
|
||||
|
|
|
@ -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 ];
|
||||
};
|
||||
|
|
|
@ -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 ];
|
||||
};
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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: (
|
||||
|
|
|
@ -269,4 +269,7 @@ in
|
|||
users.groups = mapAttrs' (instanceName: cfg: (
|
||||
nameValuePair "${cfg.group}" { })) eachBlockbook;
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ maintainers."1000101" ];
|
||||
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ in {
|
|||
NotifyAccess = "main";
|
||||
ExecStart = "${getBin cfg.package}/bin/corerad -c=${cfg.configFile}";
|
||||
Restart = "on-failure";
|
||||
RestartKillSignal = "SIGHUP";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -56,4 +56,4 @@ config = mkIf cfg.enable {
|
|||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
152
nixos/modules/services/networking/jicofo.nix
Normal file
152
nixos/modules/services/networking/jicofo.nix
Normal 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;
|
||||
}
|
276
nixos/modules/services/networking/jitsi-videobridge.nix
Normal file
276
nixos/modules/services/networking/jitsi-videobridge.nix
Normal 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;
|
||||
}
|
|
@ -5,7 +5,7 @@ in
|
|||
with lib;
|
||||
{
|
||||
options.services.mstpd = {
|
||||
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
|
|
44
nixos/modules/services/networking/nextdns.nix
Normal file
44
nixos/modules/services/networking/nextdns.nix
Normal 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" ];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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 = {
|
||||
|
|
|
@ -23,7 +23,7 @@ in {
|
|||
### Documentation
|
||||
# meta.doc = ./onedrive.xml;
|
||||
|
||||
### Interface
|
||||
### Interface
|
||||
|
||||
options.services.onedrive = {
|
||||
enable = lib.mkOption {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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.";
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
|
@ -106,7 +106,9 @@ in
|
|||
Restart = "always";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ maintainers."1000101" ];
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -234,7 +234,6 @@ in
|
|||
ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
|
||||
NotifyAccess = "main";
|
||||
KillSignal = "SIGQUIT";
|
||||
StandardError = "syslog";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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.")
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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} \
|
||||
|
|
|
@ -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 ];
|
||||
}
|
||||
|
|
165
nixos/modules/services/video/mirakurun.nix
Normal file
165
nixos/modules/services/video/mirakurun.nix
Normal 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);
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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" ];
|
||||
|
||||
}
|
||||
|
|
333
nixos/modules/services/web-apps/jitsi-meet.nix
Normal file
333
nixos/modules/services/web-apps/jitsi-meet.nix
Normal 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.<hostName></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.<hostName>.enableACME</option> to
|
||||
<literal>false</literal> and if appropriate do the same for
|
||||
<option>services.nginx.virtualHosts.<hostName>.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;
|
||||
}
|
|
@ -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.<name></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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ];
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue