Merge branch 'master' into static-fixes
This commit is contained in:
commit
0505c5125c
8
.github/CODEOWNERS
vendored
8
.github/CODEOWNERS
vendored
@ -47,6 +47,9 @@
|
||||
/nixos/doc/manual/man-nixos-option.xml @nbp
|
||||
/nixos/modules/installer/tools/nixos-option.sh @nbp
|
||||
|
||||
# NixOS integration test driver
|
||||
/nixos/lib/test-driver @tfc
|
||||
|
||||
# New NixOS modules
|
||||
/nixos/modules/module-list.nix @Infinisil
|
||||
|
||||
@ -167,3 +170,8 @@
|
||||
/nixos/modules/services/monitoring/prometheus/exporters.nix @WilliButz
|
||||
/nixos/modules/services/monitoring/prometheus/exporters.xml @WilliButz
|
||||
/nixos/tests/prometheus-exporters.nix @WilliButz
|
||||
|
||||
# PHP
|
||||
/pkgs/development/interpreters/php @etu
|
||||
/pkgs/top-level/php-packages.nix @etu
|
||||
/pkgs/build-support/build-pecl.nix @etu
|
||||
|
32
.github/stale.yml
vendored
Normal file
32
.github/stale.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: false
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- 1.severity: security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: 2.status: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Thank you for your contributions.
|
||||
|
||||
This has been automatically marked as stale because it has had no
|
||||
activity for 180 days.
|
||||
|
||||
If this is still important to you, we ask that you leave a
|
||||
comment below. Your comment can be as simple as "still important
|
||||
to me". This lets people see that at least one person still cares
|
||||
about this. Someone will have to do this at most twice a year if
|
||||
there is no other activity.
|
||||
|
||||
Here are suggestions that might help resolve this more quickly:
|
||||
|
||||
1. Search for maintainers and people that previously touched the
|
||||
related code and @ mention them in a comment.
|
||||
2. Ask on the [NixOS Discourse](https://discourse.nixos.org/).
|
||||
3. Ask on the [#nixos channel](irc://irc.freenode.net/#nixos) on
|
||||
[irc.freenode.net](https://freenode.net).
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
@ -228,6 +228,33 @@ Additional information.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="submitting-changes-submitting-security-fixes">
|
||||
<title>Submitting security fixes</title>
|
||||
|
||||
<para>
|
||||
Security fixes are submitted in the same way as other changes and thus the same guidelines apply.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the security fix comes in the form of a patch and a CVE is available, then the name of the patch should be the CVE identifier, so e.g. <literal>CVE-2019-13636.patch</literal> in the case of a patch that is included in the Nixpkgs tree. If a patch is fetched the name needs to be set as well, e.g.:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
(fetchpatch {
|
||||
name = "CVE-2019-11068.patch";
|
||||
url = "https://gitlab.gnome.org/GNOME/libxslt/commit/e03553605b45c88f0b4b2980adfbbb8f6fca2fd6.patch";
|
||||
sha256 = "0pkpb4837km15zgg6h57bncp66d5lwrlvkr73h0lanywq7zrwhj8";
|
||||
})
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
If a security fix applies to both master and a stable release then, similar to regular changes, they are preferably delivered via master first and cherry-picked to the release branch.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Critical security fixes may by-pass the staging branches and be delivered directly to release branches such as <literal>master</literal> and <literal>release-*</literal>.
|
||||
</para>
|
||||
</section>
|
||||
<section xml:id="submitting-changes-pull-request-template">
|
||||
<title>Pull Request Template</title>
|
||||
|
||||
@ -298,12 +325,17 @@ Additional information.
|
||||
|
||||
<para>
|
||||
review changes from pull request number 12345:
|
||||
<screen>nix-shell -p nix-review --run "nix-review pr 12345"</screen>
|
||||
<screen>nix run nixpkgs.nix-review -c nix-review pr 12345</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
review uncommitted changes:
|
||||
<screen>nix-shell -p nix-review --run "nix-review wip"</screen>
|
||||
<screen>nix run nixpkgs.nix-review -c nix-review wip</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
review changes from last commit:
|
||||
<screen>nix run nixpkgs.nix-review -c nix-review rev HEAD</screen>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -409,7 +441,7 @@ Additional information.
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
If you're cherry-picking a commit to a stable release branch, always use <command>git cherry-pick -xe</command> and ensure the message contains a clear description about why this needs to be included in the stable branch.
|
||||
If you're cherry-picking a commit to a stable release branch (“backporting”), always use <command>git cherry-pick -xe</command> and ensure the message contains a clear description about why this needs to be included in the stable branch.
|
||||
</para>
|
||||
<para>
|
||||
An example of a cherry-picked commit would look like this:
|
||||
|
@ -26,7 +26,7 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>packages</literal>: a set of package sets, each compiled with a specific Erlang/OTP version, e.g. <literal>beam.packages.erlangR19</literal>.
|
||||
<literal>packages</literal>: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. <literal>beam.packages.erlangR19</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@ -36,15 +36,11 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To create a package set built with a custom Erlang version, use the lambda, <literal>beam.packagesWith</literal>, which accepts an Erlang/OTP derivation and produces a package set similar to <literal>beam.packages.erlang</literal>.
|
||||
To create a package builder built with a custom Erlang version, use the lambda, <literal>beam.packagesWith</literal>, which accepts an Erlang/OTP derivation and produces a package builder similar to <literal>beam.packages.erlang</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Many Erlang/OTP distributions available in <literal>beam.interpreters</literal> have versions with ODBC and/or Java enabled. For example, there's <literal>beam.interpreters.erlangR19_odbc_javac</literal>, which corresponds to <literal>beam.interpreters.erlangR19</literal>.
|
||||
</para>
|
||||
|
||||
<para xml:id="erlang-call-package">
|
||||
We also provide the lambda, <literal>beam.packages.erlang.callPackage</literal>, which simplifies writing BEAM package definitions by injecting all packages from <literal>beam.packages.erlang</literal> into the top-level context.
|
||||
Many Erlang/OTP distributions available in <literal>beam.interpreters</literal> have versions with ODBC and/or Java enabled or without wx (no observer support). For example, there's <literal>beam.interpreters.erlangR22_odbc_javac</literal>, which corresponds to <literal>beam.interpreters.erlangR22</literal> and <literal>beam.interpreters.erlangR22_nox</literal>, which corresponds to <literal>beam.interpreters.erlangR22</literal>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -55,7 +51,7 @@
|
||||
<title>Rebar3</title>
|
||||
|
||||
<para>
|
||||
We provide a version of Rebar3, which is the normal, unmodified Rebar3, under <literal>rebar3</literal>. We also provide a helper to fetch Rebar3 dependencies from a lockfile under <literal>fetchRebar3Deps</literal>.
|
||||
We provide a version of Rebar3, under <literal>rebar3</literal>. We also provide a helper to fetch Rebar3 dependencies from a lockfile under <literal>fetchRebar3Deps</literal>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@ -72,32 +68,14 @@
|
||||
<title>How to Install BEAM Packages</title>
|
||||
|
||||
<para>
|
||||
BEAM packages are not registered at the top level, simply because they are not relevant to the vast majority of Nix users. They are installable using the <literal>beam.packages.erlang</literal> attribute set (aliased as <literal>beamPackages</literal>), which points to packages built by the default Erlang/OTP version in Nixpkgs, as defined by <literal>beam.interpreters.erlang</literal>. To list the available packages in <literal>beamPackages</literal>, use the following command:
|
||||
BEAM builders are not registered at the top level, simply because they are not relevant to the vast majority of Nix users.
|
||||
To install any of those builders into your profile, refer to them by their attribute path <literal>beamPackages.rebar3</literal>:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
<prompt>$ </prompt>nix-env -f "<nixpkgs>" -qaP -A beamPackages
|
||||
beamPackages.esqlite esqlite-0.2.1
|
||||
beamPackages.goldrush goldrush-0.1.7
|
||||
beamPackages.ibrowse ibrowse-4.2.2
|
||||
beamPackages.jiffy jiffy-0.14.5
|
||||
beamPackages.lager lager-3.0.2
|
||||
beamPackages.meck meck-0.8.3
|
||||
beamPackages.rebar3-pc pc-1.1.0
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
To install any of those packages into your profile, refer to them by their attribute path (first column):
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
<prompt>$ </prompt>nix-env -f "<nixpkgs>" -iA beamPackages.ibrowse
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
The attribute path of any BEAM package corresponds to the name of that particular package in <link xlink:href="https://hex.pm">Hex</link> or its OTP Application/Release name.
|
||||
</para>
|
||||
</section>
|
||||
<screen>
|
||||
<prompt>$ </prompt>nix-env -f "<nixpkgs>" -iA beamPackages.rebar3
|
||||
</screen>
|
||||
</section>
|
||||
|
||||
<section xml:id="packaging-beam-applications">
|
||||
<title>Packaging BEAM Applications</title>
|
||||
@ -109,35 +87,7 @@ beamPackages.rebar3-pc pc-1.1.0
|
||||
<title>Rebar3 Packages</title>
|
||||
|
||||
<para>
|
||||
The Nix function, <literal>buildRebar3</literal>, defined in <literal>beam.packages.erlang.buildRebar3</literal> and aliased at the top level, can be used to build a derivation that understands how to build a Rebar3 project. For example, we can build <link
|
||||
xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link> as follows:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
{ stdenv, fetchFromGitHub, buildRebar3, ibrowse, jsx, erlware_commons }:
|
||||
|
||||
buildRebar3 rec {
|
||||
name = "hex2nix";
|
||||
version = "0.0.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ericbmerritt";
|
||||
repo = "hex2nix";
|
||||
rev = "${version}";
|
||||
sha256 = "1w7xjidz1l5yjmhlplfx7kphmnpvqm67w99hd2m7kdixwdxq0zqg";
|
||||
};
|
||||
|
||||
beamDeps = [ ibrowse jsx erlware_commons ];
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Such derivations are callable with <literal>beam.packages.erlang.callPackage</literal> (see <xref
|
||||
linkend="erlang-call-package"/>). To call this package using the normal <literal>callPackage</literal>, refer to dependency packages via <literal>beamPackages</literal>, e.g. <literal>beamPackages.ibrowse</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Notably, <literal>buildRebar3</literal> includes <literal>beamDeps</literal>, while <literal>stdenv.mkDerivation</literal> does not. BEAM dependencies added there will be correctly handled by the system.
|
||||
The Nix function, <literal>buildRebar3</literal>, defined in <literal>beam.packages.erlang.buildRebar3</literal> and aliased at the top level, can be used to build a derivation that understands how to build a Rebar3 project.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -152,30 +102,6 @@ buildRebar3 rec {
|
||||
Erlang.mk functions similarly to Rebar3, except we use <literal>buildErlangMk</literal> instead of <literal>buildRebar3</literal>.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
{ buildErlangMk, fetchHex, cowlib, ranch }:
|
||||
|
||||
buildErlangMk {
|
||||
name = "cowboy";
|
||||
version = "1.0.4";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "cowboy";
|
||||
version = "1.0.4";
|
||||
sha256 = "6a0edee96885fae3a8dd0ac1f333538a42e807db638a9453064ccfdaa6b9fdac";
|
||||
};
|
||||
|
||||
beamDeps = [ cowlib ranch ];
|
||||
|
||||
meta = {
|
||||
description = ''
|
||||
Small, fast, modular HTTP server written in Erlang
|
||||
'';
|
||||
license = stdenv.lib.licenses.isc;
|
||||
homepage = https://github.com/ninenines/cowboy;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="mix-packages">
|
||||
@ -185,57 +111,9 @@ buildErlangMk {
|
||||
Mix functions similarly to Rebar3, except we use <literal>buildMix</literal> instead of <literal>buildRebar3</literal>.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
{ buildMix, fetchHex, plug, absinthe }:
|
||||
|
||||
buildMix {
|
||||
name = "absinthe_plug";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchHex {
|
||||
pkg = "absinthe_plug";
|
||||
version = "1.0.0";
|
||||
sha256 = "08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33";
|
||||
};
|
||||
|
||||
beamDeps = [ plug absinthe ];
|
||||
|
||||
meta = {
|
||||
description = ''
|
||||
A plug for Absinthe, an experimental GraphQL toolkit
|
||||
'';
|
||||
license = stdenv.lib.licenses.bsd3;
|
||||
homepage = https://github.com/CargoSense/absinthe_plug;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Alternatively, we can use <literal>buildHex</literal> as a shortcut:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
{ buildHex, buildMix, plug, absinthe }:
|
||||
|
||||
buildHex {
|
||||
name = "absinthe_plug";
|
||||
version = "1.0.0";
|
||||
|
||||
sha256 = "08459823fe1fd4f0325a8bf0c937a4520583a5a26d73b193040ab30a1dfc0b33";
|
||||
|
||||
builder = buildMix;
|
||||
|
||||
beamDeps = [ plug absinthe ];
|
||||
|
||||
meta = {
|
||||
description = ''
|
||||
A plug for Absinthe, an experimental GraphQL toolkit
|
||||
'';
|
||||
license = stdenv.lib.licenses.bsd3;
|
||||
homepage = https://github.com/CargoSense/absinthe_plug;
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
@ -243,66 +121,13 @@ buildHex {
|
||||
<section xml:id="how-to-develop">
|
||||
<title>How to Develop</title>
|
||||
|
||||
<section xml:id="accessing-an-environment">
|
||||
<title>Accessing an Environment</title>
|
||||
|
||||
<para>
|
||||
Often, we simply want to access a valid environment that contains a specific package and its dependencies. We can accomplish that with the <literal>env</literal> attribute of a derivation. For example, let's say we want to access an Erlang REPL with <literal>ibrowse</literal> loaded up. We could do the following:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
<prompt>$ </prompt><userinput>nix-shell -A beamPackages.ibrowse.env --run "erl"</userinput>
|
||||
<computeroutput>Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
|
||||
|
||||
Eshell V7.0 (abort with ^G)</computeroutput>
|
||||
<prompt>1> </prompt><userinput>m(ibrowse).</userinput>
|
||||
<computeroutput>Module: ibrowse
|
||||
MD5: 3b3e0137d0cbb28070146978a3392945
|
||||
Compiled: January 10 2016, 23:34
|
||||
Object file: /nix/store/g1rlf65rdgjs4abbyj4grp37ry7ywivj-ibrowse-4.2.2/lib/erlang/lib/ibrowse-4.2.2/ebin/ibrowse.beam
|
||||
Compiler options: [{outdir,"/tmp/nix-build-ibrowse-4.2.2.drv-0/hex-source-ibrowse-4.2.2/_build/default/lib/ibrowse/ebin"},
|
||||
debug_info,debug_info,nowarn_shadow_vars,
|
||||
warn_unused_import,warn_unused_vars,warnings_as_errors,
|
||||
{i,"/tmp/nix-build-ibrowse-4.2.2.drv-0/hex-source-ibrowse-4.2.2/_build/default/lib/ibrowse/include"}]
|
||||
Exports:
|
||||
add_config/1 send_req_direct/7
|
||||
all_trace_off/0 set_dest/3
|
||||
code_change/3 set_max_attempts/3
|
||||
get_config_value/1 set_max_pipeline_size/3
|
||||
get_config_value/2 set_max_sessions/3
|
||||
get_metrics/0 show_dest_status/0
|
||||
get_metrics/2 show_dest_status/1
|
||||
handle_call/3 show_dest_status/2
|
||||
handle_cast/2 spawn_link_worker_process/1
|
||||
handle_info/2 spawn_link_worker_process/2
|
||||
init/1 spawn_worker_process/1
|
||||
module_info/0 spawn_worker_process/2
|
||||
module_info/1 start/0
|
||||
rescan_config/0 start_link/0
|
||||
rescan_config/1 stop/0
|
||||
send_req/3 stop_worker_process/1
|
||||
send_req/4 stream_close/1
|
||||
send_req/5 stream_next/1
|
||||
send_req/6 terminate/2
|
||||
send_req_direct/4 trace_off/0
|
||||
send_req_direct/5 trace_off/2
|
||||
send_req_direct/6 trace_on/0
|
||||
trace_on/2
|
||||
ok</computeroutput>
|
||||
<prompt>2></prompt>
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
Notice the <literal>-A beamPackages.ibrowse.env</literal>. That is the key to this functionality.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="creating-a-shell">
|
||||
<title>Creating a Shell</title>
|
||||
|
||||
<para>
|
||||
Getting access to an environment often isn't enough to do real development. Usually, we need to create a <literal>shell.nix</literal> file and do our development inside of the environment specified therein. This file looks a lot like the packaging described above, except that <literal>src</literal> points to the project root and we call the package directly.
|
||||
</para>
|
||||
<para>
|
||||
Usually, we need to create a <literal>shell.nix</literal> file and do our development inside of the environment specified therein. Just install your version of erlang and other interpreter, and then user your normal build tools.
|
||||
As an example with elixir:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
{ pkgs ? import "<nixpkgs"> {} }:
|
||||
@ -311,114 +136,24 @@ with pkgs;
|
||||
|
||||
let
|
||||
|
||||
f = { buildRebar3, ibrowse, jsx, erlware_commons }:
|
||||
buildRebar3 {
|
||||
name = "hex2nix";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
beamDeps = [ ibrowse jsx erlware_commons ];
|
||||
};
|
||||
drv = beamPackages.callPackage f {};
|
||||
elixir = beam.packages.erlangR22.elixir_1_9;
|
||||
|
||||
in
|
||||
mkShell {
|
||||
buildInputs = [ elixir ];
|
||||
|
||||
drv
|
||||
ERL_INCLUDE_PATH="${erlang}/lib/erlang/usr/include";
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<section xml:id="building-in-a-shell">
|
||||
<title>Building in a Shell (for Mix Projects)</title>
|
||||
|
||||
<para>
|
||||
We can leverage the support of the derivation, irrespective of the build derivation, by calling the commands themselves.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
# =============================================================================
|
||||
# Variables
|
||||
# =============================================================================
|
||||
|
||||
NIX_TEMPLATES := "$(CURDIR)/nix-templates"
|
||||
|
||||
TARGET := "$(PREFIX)"
|
||||
|
||||
PROJECT_NAME := thorndyke
|
||||
|
||||
NIXPKGS=../nixpkgs
|
||||
NIX_PATH=nixpkgs=$(NIXPKGS)
|
||||
NIX_SHELL=nix-shell -I "$(NIX_PATH)" --pure
|
||||
# =============================================================================
|
||||
# Rules
|
||||
# =============================================================================
|
||||
.PHONY= all test clean repl shell build test analyze configure install \
|
||||
test-nix-install publish plt analyze
|
||||
|
||||
all: build
|
||||
|
||||
guard-%:
|
||||
@ if [ "${${*}}" == "" ]; then \
|
||||
echo "Environment variable $* not set"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -rf _build
|
||||
rm -rf .cache
|
||||
|
||||
repl:
|
||||
$(NIX_SHELL) --run "iex -pa './_build/prod/lib/*/ebin'"
|
||||
|
||||
shell:
|
||||
$(NIX_SHELL)
|
||||
|
||||
configure:
|
||||
$(NIX_SHELL) --command 'eval "$$configurePhase"'
|
||||
|
||||
build: configure
|
||||
$(NIX_SHELL) --command 'eval "$$buildPhase"'
|
||||
|
||||
install:
|
||||
$(NIX_SHELL) --command 'eval "$$installPhase"'
|
||||
|
||||
test:
|
||||
$(NIX_SHELL) --command 'mix test --no-start --no-deps-check'
|
||||
|
||||
plt:
|
||||
$(NIX_SHELL) --run "mix dialyzer.plt --no-deps-check"
|
||||
|
||||
analyze: build plt
|
||||
$(NIX_SHELL) --run "mix dialyzer --no-compile"
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Using a <literal>shell.nix</literal> as described (see <xref
|
||||
linkend="creating-a-shell"/>) should just work. Aside from <literal>test</literal>, <literal>plt</literal>, and <literal>analyze</literal>, the Make targets work just fine for all of the build derivations.
|
||||
linkend="creating-a-shell"/>) should just work.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section xml:id="generating-packages-from-hex-with-hex2nix">
|
||||
<title>Generating Packages from Hex with <literal>hex2nix</literal></title>
|
||||
|
||||
<para>
|
||||
Updating the <link xlink:href="https://hex.pm">Hex</link> package set requires <link
|
||||
xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link>. Given the path to the Erlang modules (usually <literal>pkgs/development/erlang-modules</literal>), it will dump a file called <literal>hex-packages.nix</literal>, containing all the packages that use a recognized build system in <link
|
||||
xlink:href="https://hex.pm">Hex</link>. It can't be determined, however, whether every package is buildable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To make life easier for our users, try to build every <link
|
||||
xlink:href="https://hex.pm">Hex</link> package and remove those that fail. To do that, simply run the following command in the root of your <literal>nixpkgs</literal> repository:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
<prompt>$ </prompt>nix-build -A beamPackages
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
That will attempt to build every package in <literal>beamPackages</literal>. Then manually remove those that fail. Hopefully, someone will improve <link
|
||||
xlink:href="https://github.com/erlang-nix/hex2nix">hex2nix</link> in the future to automate the process.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -74,7 +74,7 @@
|
||||
preFixup = ''
|
||||
for f in $(find $out/bin/ $out/libexec/ -type f -executable); do
|
||||
wrapProgram "$f" \
|
||||
--prefix GIO_EXTRA_MODULES : "${getLib gnome3.dconf}/lib/gio/modules" \
|
||||
--prefix GIO_EXTRA_MODULES : "${getLib dconf}/lib/gio/modules" \
|
||||
--prefix XDG_DATA_DIRS : "$out/share" \
|
||||
--prefix XDG_DATA_DIRS : "$out/share/gsettings-schemas/${name}" \
|
||||
--prefix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
|
||||
@ -102,7 +102,7 @@ preFixup = ''
|
||||
</listitem>
|
||||
<listitem xml:id="ssec-gnome-hooks-dconf">
|
||||
<para>
|
||||
<package>gnome3.dconf.lib</package> is a dependency of <package>wrapGAppsHook</package>, which then also adds it to the <envar>GIO_EXTRA_MODULES</envar> variable.
|
||||
<package>dconf.lib</package> is a dependency of <package>wrapGAppsHook</package>, which then also adds it to the <envar>GIO_EXTRA_MODULES</envar> variable.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem xml:id="ssec-gnome-hooks-hicolor-icon-theme">
|
||||
|
@ -25,14 +25,14 @@ avoided that by keeping all Haskell-related packages in a separate attribute
|
||||
set called `haskellPackages`, which the following command will list:
|
||||
```
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskellPackages
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.abacate haskell-abacate-0.0.0.0
|
||||
haskellPackages.abcBridge haskell-abcBridge-0.12
|
||||
haskellPackages.afv afv-0.1.1
|
||||
haskellPackages.alex alex-3.1.4
|
||||
haskellPackages.Allure Allure-0.4.101.1
|
||||
haskellPackages.alms alms-0.6.7
|
||||
[... some 8000 entries omitted ...]
|
||||
haskellPackages.a50 a50-0.5
|
||||
haskellPackages.AAI AAI-0.2.0.1
|
||||
haskellPackages.abacate abacate-0.0.0.0
|
||||
haskellPackages.abc-puzzle abc-puzzle-0.2.1
|
||||
haskellPackages.abcBridge abcBridge-0.15
|
||||
haskellPackages.abcnotation abcnotation-1.9.0
|
||||
haskellPackages.abeson abeson-0.1.0.1
|
||||
[... some 14000 entries omitted ...]
|
||||
```
|
||||
|
||||
To install any of those packages into your profile, refer to them by their
|
||||
@ -101,19 +101,21 @@ to compile your Haskell packages with any GHC version you please. The following
|
||||
command displays the complete list of available compilers:
|
||||
```
|
||||
$ nix-env -f "<nixpkgs>" -qaP -A haskell.compiler
|
||||
haskell.compiler.ghc6104 ghc-6.10.4
|
||||
haskell.compiler.ghc6123 ghc-6.12.3
|
||||
haskell.compiler.ghc704 ghc-7.0.4
|
||||
haskell.compiler.ghc722 ghc-7.2.2
|
||||
haskell.compiler.ghc742 ghc-7.4.2
|
||||
haskell.compiler.ghc763 ghc-7.6.3
|
||||
haskell.compiler.ghc784 ghc-7.8.4
|
||||
haskell.compiler.ghc7102 ghc-7.10.2
|
||||
haskell.compiler.ghcHEAD ghc-7.11.20150402
|
||||
haskell.compiler.ghcNokinds ghc-nokinds-7.11.20150704
|
||||
haskell.compiler.ghcjs ghcjs-0.1.0
|
||||
haskell.compiler.jhc jhc-0.8.2
|
||||
haskell.compiler.uhc uhc-1.1.9.0
|
||||
haskell.compiler.ghc822 ghc-8.2.2
|
||||
haskell.compiler.integer-simple.ghc822 ghc-8.2.2
|
||||
haskell.compiler.ghc822Binary ghc-8.2.2-binary
|
||||
haskell.compiler.ghc844 ghc-8.4.4
|
||||
haskell.compiler.ghc863Binary ghc-8.6.3-binary
|
||||
haskell.compiler.ghc864 ghc-8.6.4
|
||||
haskell.compiler.integer-simple.ghc864 ghc-8.6.4
|
||||
haskell.compiler.ghc865 ghc-8.6.5
|
||||
haskell.compiler.integer-simple.ghc865 ghc-8.6.5
|
||||
haskell.compiler.ghc881 ghc-8.8.1
|
||||
haskell.compiler.integer-simple.ghc881 ghc-8.8.1
|
||||
haskell.compiler.ghcHEAD ghc-8.9.20190601
|
||||
haskell.compiler.integer-simple.ghcHEAD ghc-8.9.20190601
|
||||
haskell.compiler.ghcjs84 ghcjs-8.4.0.1
|
||||
haskell.compiler.ghcjs ghcjs-8.6.0.1
|
||||
```
|
||||
|
||||
We have no package sets for `jhc` or `uhc` yet, unfortunately, but for every
|
||||
@ -398,7 +400,9 @@ nix:
|
||||
For more on how to write a `shell.nix` file see the below section. You'll need
|
||||
to express a derivation. Note that Nixpkgs ships with a convenience wrapper
|
||||
function around `mkDerivation` called `haskell.lib.buildStackProject` to help you
|
||||
create this derivation in exactly the way Stack expects. All of the same inputs
|
||||
create this derivation in exactly the way Stack expects. However for this to work
|
||||
you need to disable the sandbox, which you can do by using `--option sandbox relaxed`
|
||||
or `--option sandbox false` to the Nix command. All of the same inputs
|
||||
as `mkDerivation` can be provided. For example, to build a Stack project that
|
||||
including packages that link against a version of the R library compiled with
|
||||
special options turned on:
|
||||
|
@ -144,6 +144,24 @@ What's happening here?
|
||||
2. Then we create a Python 3.5 environment with the `withPackages` function.
|
||||
3. The `withPackages` function expects us to provide a function as an argument that takes the set of all python packages and returns a list of packages to include in the environment. Here, we select the packages `numpy` and `toolz` from the package set.
|
||||
|
||||
To combine this with `mkShell` you can:
|
||||
|
||||
```nix
|
||||
with import <nixpkgs> {};
|
||||
|
||||
let
|
||||
pythonEnv = python35.withPackages (ps: [
|
||||
ps.numpy
|
||||
ps.toolz
|
||||
]);
|
||||
in mkShell {
|
||||
buildInputs = [
|
||||
pythonEnv
|
||||
hello
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
##### Execute command with `--run`
|
||||
A convenient option with `nix-shell` is the `--run`
|
||||
option, with which you can execute a command in the `nix-shell`. We can
|
||||
|
@ -244,7 +244,7 @@
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefixed `ar`.
|
||||
Many packages assume that an unprefixed <command>ar</command> is available, but Nix doesn't provide one. It only provides a prefixed one, just as it only does for all the other binutils programs. It may be necessary to patch the package to fix the build system to use a prefixed <command>ar</command>.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
@ -1717,7 +1717,7 @@ someVar=$(stripHash $name)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency. For example, the C compiler wrapper's setup hook feeds itself flags for each dependency that contains relevant libraries and headers. This is done by defining a bash function, and appending its name to one of <envar>envBuildBuildHooks</envar>`, <envar>envBuildHostHooks</envar>`, <envar>envBuildTargetHooks</envar>`, <envar>envHostHostHooks</envar>`, <envar>envHostTargetHooks</envar>`, or <envar>envTargetTargetHooks</envar>`. These 6 bash variables correspond to the 6 sorts of dependencies by platform (there's 12 total but we ignore the propagated/non-propagated axis).
|
||||
The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency. For example, the C compiler wrapper's setup hook feeds itself flags for each dependency that contains relevant libraries and headers. This is done by defining a bash function, and appending its name to one of <envar>envBuildBuildHooks</envar>, <envar>envBuildHostHooks</envar>, <envar>envBuildTargetHooks</envar>, <envar>envHostHostHooks</envar>, <envar>envHostTargetHooks</envar>, or <envar>envTargetTargetHooks</envar>. These 6 bash variables correspond to the 6 sorts of dependencies by platform (there's 12 total but we ignore the propagated/non-propagated axis).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -141,11 +141,10 @@
|
||||
For a more useful example, try the following. This configuration only allows unfree packages named flash player and visual studio code:
|
||||
<programlisting>
|
||||
{
|
||||
allowUnfreePredicate = (pkg: builtins.elem
|
||||
(pkg.pname or (builtins.parseDrvName pkg.name).name) [
|
||||
"flashplayer"
|
||||
"vscode"
|
||||
]);
|
||||
allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
"flashplayer"
|
||||
"vscode"
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
@ -217,7 +216,7 @@
|
||||
The following configuration example only allows insecure packages with very short names:
|
||||
<programlisting>
|
||||
{
|
||||
allowInsecurePredicate = (pkg: (builtins.stringLength (builtins.parseDrvName pkg.name).name) <= 5);
|
||||
allowInsecurePredicate = pkg: builtins.stringLength (lib.getName pkg) <= 5;
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
@ -84,7 +84,8 @@ let
|
||||
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
||||
escapeShellArg escapeShellArgs replaceChars lowerChars
|
||||
upperChars toLower toUpper addContextFrom splitString
|
||||
removePrefix removeSuffix versionOlder versionAtLeast getVersion
|
||||
removePrefix removeSuffix versionOlder versionAtLeast
|
||||
getName getVersion
|
||||
nameFromURL enableFeature enableFeatureAs withFeature
|
||||
withFeatureAs fixedWidthString fixedWidthNumber isStorePath
|
||||
toInt readPathsFromFile fileContents;
|
||||
|
@ -472,6 +472,23 @@ rec {
|
||||
*/
|
||||
versionAtLeast = v1: v2: !versionOlder v1 v2;
|
||||
|
||||
/* This function takes an argument that's either a derivation or a
|
||||
derivation's "name" attribute and extracts the name part from that
|
||||
argument.
|
||||
|
||||
Example:
|
||||
getName "youtube-dl-2016.01.01"
|
||||
=> "youtube-dl"
|
||||
getName pkgs.youtube-dl
|
||||
=> "youtube-dl"
|
||||
*/
|
||||
getName = x:
|
||||
let
|
||||
parse = drv: (builtins.parseDrvName drv).name;
|
||||
in if isString x
|
||||
then parse x
|
||||
else x.pname or (parse x.name);
|
||||
|
||||
/* This function takes an argument that's either a derivation or a
|
||||
derivation's "name" attribute and extracts the version part from that
|
||||
argument.
|
||||
|
@ -37,6 +37,7 @@ rec {
|
||||
else if final.isAndroid then "bionic"
|
||||
else if final.isLinux /* default */ then "glibc"
|
||||
else if final.isMsp430 then "newlib"
|
||||
else if final.isVc4 then "newlib"
|
||||
else if final.isAvr then "avrlibc"
|
||||
else if final.isNetBSD then "nblibc"
|
||||
# TODO(@Ericson2314) think more about other operating systems
|
||||
|
@ -26,7 +26,7 @@ let
|
||||
|
||||
"riscv32-linux" "riscv64-linux"
|
||||
|
||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none"
|
||||
"aarch64-none" "avr-none" "arm-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none" "vc4-none"
|
||||
];
|
||||
|
||||
allParsed = map parse.mkSystemFromString all;
|
||||
@ -45,6 +45,7 @@ in {
|
||||
x86_64 = filterDoubles predicates.isx86_64;
|
||||
mips = filterDoubles predicates.isMips;
|
||||
riscv = filterDoubles predicates.isRiscV;
|
||||
vc4 = filterDoubles predicates.isVc4;
|
||||
|
||||
cygwin = filterDoubles predicates.isCygwin;
|
||||
darwin = filterDoubles predicates.isDarwin;
|
||||
|
@ -118,6 +118,12 @@ rec {
|
||||
config = "avr";
|
||||
};
|
||||
|
||||
vc4 = {
|
||||
config = "vc4-elf";
|
||||
libc = "newlib";
|
||||
platform = {};
|
||||
};
|
||||
|
||||
arm-embedded = {
|
||||
config = "arm-none-eabi";
|
||||
libc = "newlib";
|
||||
@ -207,7 +213,7 @@ rec {
|
||||
|
||||
# 32 bit mingw-w64
|
||||
mingw32 = {
|
||||
config = "i686-pc-mingw32";
|
||||
config = "i686-w64-mingw32";
|
||||
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
|
||||
platform = {};
|
||||
};
|
||||
@ -215,7 +221,7 @@ rec {
|
||||
# 64 bit mingw-w64
|
||||
mingwW64 = {
|
||||
# That's the triplet they use in the mingw-w64 docs.
|
||||
config = "x86_64-pc-mingw32";
|
||||
config = "x86_64-w64-mingw32";
|
||||
libc = "msvcrt"; # This distinguishes the mingw (non posix) toolchain
|
||||
platform = {};
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ rec {
|
||||
isSparc = { cpu = { family = "sparc"; }; };
|
||||
isWasm = { cpu = { family = "wasm"; }; };
|
||||
isMsp430 = { cpu = { family = "msp430"; }; };
|
||||
isVc4 = { cpu = { family = "vc4"; }; };
|
||||
isAvr = { cpu = { family = "avr"; }; };
|
||||
isAlpha = { cpu = { family = "alpha"; }; };
|
||||
isJavaScript = { cpu = cpuTypes.js; };
|
||||
|
@ -112,6 +112,8 @@ rec {
|
||||
msp430 = { bits = 16; significantByte = littleEndian; family = "msp430"; };
|
||||
avr = { bits = 8; family = "avr"; };
|
||||
|
||||
vc4 = { bits = 32; significantByte = littleEndian; family = "vc4"; };
|
||||
|
||||
js = { bits = 32; significantByte = littleEndian; family = "js"; };
|
||||
};
|
||||
|
||||
@ -208,6 +210,9 @@ rec {
|
||||
vendors = setTypes types.openVendor {
|
||||
apple = {};
|
||||
pc = {};
|
||||
# Actually matters, unlocking some MinGW-w64-specific options in GCC. See
|
||||
# bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/
|
||||
w64 = {};
|
||||
|
||||
none = {};
|
||||
unknown = {};
|
||||
|
@ -731,6 +731,16 @@
|
||||
githubId = 135230;
|
||||
name = "Aycan iRiCAN";
|
||||
};
|
||||
b4dm4n = {
|
||||
email = "fabianm88@gmail.com";
|
||||
github = "B4dM4n";
|
||||
githubId = 448169;
|
||||
name = "Fabian Möller";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x754B5C0963C42C5";
|
||||
fingerprint = "6309 E212 29D4 DA30 AF24 BDED 754B 5C09 63C4 2C50";
|
||||
}];
|
||||
};
|
||||
babariviere = {
|
||||
email = "babathriviere@gmail.com";
|
||||
github = "babariviere";
|
||||
@ -934,6 +944,12 @@
|
||||
githubId = 5718007;
|
||||
name = "Bastian Köcher";
|
||||
};
|
||||
blitz = {
|
||||
email = "js@alien8.de";
|
||||
github = "blitz";
|
||||
githubId = 37907;
|
||||
name = "Julian Stecklina";
|
||||
};
|
||||
bluescreen303 = {
|
||||
email = "mathijs@bluescreen303.nl";
|
||||
github = "bluescreen303";
|
||||
@ -1389,6 +1405,12 @@
|
||||
githubId = 1740337;
|
||||
name = "Chris Ostrouchov";
|
||||
};
|
||||
contrun = {
|
||||
email = "uuuuuu@protonmail.com";
|
||||
github = "contrun";
|
||||
githubId = 32609395;
|
||||
name = "B YI";
|
||||
};
|
||||
couchemar = {
|
||||
email = "couchemar@yandex.ru";
|
||||
github = "couchemar";
|
||||
@ -1462,6 +1484,16 @@
|
||||
}
|
||||
];
|
||||
};
|
||||
d-goldin = {
|
||||
email = "dgoldin+github@protonmail.ch";
|
||||
github = "d-goldin";
|
||||
githubId = 43349662;
|
||||
name = "Dima";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/BAB1D15FB7B4D4CE";
|
||||
fingerprint = "1C4E F4FE 7F8E D8B7 1E88 CCDF BAB1 D15F B7B4 D4CE";
|
||||
}];
|
||||
};
|
||||
dadada = {
|
||||
name = "dadada";
|
||||
email = "dadada@dadada.li";
|
||||
@ -1758,6 +1790,12 @@
|
||||
githubId = 875324;
|
||||
name = "David Johnson";
|
||||
};
|
||||
dmrauh = {
|
||||
email = "dmrauh@posteo.de";
|
||||
github = "dmrauh";
|
||||
githubId = 37698547;
|
||||
name = "Dominik Michael Rauh";
|
||||
};
|
||||
dmvianna = {
|
||||
email = "dmlvianna@gmail.com";
|
||||
github = "dmvianna";
|
||||
@ -2082,6 +2120,12 @@
|
||||
email = "mpcervin@uncg.edu";
|
||||
name = "Mabry Cervin";
|
||||
};
|
||||
equirosa = {
|
||||
email = "eduardo@eduardoquiros.com";
|
||||
github = "equirosa";
|
||||
githubId = 39096810;
|
||||
name = "Eduardo Quiros";
|
||||
};
|
||||
eqyiel = {
|
||||
email = "ruben@maher.fyi";
|
||||
github = "eqyiel";
|
||||
@ -2279,6 +2323,16 @@
|
||||
githubId = 415760;
|
||||
name = "Jonas Höglund";
|
||||
};
|
||||
Flakebi = {
|
||||
email = "flakebi@t-online.de";
|
||||
github = "Flakebi";
|
||||
githubId = "Flakebi";
|
||||
name = "Sebastian Neubauer";
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0xECC755EE583C1672";
|
||||
fingerprint = "2F93 661D AC17 EA98 A104 F780 ECC7 55EE 583C 1672";
|
||||
}];
|
||||
};
|
||||
flexw = {
|
||||
email = "felix.weilbach@t-online.de";
|
||||
github = "FlexW";
|
||||
@ -2477,6 +2531,7 @@
|
||||
gazally = {
|
||||
email = "gazally@runbox.com";
|
||||
github = "gazally";
|
||||
githubId = 16470252;
|
||||
name = "Gemini Lasswell";
|
||||
};
|
||||
gebner = {
|
||||
@ -2621,6 +2676,12 @@
|
||||
githubId = 9705357;
|
||||
name = "Guillaume Bouchard";
|
||||
};
|
||||
GuillaumeDesforges = {
|
||||
email = "aceus02@gmail.com";
|
||||
github = "GuillaumeDesforges";
|
||||
githubId = 1882000;
|
||||
name = "Guillaume Desforges";
|
||||
};
|
||||
guillaumekoenig = {
|
||||
email = "guillaume.edward.koenig@gmail.com";
|
||||
github = "guillaumekoenig";
|
||||
@ -2884,6 +2945,15 @@
|
||||
githubId = 137306;
|
||||
name = "Michele Catalano";
|
||||
};
|
||||
isgy = {
|
||||
email = "isgy@teiyg.com";
|
||||
github = "isgy";
|
||||
githubId = 13622947;
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0xD3E1B013B4631293";
|
||||
fingerprint = "1412 816B A9FA F62F D051 1975 D3E1 B013 B463 1293";
|
||||
}];
|
||||
};
|
||||
ivan = {
|
||||
email = "ivan@ludios.org";
|
||||
github = "ivan";
|
||||
@ -3355,6 +3425,12 @@
|
||||
github = "juliendehos";
|
||||
name = "Julien Dehos";
|
||||
};
|
||||
jumper149 = {
|
||||
email = "felixspringer149@gmail.com";
|
||||
github = "jumper149";
|
||||
githubId = 39434424;
|
||||
name = "Felix Springer";
|
||||
};
|
||||
justinwoo = {
|
||||
email = "moomoowoo@gmail.com";
|
||||
github = "justinwoo";
|
||||
@ -3535,6 +3611,12 @@
|
||||
github = "klntsky";
|
||||
githubId = 18447310;
|
||||
};
|
||||
kmcopper = {
|
||||
email = "kmcopper@danwin1210.me";
|
||||
name = "Kyle Copperfield";
|
||||
github = "kmcopper";
|
||||
githubId = 57132115;
|
||||
};
|
||||
kmeakin = {
|
||||
email = "karlwfmeakin@gmail.com";
|
||||
name = "Karl Meakin";
|
||||
@ -3641,6 +3723,18 @@
|
||||
githubId = 449813;
|
||||
name = "Roman Kuznetsov";
|
||||
};
|
||||
kylesferrazza = {
|
||||
name = "Kyle Sferrazza";
|
||||
email = "kyle.sferrazza@gmail.com";
|
||||
|
||||
github = "kylesferrazza";
|
||||
githubId = 6677292;
|
||||
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/81A1540948162372";
|
||||
fingerprint = "5A9A 1C9B 2369 8049 3B48 CF5B 81A1 5409 4816 2372";
|
||||
}];
|
||||
};
|
||||
kylewlacy = {
|
||||
email = "kylelacy+nix@pm.me";
|
||||
github = "kylewlacy";
|
||||
@ -3891,6 +3985,22 @@
|
||||
github = "lovek323";
|
||||
name = "Jason O'Conal";
|
||||
};
|
||||
lovesegfault = {
|
||||
email = "meurerbernardo@gmail.com";
|
||||
github = "lovesegfault";
|
||||
githubId = 7243783;
|
||||
name = "Bernardo Meurer";
|
||||
keys = [
|
||||
{
|
||||
longkeyid = "rsa2048/0xE421C74191EA186C";
|
||||
fingerprint = "5894 12CE 19DF 582A E10A 3320 E421 C741 91EA 186C";
|
||||
}
|
||||
{
|
||||
longkeyid = "rsa2048/0x4A6D87A0E7475769";
|
||||
fingerprint = "56A8 E164 E834 290C 4AC0 EE3E 4A6D 87A0 E747 5769";
|
||||
}
|
||||
];
|
||||
};
|
||||
lowfatcomputing = {
|
||||
email = "andreas.wagner@lowfatcomputing.org";
|
||||
github = "lowfatcomputing";
|
||||
@ -4052,6 +4162,12 @@
|
||||
github = "marcweber";
|
||||
githubId = 34086;
|
||||
name = "Marc Weber";
|
||||
};
|
||||
marcus7070 = {
|
||||
email = "marcus@geosol.com.au";
|
||||
github = "marcus7070";
|
||||
githubId = 50230945;
|
||||
name = "Marcus Boyd";
|
||||
};
|
||||
marenz = {
|
||||
email = "marenz@arkom.men";
|
||||
@ -4391,6 +4507,12 @@
|
||||
githubId = 16974598;
|
||||
name = "Mike Playle";
|
||||
};
|
||||
mkaito = {
|
||||
email = "chris@mkaito.net";
|
||||
github = "mkaito";
|
||||
githubId = 20434;
|
||||
name = "Christian Höppner";
|
||||
};
|
||||
mkazulak = {
|
||||
email = "kazulakm@gmail.com";
|
||||
github = "mulderr";
|
||||
@ -4430,6 +4552,12 @@
|
||||
githubId = 117842;
|
||||
name = "Henri Bourcereau";
|
||||
};
|
||||
mmilata = {
|
||||
email = "martin@martinmilata.cz";
|
||||
github = "mmilata";
|
||||
gitHubId = 85857;
|
||||
name = "Martin Milata";
|
||||
};
|
||||
mmlb = {
|
||||
email = "me.mmlb@mmlb.me";
|
||||
github = "mmlb";
|
||||
@ -4487,6 +4615,10 @@
|
||||
github = "moredread";
|
||||
githubId = 100848;
|
||||
name = "André-Patrick Bubel";
|
||||
keys = [{
|
||||
longkeyid = "rsa8192/0x118CE7C424B45728";
|
||||
fingerprint = "4412 38AD CAD3 228D 876C 5455 118C E7C4 24B4 5728";
|
||||
}];
|
||||
};
|
||||
moretea = {
|
||||
email = "maarten@moretea.nl";
|
||||
@ -4540,6 +4672,12 @@
|
||||
githubId = 2881922;
|
||||
name = "Francis St-Amour";
|
||||
};
|
||||
mtrsk = {
|
||||
email = "marcos.schonfinkel@protonmail.com";
|
||||
github = "mtrsk";
|
||||
githubId = 16356569;
|
||||
name = "Marcos Benevides";
|
||||
};
|
||||
mredaelli = {
|
||||
email = "massimo@typish.io";
|
||||
github = "mredaelli";
|
||||
@ -6008,7 +6146,7 @@
|
||||
name = "Shahrukh Khan";
|
||||
};
|
||||
shanemikel = {
|
||||
email = "shanemikel1@gmail.com";
|
||||
email = "shanepearlman@pm.me";
|
||||
github = "shanemikel";
|
||||
githubId = 6720672;
|
||||
name = "Shane Pearlman";
|
||||
@ -6629,6 +6767,12 @@
|
||||
githubId = 42933;
|
||||
name = "Andrew Childs";
|
||||
};
|
||||
thefenriswolf = {
|
||||
email = "stefan.rohrbacher97@gmail.com";
|
||||
github = "thefenriswolf";
|
||||
githubId = "8547242";
|
||||
name = "Stefan Rohrbacher";
|
||||
};
|
||||
thesola10 = {
|
||||
email = "thesola10@bobile.fr";
|
||||
github = "thesola10";
|
||||
@ -7520,4 +7664,16 @@
|
||||
githubId = 50867187;
|
||||
name = "Rakesh Gupta";
|
||||
};
|
||||
mlatus = {
|
||||
email = "wqseleven@gmail.com";
|
||||
github = "Ninlives";
|
||||
githubId = 17873203;
|
||||
name = "mlatus";
|
||||
};
|
||||
waiting-for-dev = {
|
||||
email = "marc@lamarciana.com";
|
||||
github = "waiting-for-dev";
|
||||
githubId = 52650;
|
||||
name = "Marc Busqué";
|
||||
};
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ let
|
||||
|
||||
packageData = package: {
|
||||
name = package.name;
|
||||
pname = (builtins.parseDrvName package.name).name;
|
||||
pname = pkgs.lib.getName package;
|
||||
updateScript = map builtins.toString (pkgs.lib.toList package.updateScript);
|
||||
};
|
||||
|
||||
|
@ -13,9 +13,7 @@
|
||||
<para>
|
||||
It sets <xref linkend="opt-services.xserver.enable"/>,
|
||||
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/>,
|
||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> (
|
||||
<link linkend="opt-services.xserver.desktopManager.plasma5.enableQt4Support">
|
||||
without Qt4 Support</link>), and
|
||||
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/>, and
|
||||
<xref linkend="opt-services.xserver.libinput.enable"/> to true. It also
|
||||
includes glxinfo and firefox in the system packages list.
|
||||
</para>
|
||||
|
@ -39,7 +39,7 @@
|
||||
can select an alternative one by picking one of the following lines:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true;
|
||||
<xref linkend="opt-services.xserver.displayManager.slim.enable"/> = true;
|
||||
<xref linkend="opt-services.xserver.displayManager.gdm.enable"/> = true;
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
|
@ -99,7 +99,7 @@ xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
|
||||
<para>
|
||||
As an example, we will take the case of display managers. There is a central
|
||||
display manager module for generic display manager options and a module file
|
||||
per display manager backend (slim, sddm, gdm ...).
|
||||
per display manager backend (sddm, gdm ...).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -146,7 +146,7 @@ xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
|
||||
/>), and to extend
|
||||
it in each backend module
|
||||
(<xref
|
||||
linkend='ex-option-declaration-eot-backend-slim' />,
|
||||
linkend='ex-option-declaration-eot-backend-gdm' />,
|
||||
<xref
|
||||
linkend='ex-option-declaration-eot-backend-sddm' />).
|
||||
</para>
|
||||
@ -167,11 +167,11 @@ services.xserver.displayManager.enable = mkOption {
|
||||
};</screen>
|
||||
</example>
|
||||
|
||||
<example xml:id='ex-option-declaration-eot-backend-slim'>
|
||||
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>slim</literal> module</title>
|
||||
<example xml:id='ex-option-declaration-eot-backend-gdm'>
|
||||
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>gdm</literal> module</title>
|
||||
<screen>
|
||||
services.xserver.displayManager.enable = mkOption {
|
||||
type = with types; nullOr (enum [ "slim" ]);
|
||||
type = with types; nullOr (enum [ "gdm" ]);
|
||||
};</screen>
|
||||
</example>
|
||||
|
||||
|
@ -45,12 +45,12 @@
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>git tag -a -s -m "Release 17.09-beta" 17.09-beta
|
||||
&& git push --tags</literal>
|
||||
&& git push origin 17.09-beta</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
From the master branch run <literal>git checkout -B
|
||||
From the master branch run <literal>git checkout -b
|
||||
release-17.09</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
@ -157,7 +157,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
Release Nix (currently only Eelco Dolstra can do that).
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/53710c752a85f00658882531bc90a23a3d1287e4">
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix">
|
||||
Make sure fallback is updated. </link>
|
||||
</para>
|
||||
</listitem>
|
||||
@ -169,8 +169,8 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Change <literal>stableBranch</literal> to true and wait for channel to
|
||||
update.
|
||||
Change <literal>stableBranch</literal> to <literal>true</literal> in Hydra and wait for
|
||||
the channel to update.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@ -193,9 +193,11 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Update http://nixos.org/nixos/download.html and
|
||||
http://nixos.org/nixos/manual in
|
||||
https://github.com/NixOS/nixos-org-configurations
|
||||
Update the
|
||||
<link xlink:href="https://github.com/NixOS/nixos-homepage/commit/2a37975d5a617ecdfca94696242b6f32ffcba9f1"><code>NIXOS_SERIES</code></link>
|
||||
in the
|
||||
<link xlink:href="https://github.com/NixOS/nixos-homepage">nixos-homepage</link>
|
||||
repository.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -212,7 +214,8 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Send an email to nix-dev to announce the release with above information.
|
||||
Create a new topic on <link xlink:href="https://discourse.nixos.org/">the
|
||||
Discourse instance</link> to announce the release with the above information.
|
||||
Best to check how previous email was formulated to see what needs to be
|
||||
included.
|
||||
</para>
|
||||
|
@ -2,7 +2,7 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-running-nixos-tests">
|
||||
xml:id="sec-running-nixos-tests-interactively">
|
||||
<title>Running Tests interactively</title>
|
||||
|
||||
<para>
|
||||
|
@ -2,7 +2,7 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="sec-running-nixos-tests-interactively">
|
||||
xml:id="sec-running-nixos-tests">
|
||||
<title>Running Tests</title>
|
||||
|
||||
<para>
|
||||
|
@ -392,11 +392,11 @@
|
||||
<filename>hardware-configuration.nix</filename> is included from
|
||||
<filename>configuration.nix</filename> and will be overwritten by future
|
||||
invocations of <command>nixos-generate-config</command>; thus, you
|
||||
generally should not modify it.) Additionally, you may want to look at
|
||||
generally should not modify it.) Additionally, you may want to look at
|
||||
<link xlink:href="https://github.com/NixOS/nixos-hardware">Hardware
|
||||
configuration for known-hardware</link> at this point or after
|
||||
installation.
|
||||
|
||||
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
@ -418,11 +418,11 @@
|
||||
Do the installation:
|
||||
<screen>
|
||||
<prompt># </prompt>nixos-install</screen>
|
||||
Cross fingers. If this fails due to a temporary problem (such as a network
|
||||
issue while downloading binaries from the NixOS binary cache), you can
|
||||
just re-run <command>nixos-install</command>. Otherwise, fix your
|
||||
<filename>configuration.nix</filename> and then re-run
|
||||
<command>nixos-install</command>.
|
||||
This will install your system based on the configuration you provided.
|
||||
If anything fails due to a configuration problem or any other issue
|
||||
(such as a network outage while downloading binaries from the NixOS
|
||||
binary cache), you can re-run <command>nixos-install</command> after
|
||||
fixing your <filename>configuration.nix</filename>.
|
||||
</para>
|
||||
<para>
|
||||
As the last step, <command>nixos-install</command> will ask you to set the
|
||||
|
@ -543,7 +543,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
The <option>networking.useDHCP</option> option is unsupported in combination with
|
||||
<option>networking.useNetworkd</option> in anticipation of defaulting to it by default.
|
||||
<option>networking.useNetworkd</option> in anticipation of defaulting to it.
|
||||
It has to be set to <literal>false</literal> and enabled per
|
||||
interface with <option>networking.interfaces.<name>.useDHCP = true;</option>
|
||||
</para>
|
||||
|
@ -71,7 +71,11 @@
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para />
|
||||
<para>
|
||||
The kubernetes kube-proxy now supports a new hostname configuration
|
||||
<literal>services.kubernetes.proxy.hostname</literal> which has to
|
||||
be set if the hostname of the node should be non default.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
@ -131,6 +135,85 @@
|
||||
<link linkend="opt-networking.interfaces">networking.interfaces.<name>.…</link> options.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The stdenv now runs all bash with <literal>set -u</literal>, to catch the use of undefined variables.
|
||||
Before, it itself used <literal>set -u</literal> but was careful to unset it so other packages' code ran as before.
|
||||
Now, all bash code is held to the same high standard, and the rather complex stateful manipulation of the options can be discarded.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The SLIM Display Manager has been removed, as it has been unmaintained since 2013.
|
||||
Consider migrating to a different display manager such as LightDM (current default in NixOS),
|
||||
SDDM, GDM, or using the startx module which uses Xinitrc.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The BEAM package set has been deleted. You will only find there the different interpreters.
|
||||
You should now use the different build tools coming with the languages with sandbox mode disabled.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
There is now only one Xfce package-set and module. This means attributes, <literal>xfce4-14</literal>
|
||||
<literal>xfce4-12</literal>, and <literal>xfceUnstable</literal> all now point to the latest Xfce 4.14
|
||||
packages. And in future NixOS releases will be the latest released version of Xfce available at the
|
||||
time during the releases development (if viable).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <link linkend="opt-services.phpfpm.pools">phpfpm</link> module now sets
|
||||
<literal>PrivateTmp=true</literal> in its systemd units for better process isolation.
|
||||
If you rely on <literal>/tmp</literal> being shared with other services, explicitly override this by
|
||||
setting <literal>serviceConfig.PrivateTmp</literal> to <literal>false</literal> for each phpfpm unit.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
KDE’s old multimedia framework Phonon no longer supports Qt 4. For that reason, Plasma desktop also does not have <option>enableQt4Support</option> option any more.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The BeeGFS module has been removed.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The osquery module has been removed.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Going forward, <literal>~/bin</literal> in the users home directory will no longer be in <literal>PATH</literal> by default.
|
||||
If you depend on this you should set the option <literal>environment.homeBinInPath</literal> to <literal>true</literal>.
|
||||
The aforementioned option was added this release.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
|
||||
This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The packages <literal>openobex</literal> and <literal>obexftp</literal>
|
||||
are no loger installed when enabling bluetooth via
|
||||
<option>hardware.bluetooth.enable</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>dump1090</literal> derivation has been changed to use FlightAware's dump1090
|
||||
as its upstream. However, this version does not have an internal webserver anymore. The
|
||||
assets in the <literal>share/dump1090</literal> directory of the derivation can be used
|
||||
in conjunction with an external webserver to replace this functionality.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
@ -86,7 +86,7 @@ let
|
||||
optionsList = lib.sort optionLess optionsListDesc;
|
||||
|
||||
# Convert the list of options into an XML file.
|
||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsList);
|
||||
optionsXML = pkgs.writeText "options.xml" (builtins.toXML optionsList);
|
||||
|
||||
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
#! /somewhere/python3
|
||||
|
||||
from contextlib import contextmanager
|
||||
from contextlib import contextmanager, _GeneratorContextManager
|
||||
from xml.sax.saxutils import XMLGenerator
|
||||
import _thread
|
||||
import atexit
|
||||
import json
|
||||
import os
|
||||
import ptpython.repl
|
||||
import pty
|
||||
import queue
|
||||
from queue import Queue, Empty
|
||||
import re
|
||||
import shutil
|
||||
import socket
|
||||
@ -17,6 +15,9 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unicodedata
|
||||
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
|
||||
import shlex
|
||||
import pathlib
|
||||
|
||||
CHAR_TO_KEY = {
|
||||
"A": "shift-a",
|
||||
@ -81,12 +82,22 @@ CHAR_TO_KEY = {
|
||||
")": "shift-0x0B",
|
||||
}
|
||||
|
||||
# Forward references
|
||||
nr_tests: int
|
||||
nr_succeeded: int
|
||||
log: "Logger"
|
||||
machines: "List[Machine]"
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
|
||||
def eprint(*args: object, **kwargs: Any) -> None:
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
|
||||
def create_vlan(vlan_nr):
|
||||
def make_command(args: list) -> str:
|
||||
return " ".join(map(shlex.quote, (map(str, args))))
|
||||
|
||||
|
||||
def create_vlan(vlan_nr: str) -> Tuple[str, str, "subprocess.Popen[bytes]", Any]:
|
||||
global log
|
||||
log.log("starting VDE switch for network {}".format(vlan_nr))
|
||||
vde_socket = os.path.abspath("./vde{}.ctl".format(vlan_nr))
|
||||
@ -110,7 +121,7 @@ def create_vlan(vlan_nr):
|
||||
return (vlan_nr, vde_socket, vde_process, fd)
|
||||
|
||||
|
||||
def retry(fn):
|
||||
def retry(fn: Callable) -> None:
|
||||
"""Call the given function repeatedly, with 1 second intervals,
|
||||
until it returns True or a timeout is reached.
|
||||
"""
|
||||
@ -125,52 +136,52 @@ def retry(fn):
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self):
|
||||
def __init__(self) -> None:
|
||||
self.logfile = os.environ.get("LOGFILE", "/dev/null")
|
||||
self.logfile_handle = open(self.logfile, "wb")
|
||||
self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
|
||||
self.queue = queue.Queue(1000)
|
||||
self.queue: "Queue[Dict[str, str]]" = Queue(1000)
|
||||
|
||||
self.xml.startDocument()
|
||||
self.xml.startElement("logfile", attrs={})
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
self.xml.endElement("logfile")
|
||||
self.xml.endDocument()
|
||||
self.logfile_handle.close()
|
||||
|
||||
def sanitise(self, message):
|
||||
def sanitise(self, message: str) -> str:
|
||||
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
|
||||
|
||||
def maybe_prefix(self, message, attributes):
|
||||
def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
|
||||
if "machine" in attributes:
|
||||
return "{}: {}".format(attributes["machine"], message)
|
||||
return message
|
||||
|
||||
def log_line(self, message, attributes):
|
||||
def log_line(self, message: str, attributes: Dict[str, str]) -> None:
|
||||
self.xml.startElement("line", attributes)
|
||||
self.xml.characters(message)
|
||||
self.xml.endElement("line")
|
||||
|
||||
def log(self, message, attributes={}):
|
||||
def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
|
||||
eprint(self.maybe_prefix(message, attributes))
|
||||
self.drain_log_queue()
|
||||
self.log_line(message, attributes)
|
||||
|
||||
def enqueue(self, message):
|
||||
def enqueue(self, message: Dict[str, str]) -> None:
|
||||
self.queue.put(message)
|
||||
|
||||
def drain_log_queue(self):
|
||||
def drain_log_queue(self) -> None:
|
||||
try:
|
||||
while True:
|
||||
item = self.queue.get_nowait()
|
||||
attributes = {"machine": item["machine"], "type": "serial"}
|
||||
self.log_line(self.sanitise(item["msg"]), attributes)
|
||||
except queue.Empty:
|
||||
except Empty:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def nested(self, message, attributes={}):
|
||||
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
|
||||
eprint(self.maybe_prefix(message, attributes))
|
||||
|
||||
self.xml.startElement("nest", attrs={})
|
||||
@ -189,41 +200,39 @@ class Logger:
|
||||
|
||||
|
||||
class Machine:
|
||||
def __init__(self, args):
|
||||
def __init__(self, args: Dict[str, Any]) -> None:
|
||||
if "name" in args:
|
||||
self.name = args["name"]
|
||||
else:
|
||||
self.name = "machine"
|
||||
try:
|
||||
cmd = args["startCommand"]
|
||||
self.name = re.search("run-(.+)-vm$", cmd).group(1)
|
||||
except KeyError:
|
||||
pass
|
||||
except AttributeError:
|
||||
pass
|
||||
cmd = args.get("startCommand", None)
|
||||
if cmd:
|
||||
match = re.search("run-(.+)-vm$", cmd)
|
||||
if match:
|
||||
self.name = match.group(1)
|
||||
|
||||
self.script = args.get("startCommand", self.create_startcommand(args))
|
||||
|
||||
tmp_dir = os.environ.get("TMPDIR", tempfile.gettempdir())
|
||||
|
||||
def create_dir(name):
|
||||
def create_dir(name: str) -> str:
|
||||
path = os.path.join(tmp_dir, name)
|
||||
os.makedirs(path, mode=0o700, exist_ok=True)
|
||||
return path
|
||||
|
||||
self.state_dir = create_dir("vm-state-{}".format(self.name))
|
||||
self.shared_dir = create_dir("xchg-shared")
|
||||
self.shared_dir = create_dir("{}/xchg".format(self.state_dir))
|
||||
|
||||
self.booted = False
|
||||
self.connected = False
|
||||
self.pid = None
|
||||
self.pid: Optional[int] = None
|
||||
self.socket = None
|
||||
self.monitor = None
|
||||
self.logger = args["log"]
|
||||
self.monitor: Optional[socket.socket] = None
|
||||
self.logger: Logger = args["log"]
|
||||
self.allow_reboot = args.get("allowReboot", False)
|
||||
|
||||
@staticmethod
|
||||
def create_startcommand(args):
|
||||
def create_startcommand(args: Dict[str, str]) -> str:
|
||||
net_backend = "-netdev user,id=net0"
|
||||
net_frontend = "-device virtio-net-pci,netdev=net0"
|
||||
|
||||
@ -273,30 +282,37 @@ class Machine:
|
||||
|
||||
return start_command
|
||||
|
||||
def is_up(self):
|
||||
def is_up(self) -> bool:
|
||||
return self.booted and self.connected
|
||||
|
||||
def log(self, msg):
|
||||
def log(self, msg: str) -> None:
|
||||
self.logger.log(msg, {"machine": self.name})
|
||||
|
||||
def nested(self, msg, attrs={}):
|
||||
def nested(self, msg: str, attrs: Dict[str, str] = {}) -> _GeneratorContextManager:
|
||||
my_attrs = {"machine": self.name}
|
||||
my_attrs.update(attrs)
|
||||
return self.logger.nested(msg, my_attrs)
|
||||
|
||||
def wait_for_monitor_prompt(self):
|
||||
def wait_for_monitor_prompt(self) -> str:
|
||||
assert self.monitor is not None
|
||||
answer = ""
|
||||
while True:
|
||||
answer = self.monitor.recv(1024).decode()
|
||||
undecoded_answer = self.monitor.recv(1024)
|
||||
if not undecoded_answer:
|
||||
break
|
||||
answer += undecoded_answer.decode()
|
||||
if answer.endswith("(qemu) "):
|
||||
return answer
|
||||
break
|
||||
return answer
|
||||
|
||||
def send_monitor_command(self, command):
|
||||
def send_monitor_command(self, command: str) -> str:
|
||||
message = ("{}\n".format(command)).encode()
|
||||
self.log("sending monitor command: {}".format(command))
|
||||
assert self.monitor is not None
|
||||
self.monitor.send(message)
|
||||
return self.wait_for_monitor_prompt()
|
||||
|
||||
def wait_for_unit(self, unit, user=None):
|
||||
def wait_for_unit(self, unit: str, user: Optional[str] = None) -> bool:
|
||||
while True:
|
||||
info = self.get_unit_info(unit, user)
|
||||
state = info["ActiveState"]
|
||||
@ -316,7 +332,7 @@ class Machine:
|
||||
if state == "active":
|
||||
return True
|
||||
|
||||
def get_unit_info(self, unit, user=None):
|
||||
def get_unit_info(self, unit: str, user: Optional[str] = None) -> Dict[str, str]:
|
||||
status, lines = self.systemctl('--no-pager show "{}"'.format(unit), user)
|
||||
if status != 0:
|
||||
raise Exception(
|
||||
@ -327,8 +343,9 @@ class Machine:
|
||||
|
||||
line_pattern = re.compile(r"^([^=]+)=(.*)$")
|
||||
|
||||
def tuple_from_line(line):
|
||||
def tuple_from_line(line: str) -> Tuple[str, str]:
|
||||
match = line_pattern.match(line)
|
||||
assert match is not None
|
||||
return match[1], match[2]
|
||||
|
||||
return dict(
|
||||
@ -337,7 +354,7 @@ class Machine:
|
||||
if line_pattern.match(line)
|
||||
)
|
||||
|
||||
def systemctl(self, q, user=None):
|
||||
def systemctl(self, q: str, user: Optional[str] = None) -> Tuple[int, str]:
|
||||
if user is not None:
|
||||
q = q.replace("'", "\\'")
|
||||
return self.execute(
|
||||
@ -349,7 +366,7 @@ class Machine:
|
||||
)
|
||||
return self.execute("systemctl {}".format(q))
|
||||
|
||||
def require_unit_state(self, unit, require_state="active"):
|
||||
def require_unit_state(self, unit: str, require_state: str = "active") -> None:
|
||||
with self.nested(
|
||||
"checking if unit ‘{}’ has reached state '{}'".format(unit, require_state)
|
||||
):
|
||||
@ -361,7 +378,7 @@ class Machine:
|
||||
+ "'active' but it is in state ‘{}’".format(state)
|
||||
)
|
||||
|
||||
def execute(self, command):
|
||||
def execute(self, command: str) -> Tuple[int, str]:
|
||||
self.connect()
|
||||
|
||||
out_command = "( {} ); echo '|!EOF' $?\n".format(command)
|
||||
@ -379,19 +396,21 @@ class Machine:
|
||||
return (status_code, output)
|
||||
output += chunk
|
||||
|
||||
def succeed(self, *commands):
|
||||
def succeed(self, *commands: str) -> str:
|
||||
"""Execute each command and check that it succeeds."""
|
||||
output = ""
|
||||
for command in commands:
|
||||
with self.nested("must succeed: {}".format(command)):
|
||||
status, output = self.execute(command)
|
||||
(status, out) = self.execute(command)
|
||||
if status != 0:
|
||||
self.log("output: {}".format(output))
|
||||
self.log("output: {}".format(out))
|
||||
raise Exception(
|
||||
"command `{}` failed (exit code {})".format(command, status)
|
||||
)
|
||||
return output
|
||||
output += out
|
||||
return output
|
||||
|
||||
def fail(self, *commands):
|
||||
def fail(self, *commands: str) -> None:
|
||||
"""Execute each command and check that it fails."""
|
||||
for command in commands:
|
||||
with self.nested("must fail: {}".format(command)):
|
||||
@ -401,21 +420,21 @@ class Machine:
|
||||
"command `{}` unexpectedly succeeded".format(command)
|
||||
)
|
||||
|
||||
def wait_until_succeeds(self, command):
|
||||
def wait_until_succeeds(self, command: str) -> str:
|
||||
with self.nested("waiting for success: {}".format(command)):
|
||||
while True:
|
||||
status, output = self.execute(command)
|
||||
if status == 0:
|
||||
return output
|
||||
|
||||
def wait_until_fails(self, command):
|
||||
def wait_until_fails(self, command: str) -> str:
|
||||
with self.nested("waiting for failure: {}".format(command)):
|
||||
while True:
|
||||
status, output = self.execute(command)
|
||||
if status != 0:
|
||||
return output
|
||||
|
||||
def wait_for_shutdown(self):
|
||||
def wait_for_shutdown(self) -> None:
|
||||
if not self.booted:
|
||||
return
|
||||
|
||||
@ -427,14 +446,14 @@ class Machine:
|
||||
self.booted = False
|
||||
self.connected = False
|
||||
|
||||
def get_tty_text(self, tty):
|
||||
def get_tty_text(self, tty: str) -> str:
|
||||
status, output = self.execute(
|
||||
"fold -w$(stty -F /dev/tty{0} size | "
|
||||
"awk '{{print $2}}') /dev/vcs{0}".format(tty)
|
||||
)
|
||||
return output
|
||||
|
||||
def wait_until_tty_matches(self, tty, regexp):
|
||||
def wait_until_tty_matches(self, tty: str, regexp: str) -> bool:
|
||||
matcher = re.compile(regexp)
|
||||
with self.nested("waiting for {} to appear on tty {}".format(regexp, tty)):
|
||||
while True:
|
||||
@ -442,43 +461,43 @@ class Machine:
|
||||
if len(matcher.findall(text)) > 0:
|
||||
return True
|
||||
|
||||
def send_chars(self, chars):
|
||||
def send_chars(self, chars: List[str]) -> None:
|
||||
with self.nested("sending keys ‘{}‘".format(chars)):
|
||||
for char in chars:
|
||||
self.send_key(char)
|
||||
|
||||
def wait_for_file(self, filename):
|
||||
def wait_for_file(self, filename: str) -> bool:
|
||||
with self.nested("waiting for file ‘{}‘".format(filename)):
|
||||
while True:
|
||||
status, _ = self.execute("test -e {}".format(filename))
|
||||
if status == 0:
|
||||
return True
|
||||
|
||||
def wait_for_open_port(self, port):
|
||||
def port_is_open(_):
|
||||
def wait_for_open_port(self, port: int) -> None:
|
||||
def port_is_open(_: Any) -> bool:
|
||||
status, _ = self.execute("nc -z localhost {}".format(port))
|
||||
return status == 0
|
||||
|
||||
with self.nested("waiting for TCP port {}".format(port)):
|
||||
retry(port_is_open)
|
||||
|
||||
def wait_for_closed_port(self, port):
|
||||
def port_is_closed(_):
|
||||
def wait_for_closed_port(self, port: int) -> None:
|
||||
def port_is_closed(_: Any) -> bool:
|
||||
status, _ = self.execute("nc -z localhost {}".format(port))
|
||||
return status != 0
|
||||
|
||||
retry(port_is_closed)
|
||||
|
||||
def start_job(self, jobname, user=None):
|
||||
def start_job(self, jobname: str, user: Optional[str] = None) -> Tuple[int, str]:
|
||||
return self.systemctl("start {}".format(jobname), user)
|
||||
|
||||
def stop_job(self, jobname, user=None):
|
||||
def stop_job(self, jobname: str, user: Optional[str] = None) -> Tuple[int, str]:
|
||||
return self.systemctl("stop {}".format(jobname), user)
|
||||
|
||||
def wait_for_job(self, jobname):
|
||||
def wait_for_job(self, jobname: str) -> bool:
|
||||
return self.wait_for_unit(jobname)
|
||||
|
||||
def connect(self):
|
||||
def connect(self) -> None:
|
||||
if self.connected:
|
||||
return
|
||||
|
||||
@ -494,7 +513,7 @@ class Machine:
|
||||
self.log("(connecting took {:.2f} seconds)".format(toc - tic))
|
||||
self.connected = True
|
||||
|
||||
def screenshot(self, filename):
|
||||
def screenshot(self, filename: str) -> None:
|
||||
out_dir = os.environ.get("out", os.getcwd())
|
||||
word_pattern = re.compile(r"^\w+$")
|
||||
if word_pattern.match(filename):
|
||||
@ -511,12 +530,39 @@ class Machine:
|
||||
if ret.returncode != 0:
|
||||
raise Exception("Cannot convert screenshot")
|
||||
|
||||
def dump_tty_contents(self, tty):
|
||||
def copy_from_vm(self, source: str, target_dir: str = "") -> None:
|
||||
"""Copy a file from the VM (specified by an in-VM source path) to a path
|
||||
relative to `$out`. The file is copied via the `shared_dir` shared among
|
||||
all the VMs (using a temporary directory).
|
||||
"""
|
||||
# Compute the source, target, and intermediate shared file names
|
||||
out_dir = pathlib.Path(os.environ.get("out", os.getcwd()))
|
||||
vm_src = pathlib.Path(source)
|
||||
with tempfile.TemporaryDirectory(dir=self.shared_dir) as shared_td:
|
||||
shared_temp = pathlib.Path(shared_td)
|
||||
vm_shared_temp = pathlib.Path("/tmp/xchg") / shared_temp.name
|
||||
vm_intermediate = vm_shared_temp / vm_src.name
|
||||
intermediate = shared_temp / vm_src.name
|
||||
# Copy the file to the shared directory inside VM
|
||||
self.succeed(make_command(["mkdir", "-p", vm_shared_temp]))
|
||||
self.succeed(make_command(["cp", "-r", vm_src, vm_intermediate]))
|
||||
self.succeed("sync")
|
||||
abs_target = out_dir / target_dir / vm_src.name
|
||||
abs_target.parent.mkdir(exist_ok=True, parents=True)
|
||||
# Copy the file from the shared directory outside VM
|
||||
if intermediate.is_dir():
|
||||
shutil.copytree(intermediate, abs_target)
|
||||
else:
|
||||
shutil.copy(intermediate, abs_target)
|
||||
# Make sure the cleanup is synced into VM
|
||||
self.succeed("sync")
|
||||
|
||||
def dump_tty_contents(self, tty: str) -> None:
|
||||
"""Debugging: Dump the contents of the TTY<n>
|
||||
"""
|
||||
self.execute("fold -w 80 /dev/vcs{} | systemd-cat".format(tty))
|
||||
|
||||
def get_screen_text(self):
|
||||
def get_screen_text(self) -> str:
|
||||
if shutil.which("tesseract") is None:
|
||||
raise Exception("get_screen_text used but enableOCR is false")
|
||||
|
||||
@ -544,30 +590,30 @@ class Machine:
|
||||
|
||||
return ret.stdout.decode("utf-8")
|
||||
|
||||
def wait_for_text(self, regex):
|
||||
def screen_matches(last):
|
||||
def wait_for_text(self, regex: str) -> None:
|
||||
def screen_matches(last: bool) -> bool:
|
||||
text = self.get_screen_text()
|
||||
m = re.search(regex, text)
|
||||
matches = re.search(regex, text) is not None
|
||||
|
||||
if last and not m:
|
||||
if last and not matches:
|
||||
self.log("Last OCR attempt failed. Text was: {}".format(text))
|
||||
|
||||
return m
|
||||
return matches
|
||||
|
||||
with self.nested("waiting for {} to appear on screen".format(regex)):
|
||||
retry(screen_matches)
|
||||
|
||||
def send_key(self, key):
|
||||
def send_key(self, key: str) -> None:
|
||||
key = CHAR_TO_KEY.get(key, key)
|
||||
self.send_monitor_command("sendkey {}".format(key))
|
||||
|
||||
def start(self):
|
||||
def start(self) -> None:
|
||||
if self.booted:
|
||||
return
|
||||
|
||||
self.log("starting vm")
|
||||
|
||||
def create_socket(path):
|
||||
def create_socket(path: str) -> socket.socket:
|
||||
if os.path.exists(path):
|
||||
os.unlink(path)
|
||||
s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM)
|
||||
@ -597,12 +643,15 @@ class Machine:
|
||||
+ os.environ.get("QEMU_OPTS", "")
|
||||
)
|
||||
|
||||
environment = {
|
||||
"QEMU_OPTS": qemu_options,
|
||||
"SHARED_DIR": self.shared_dir,
|
||||
"USE_TMPDIR": "1",
|
||||
}
|
||||
environment.update(dict(os.environ))
|
||||
environment = dict(os.environ)
|
||||
environment.update(
|
||||
{
|
||||
"TMPDIR": self.state_dir,
|
||||
"SHARED_DIR": self.shared_dir,
|
||||
"USE_TMPDIR": "1",
|
||||
"QEMU_OPTS": qemu_options,
|
||||
}
|
||||
)
|
||||
|
||||
self.process = subprocess.Popen(
|
||||
self.script,
|
||||
@ -617,9 +666,9 @@ class Machine:
|
||||
self.monitor, _ = self.monitor_socket.accept()
|
||||
self.shell, _ = self.shell_socket.accept()
|
||||
|
||||
def process_serial_output():
|
||||
for line in self.process.stdout:
|
||||
line = line.decode("unicode_escape").replace("\r", "").rstrip()
|
||||
def process_serial_output() -> None:
|
||||
for _line in self.process.stdout:
|
||||
line = _line.decode("unicode_escape").replace("\r", "").rstrip()
|
||||
eprint("{} # {}".format(self.name, line))
|
||||
self.logger.enqueue({"msg": line, "machine": self.name})
|
||||
|
||||
@ -632,14 +681,14 @@ class Machine:
|
||||
|
||||
self.log("QEMU running (pid {})".format(self.pid))
|
||||
|
||||
def shutdown(self):
|
||||
def shutdown(self) -> None:
|
||||
if not self.booted:
|
||||
return
|
||||
|
||||
self.shell.send("poweroff\n".encode())
|
||||
self.wait_for_shutdown()
|
||||
|
||||
def crash(self):
|
||||
def crash(self) -> None:
|
||||
if not self.booted:
|
||||
return
|
||||
|
||||
@ -647,7 +696,7 @@ class Machine:
|
||||
self.send_monitor_command("quit")
|
||||
self.wait_for_shutdown()
|
||||
|
||||
def wait_for_x(self):
|
||||
def wait_for_x(self) -> None:
|
||||
"""Wait until it is possible to connect to the X server. Note that
|
||||
testing the existence of /tmp/.X11-unix/X0 is insufficient.
|
||||
"""
|
||||
@ -664,15 +713,15 @@ class Machine:
|
||||
if status == 0:
|
||||
return
|
||||
|
||||
def get_window_names(self):
|
||||
def get_window_names(self) -> List[str]:
|
||||
return self.succeed(
|
||||
r"xwininfo -root -tree | sed 's/.*0x[0-9a-f]* \"\([^\"]*\)\".*/\1/; t; d'"
|
||||
).splitlines()
|
||||
|
||||
def wait_for_window(self, regexp):
|
||||
def wait_for_window(self, regexp: str) -> None:
|
||||
pattern = re.compile(regexp)
|
||||
|
||||
def window_is_visible(last_try):
|
||||
def window_is_visible(last_try: bool) -> bool:
|
||||
names = self.get_window_names()
|
||||
if last_try:
|
||||
self.log(
|
||||
@ -685,10 +734,10 @@ class Machine:
|
||||
with self.nested("Waiting for a window to appear"):
|
||||
retry(window_is_visible)
|
||||
|
||||
def sleep(self, secs):
|
||||
def sleep(self, secs: int) -> None:
|
||||
time.sleep(secs)
|
||||
|
||||
def forward_port(self, host_port=8080, guest_port=80):
|
||||
def forward_port(self, host_port: int = 8080, guest_port: int = 80) -> None:
|
||||
"""Forward a TCP port on the host to a TCP port on the guest.
|
||||
Useful during interactive testing.
|
||||
"""
|
||||
@ -696,48 +745,51 @@ class Machine:
|
||||
"hostfwd_add tcp::{}-:{}".format(host_port, guest_port)
|
||||
)
|
||||
|
||||
def block(self):
|
||||
def block(self) -> None:
|
||||
"""Make the machine unreachable by shutting down eth1 (the multicast
|
||||
interface used to talk to the other VMs). We keep eth0 up so that
|
||||
the test driver can continue to talk to the machine.
|
||||
"""
|
||||
self.send_monitor_command("set_link virtio-net-pci.1 off")
|
||||
|
||||
def unblock(self):
|
||||
def unblock(self) -> None:
|
||||
"""Make the machine reachable.
|
||||
"""
|
||||
self.send_monitor_command("set_link virtio-net-pci.1 on")
|
||||
|
||||
|
||||
def create_machine(args):
|
||||
def create_machine(args: Dict[str, Any]) -> Machine:
|
||||
global log
|
||||
args["log"] = log
|
||||
args["redirectSerial"] = os.environ.get("USE_SERIAL", "0") == "1"
|
||||
return Machine(args)
|
||||
|
||||
|
||||
def start_all():
|
||||
def start_all() -> None:
|
||||
global machines
|
||||
with log.nested("starting all VMs"):
|
||||
for machine in machines:
|
||||
machine.start()
|
||||
|
||||
|
||||
def join_all():
|
||||
def join_all() -> None:
|
||||
global machines
|
||||
with log.nested("waiting for all VMs to finish"):
|
||||
for machine in machines:
|
||||
machine.wait_for_shutdown()
|
||||
|
||||
|
||||
def test_script():
|
||||
def test_script() -> None:
|
||||
exec(os.environ["testScript"])
|
||||
|
||||
|
||||
def run_tests():
|
||||
def run_tests() -> None:
|
||||
global machines
|
||||
tests = os.environ.get("tests", None)
|
||||
if tests is not None:
|
||||
with log.nested("running the VM test script"):
|
||||
try:
|
||||
exec(tests)
|
||||
exec(tests, globals())
|
||||
except Exception as e:
|
||||
eprint("error: {}".format(str(e)))
|
||||
sys.exit(1)
|
||||
@ -751,11 +803,13 @@ def run_tests():
|
||||
machine.execute("sync")
|
||||
|
||||
if nr_tests != 0:
|
||||
log.log("{} out of {} tests succeeded".format(nr_succeeded, nr_tests))
|
||||
eprint("{} out of {} tests succeeded".format(nr_succeeded, nr_tests))
|
||||
if nr_tests > nr_succeeded:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def subtest(name):
|
||||
def subtest(name: str) -> Iterator[None]:
|
||||
global nr_tests
|
||||
global nr_succeeded
|
||||
|
||||
@ -772,7 +826,6 @@ def subtest(name):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
global log
|
||||
log = Logger()
|
||||
|
||||
vlan_nrs = list(dict.fromkeys(os.environ["VLANS"].split()))
|
||||
@ -791,7 +844,7 @@ if __name__ == "__main__":
|
||||
nr_succeeded = 0
|
||||
|
||||
@atexit.register
|
||||
def clean_up():
|
||||
def clean_up() -> None:
|
||||
with log.nested("cleaning up"):
|
||||
for machine in machines:
|
||||
if machine.pid is None:
|
||||
|
@ -26,7 +26,7 @@ in rec {
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
buildInputs = [ (python3.withPackages (p: [ p.ptpython ])) ];
|
||||
checkInputs = with python3Packages; [ pylint black ];
|
||||
checkInputs = with python3Packages; [ pylint black mypy ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
@ -34,6 +34,9 @@ in rec {
|
||||
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${testDriverScript}
|
||||
pylint --errors-only ${testDriverScript}
|
||||
black --check --diff ${testDriverScript}
|
||||
'';
|
||||
@ -258,7 +261,6 @@ in rec {
|
||||
inherit require;
|
||||
virtualisation.memorySize = 1024;
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager.slim.enable = false;
|
||||
services.xserver.displayManager.auto.enable = true;
|
||||
services.xserver.windowManager.default = "icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
|
@ -248,7 +248,6 @@ in rec {
|
||||
inherit require;
|
||||
virtualisation.memorySize = 1024;
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager.slim.enable = false;
|
||||
services.xserver.displayManager.auto.enable = true;
|
||||
services.xserver.windowManager.default = "icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
|
@ -211,11 +211,11 @@ upload_image() {
|
||||
log "Registering snapshot $snapshot_id as AMI"
|
||||
|
||||
local block_device_mappings=(
|
||||
"DeviceName=/dev/sda1,Ebs={SnapshotId=$snapshot_id,VolumeSize=$image_logical_gigabytes,DeleteOnTermination=true,VolumeType=gp2}"
|
||||
"DeviceName=/dev/xvda,Ebs={SnapshotId=$snapshot_id,VolumeSize=$image_logical_gigabytes,DeleteOnTermination=true,VolumeType=gp2}"
|
||||
)
|
||||
|
||||
local extra_flags=(
|
||||
--root-device-name /dev/sda1
|
||||
--root-device-name /dev/xvda
|
||||
--sriov-net-support simple
|
||||
--ena-support
|
||||
--virtualization-type hvm
|
||||
|
@ -10,7 +10,7 @@ let
|
||||
isQtStyle = cfg.platformTheme == "gtk2" && cfg.style != "adwaita";
|
||||
|
||||
packages = if isQGnome then [ pkgs.qgnomeplatform pkgs.adwaita-qt ]
|
||||
else if isQtStyle then [ pkgs.qtstyleplugins ]
|
||||
else if isQtStyle then [ pkgs.libsForQt5.qtstyleplugins ]
|
||||
else throw "`qt5.platformTheme` ${cfg.platformTheme} and `qt5.style` ${cfg.style} are not compatible.";
|
||||
|
||||
in
|
||||
|
@ -122,7 +122,7 @@ in
|
||||
description = ''
|
||||
Include ~/bin/ in $PATH.
|
||||
'';
|
||||
default = true;
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking.vpnc;
|
||||
mkServiceDef = name: value:
|
||||
{
|
||||
name = "vpnc/${name}.conf";
|
||||
value = { text = value; };
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
networking.vpnc = {
|
||||
services = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
example = literalExample ''
|
||||
{ test = '''
|
||||
IPSec gateway 192.168.1.1
|
||||
IPSec ID someID
|
||||
IPSec secret secretKey
|
||||
Xauth username name
|
||||
Xauth password pass
|
||||
''';
|
||||
}
|
||||
'';
|
||||
description =
|
||||
''
|
||||
The names of cisco VPNs and their associated definitions
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config.environment.etc = mapAttrs' mkServiceDef cfg.services;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ in
|
||||
|
||||
Note that this configuration will only be successful when a display manager
|
||||
for which the <option>services.xserver.displayManager.setupCommands</option>
|
||||
option is supported is used; notably, SLiM is not supported.
|
||||
option is supported is used.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -111,9 +111,10 @@ in
|
||||
config = mkIf enabled {
|
||||
assertions = [
|
||||
{
|
||||
assertion = with config.services.xserver.displayManager; gdm.enable -> !gdm.wayland;
|
||||
message = "NVIDIA drivers don't support wayland, set services.xserver.displayManager.gdm.wayland=false";
|
||||
assertion = with config.services.xserver.displayManager; gdm.nvidiaWayland -> cfg.modesetting.enable;
|
||||
message = "You cannot use wayland with GDM without modesetting enabled for NVIDIA drivers, set `hardware.nvidia.modesetting.enable = true`";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = !optimusCfg.enable ||
|
||||
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
|
||||
|
@ -55,7 +55,7 @@ in
|
||||
|
||||
# Without dconf enabled it is impossible to use IBus
|
||||
environment.systemPackages = with pkgs; [
|
||||
gnome3.dconf ibusAutostart
|
||||
dconf ibusAutostart
|
||||
];
|
||||
|
||||
environment.variables = {
|
||||
|
@ -22,17 +22,7 @@ with lib;
|
||||
});
|
||||
'';
|
||||
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
|
||||
# Automatically login as nixos.
|
||||
displayManager.slim = {
|
||||
enable = true;
|
||||
defaultUser = "nixos";
|
||||
autoLogin = true;
|
||||
};
|
||||
|
||||
};
|
||||
services.xserver.enable = true;
|
||||
|
||||
# Provide networkmanager for easy wireless configuration.
|
||||
networking.networkmanager.enable = true;
|
||||
|
@ -10,8 +10,6 @@ with lib;
|
||||
|
||||
services.xserver.desktopManager.gnome3.enable = true;
|
||||
|
||||
services.xserver.displayManager.slim.enable = mkForce false;
|
||||
|
||||
# Auto-login as root.
|
||||
services.xserver.displayManager.gdm.autoLogin = {
|
||||
enable = true;
|
||||
|
@ -11,7 +11,15 @@ with lib;
|
||||
services.xserver = {
|
||||
desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
enableQt4Support = false;
|
||||
};
|
||||
|
||||
# Automatically login as nixos.
|
||||
displayManager.sddm = {
|
||||
enable = true;
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "nixos";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
{ lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) types;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
|
||||
@ -19,6 +22,7 @@
|
||||
description = ''
|
||||
The user IDs used in NixOS.
|
||||
'';
|
||||
type = types.attrsOf types.int;
|
||||
};
|
||||
|
||||
ids.gids = lib.mkOption {
|
||||
@ -26,6 +30,7 @@
|
||||
description = ''
|
||||
The group IDs used in NixOS.
|
||||
'';
|
||||
type = types.attrsOf types.int;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -35,7 +35,6 @@
|
||||
./config/terminfo.nix
|
||||
./config/unix-odbc-drivers.nix
|
||||
./config/users-groups.nix
|
||||
./config/vpnc.nix
|
||||
./config/vte.nix
|
||||
./config/zram.nix
|
||||
./hardware/acpilight.nix
|
||||
@ -308,6 +307,7 @@
|
||||
./services/desktops/gnome3/sushi.nix
|
||||
./services/desktops/gnome3/tracker.nix
|
||||
./services/desktops/gnome3/tracker-miners.nix
|
||||
./services/desktops/neard.nix
|
||||
./services/desktops/profile-sync-daemon.nix
|
||||
./services/desktops/system-config-printer.nix
|
||||
./services/desktops/telepathy.nix
|
||||
@ -316,6 +316,7 @@
|
||||
./services/development/bloop.nix
|
||||
./services/development/hoogle.nix
|
||||
./services/development/jupyter/default.nix
|
||||
./services/development/lorri.nix
|
||||
./services/editors/emacs.nix
|
||||
./services/editors/infinoted.nix
|
||||
./services/games/factorio.nix
|
||||
@ -518,7 +519,6 @@
|
||||
./services/monitoring/munin.nix
|
||||
./services/monitoring/nagios.nix
|
||||
./services/monitoring/netdata.nix
|
||||
./services/monitoring/osquery.nix
|
||||
./services/monitoring/prometheus/default.nix
|
||||
./services/monitoring/prometheus/alertmanager.nix
|
||||
./services/monitoring/prometheus/exporters.nix
|
||||
@ -538,7 +538,6 @@
|
||||
./services/monitoring/zabbix-agent.nix
|
||||
./services/monitoring/zabbix-proxy.nix
|
||||
./services/monitoring/zabbix-server.nix
|
||||
./services/network-filesystems/beegfs.nix
|
||||
./services/network-filesystems/cachefilesd.nix
|
||||
./services/network-filesystems/davfs2.nix
|
||||
./services/network-filesystems/drbd.nix
|
||||
@ -841,6 +840,7 @@
|
||||
./services/web-servers/shellinabox.nix
|
||||
./services/web-servers/tomcat.nix
|
||||
./services/web-servers/traefik.nix
|
||||
./services/web-servers/ttyd.nix
|
||||
./services/web-servers/uwsgi.nix
|
||||
./services/web-servers/varnish/default.nix
|
||||
./services/web-servers/zope2.nix
|
||||
|
@ -9,14 +9,12 @@
|
||||
displayManager.sddm.enable = true;
|
||||
desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
enableQt4Support = false;
|
||||
};
|
||||
libinput.enable = true; # for touchpad support on many laptops
|
||||
};
|
||||
|
||||
# Enable sound in virtualbox appliances.
|
||||
hardware.pulseaudio.enable = true;
|
||||
hardware.pulseaudio.systemWide = true; # Needed since we run plasma as root.
|
||||
|
||||
environment.systemPackages = [ pkgs.glxinfo pkgs.firefox ];
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ with lib;
|
||||
###### implementation
|
||||
config = mkIf config.programs.adb.enable {
|
||||
services.udev.packages = [ pkgs.android-udev-rules ];
|
||||
environment.systemPackages = [ pkgs.androidenv.androidPkgs_9_0.platform-tools ];
|
||||
# Give platform-tools lower priority so mke2fs+friends are taken from other packages first
|
||||
environment.systemPackages = [ (lowPrio pkgs.androidenv.androidPkgs_9_0.platform-tools) ];
|
||||
users.groups.adbusers = {};
|
||||
};
|
||||
}
|
||||
|
@ -32,13 +32,13 @@ in
|
||||
environment.etc = optionals (cfg.profiles != {})
|
||||
(mapAttrsToList mkDconfProfile cfg.profiles);
|
||||
|
||||
services.dbus.packages = [ pkgs.gnome3.dconf ];
|
||||
services.dbus.packages = [ pkgs.dconf ];
|
||||
|
||||
# For dconf executable
|
||||
environment.systemPackages = [ pkgs.gnome3.dconf ];
|
||||
environment.systemPackages = [ pkgs.dconf ];
|
||||
|
||||
# Needed for unwrapped applications
|
||||
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.gnome3.dconf.lib}/lib/gio/modules" ];
|
||||
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -8,18 +8,16 @@
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.networking.defaultMailServer;
|
||||
cfg = config.services.ssmtp;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
networking.defaultMailServer = {
|
||||
services.ssmtp = {
|
||||
|
||||
directDelivery = mkOption {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
@ -29,7 +27,7 @@ in
|
||||
<command>sendmail</command> or <command>postfix</command> on
|
||||
your machine, set this option to <literal>true</literal>, and
|
||||
set the option
|
||||
<option>networking.defaultMailServer.hostName</option> to the
|
||||
<option>services.ssmtp.hostName</option> to the
|
||||
host name of your preferred mail server.
|
||||
'';
|
||||
};
|
||||
@ -129,9 +127,9 @@ in
|
||||
};
|
||||
|
||||
|
||||
config = mkIf cfg.directDelivery {
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
networking.defaultMailServer.authPassFile = mkIf (cfg.authPass != "")
|
||||
services.ssmtp.authPassFile = mkIf (cfg.authPass != "")
|
||||
(mkDefault (toString (pkgs.writeTextFile {
|
||||
name = "ssmtp-authpass";
|
||||
text = cfg.authPass;
|
||||
|
@ -10,6 +10,9 @@ with lib;
|
||||
(mkRenamedOptionModule [ "networking" "enableRalinkFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||
(mkRenamedOptionModule [ "networking" "enableRTL8192cFirmware" ] [ "hardware" "enableRedistributableFirmware" ])
|
||||
(mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ])
|
||||
(mkRenamedOptionModule [ "networking" "connman" ] [ "services" "connman" ])
|
||||
(mkRenamedOptionModule [ "networking" "defaultMailServer" ] [ "services" "ssmtp" ])
|
||||
(mkRenamedOptionModule [ "services" "ssmtp" "directDelivery" ] [ "services" "ssmtp" "enable" ])
|
||||
(mkChangedOptionModule [ "services" "printing" "gutenprint" ] [ "services" "printing" "drivers" ]
|
||||
(config:
|
||||
let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config;
|
||||
@ -235,6 +238,7 @@ with lib;
|
||||
(mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.")
|
||||
(mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
|
||||
(mkRemovedOptionModule [ "fonts" "enableCoreFonts" ] "Use fonts.fonts = [ pkgs.corefonts ]; instead.")
|
||||
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
|
||||
|
||||
# ZSH
|
||||
(mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
|
||||
@ -279,6 +283,13 @@ with lib;
|
||||
# BLCR
|
||||
(mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
|
||||
|
||||
# beegfs
|
||||
(mkRemovedOptionModule [ "services.beegfsEnable" ] "The BeeGFS module has been removed")
|
||||
(mkRemovedOptionModule [ "services.beegfs" ] "The BeeGFS module has been removed")
|
||||
|
||||
# osquery
|
||||
(mkRemovedOptionModule [ "services.osquery" ] "The osquery module has been removed")
|
||||
|
||||
# Redis
|
||||
(mkRemovedOptionModule [ "services" "redis" "user" ] "The redis module now is hardcoded to the redis user.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "dbpath" ] "The redis module now uses /var/lib/redis as data directory.")
|
||||
|
@ -224,6 +224,12 @@ in
|
||||
environment.REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
# With RemainAfterExit the service is considered active even
|
||||
# after the main process having exited, which means when it
|
||||
# gets changed, the activation phase restarts it, meaning
|
||||
# the permissions of the StateDirectory get adjusted
|
||||
# according to the specified group
|
||||
RemainAfterExit = true;
|
||||
SuccessExitStatus = [ "0" "1" ];
|
||||
User = data.user;
|
||||
Group = data.group;
|
||||
|
@ -18,7 +18,6 @@ let
|
||||
''}
|
||||
state_file "${cfg.dataDir}/state"
|
||||
sticker_file "${cfg.dataDir}/sticker.sql"
|
||||
log_file "syslog"
|
||||
user "${cfg.user}"
|
||||
group "${cfg.group}"
|
||||
|
||||
|
@ -66,7 +66,8 @@ in {
|
||||
if cfg.user == "roon-server" then {
|
||||
isSystemUser = true;
|
||||
description = "Roon Server user";
|
||||
groups = [ cfg.group "audio" ];
|
||||
group = cfg.group;
|
||||
extraGroups = [ "audio" ];
|
||||
}
|
||||
else {};
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
with lib;
|
||||
|
||||
let
|
||||
version = "1.5.0";
|
||||
version = "1.6.4";
|
||||
cfg = config.services.kubernetes.addons.dns;
|
||||
ports = {
|
||||
dns = 10053;
|
||||
@ -55,9 +55,9 @@ in {
|
||||
type = types.attrs;
|
||||
default = {
|
||||
imageName = "coredns/coredns";
|
||||
imageDigest = "sha256:e83beb5e43f8513fa735e77ffc5859640baea30a882a11cc75c4c3244a737d3c";
|
||||
imageDigest = "sha256:493ee88e1a92abebac67cbd4b5658b4730e0f33512461442d8d9214ea6734a9b";
|
||||
finalImageTag = version;
|
||||
sha256 = "15sbmhrxjxidj0j0cccn1qxpg6al175w43m6ngspl0mc132zqc9q";
|
||||
sha256 = "0fm9zdjavpf5hni8g7fkdd3csjbhd7n7py7llxjc66sbii087028";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -68,7 +68,7 @@ in {
|
||||
|
||||
services.kubernetes.addonManager.bootstrapAddons = {
|
||||
coredns-cr = {
|
||||
apiVersion = "rbac.authorization.k8s.io/v1beta1";
|
||||
apiVersion = "rbac.authorization.k8s.io/v1";
|
||||
kind = "ClusterRole";
|
||||
metadata = {
|
||||
labels = {
|
||||
@ -94,7 +94,7 @@ in {
|
||||
};
|
||||
|
||||
coredns-crb = {
|
||||
apiVersion = "rbac.authorization.k8s.io/v1beta1";
|
||||
apiVersion = "rbac.authorization.k8s.io/v1";
|
||||
kind = "ClusterRoleBinding";
|
||||
metadata = {
|
||||
annotations = {
|
||||
@ -170,7 +170,7 @@ in {
|
||||
};
|
||||
|
||||
coredns-deploy = {
|
||||
apiVersion = "extensions/v1beta1";
|
||||
apiVersion = "apps/v1";
|
||||
kind = "Deployment";
|
||||
metadata = {
|
||||
labels = {
|
||||
|
@ -40,6 +40,7 @@ in
|
||||
cni.config = mkDefault [{
|
||||
name = "mynet";
|
||||
type = "flannel";
|
||||
cniVersion = "0.3.1";
|
||||
delegate = {
|
||||
isDefaultGateway = true;
|
||||
bridge = "docker0";
|
||||
|
@ -92,7 +92,7 @@ in
|
||||
default = [];
|
||||
example = literalExample ''
|
||||
[{
|
||||
"cniVersion": "0.2.0",
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "mynet",
|
||||
"type": "bridge",
|
||||
"bridge": "cni0",
|
||||
@ -106,7 +106,7 @@ in
|
||||
]
|
||||
}
|
||||
} {
|
||||
"cniVersion": "0.2.0",
|
||||
"cniVersion": "0.3.1",
|
||||
"type": "loopback"
|
||||
}]
|
||||
'';
|
||||
|
@ -31,6 +31,12 @@ in
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
description = "Kubernetes proxy hostname override.";
|
||||
default = config.networking.hostName;
|
||||
type = str;
|
||||
};
|
||||
|
||||
kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes proxy";
|
||||
|
||||
verbosity = mkOption {
|
||||
@ -59,6 +65,7 @@ in
|
||||
"--cluster-cidr=${top.clusterCidr}"} \
|
||||
${optionalString (cfg.featureGates != [])
|
||||
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
|
||||
--hostname-override=${cfg.hostname} \
|
||||
--kubeconfig=${top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig} \
|
||||
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
|
||||
${cfg.extraOpts}
|
||||
@ -69,6 +76,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.kubernetes.proxy.hostname = with config.networking; mkDefault hostName;
|
||||
|
||||
services.kubernetes.pki.certs = {
|
||||
kubeProxyClient = top.lib.mkCert {
|
||||
name = "kube-proxy-client";
|
||||
|
@ -18,7 +18,7 @@ let
|
||||
${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
|
||||
${toString (map (x: "NodeName=${x}\n") cfg.nodeName)}
|
||||
${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)}
|
||||
PlugStackConfig=${plugStackConfig}
|
||||
PlugStackConfig=${plugStackConfig}/plugstack.conf
|
||||
ProctrackType=${cfg.procTrackType}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
@ -39,6 +39,8 @@ let
|
||||
DbdHost=${cfg.dbdserver.dbdHost}
|
||||
SlurmUser=${cfg.user}
|
||||
StorageType=accounting_storage/mysql
|
||||
StorageUser=${cfg.dbdserver.storageUser}
|
||||
${optionalString (cfg.dbdserver.storagePass != null) "StoragePass=${cfg.dbdserver.storagePass}"}
|
||||
${cfg.dbdserver.extraConfig}
|
||||
'';
|
||||
|
||||
@ -48,7 +50,6 @@ let
|
||||
name = "etc-slurm";
|
||||
paths = [ configFile cgroupConfig plugStackConfig ] ++ cfg.extraConfigPaths;
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
@ -86,6 +87,37 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
storageUser = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
description = ''
|
||||
Database user name.
|
||||
'';
|
||||
};
|
||||
|
||||
storagePass = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Database password. Note that this password will be publicable
|
||||
readable in the nix store. Use <option>configFile</option>
|
||||
to store the and config file and password outside the nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to <literal>slurmdbd.conf</literal>. The password for the database connection
|
||||
is stored in the config file. Use this option to specfify a path
|
||||
outside the nix store. If this option is unset a configuration file
|
||||
will be generated. See also:
|
||||
<citerefentry><refentrytitle>slurmdbd.conf</refentrytitle>
|
||||
<manvolnum>8</manvolnum></citerefentry>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
@ -112,7 +144,7 @@ in
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.slurm;
|
||||
default = pkgs.slurm.override { enableX11 = ! cfg.enableSrunX11; };
|
||||
defaultText = "pkgs.slurm";
|
||||
example = literalExample "pkgs.slurm-full";
|
||||
description = ''
|
||||
@ -178,9 +210,14 @@ in
|
||||
If enabled srun will accept the option "--x11" to allow for X11 forwarding
|
||||
from within an interactive session or a batch job. This activates the
|
||||
slurm-spank-x11 module. Note that this option also enables
|
||||
'services.openssh.forwardX11' on the client.
|
||||
<option>services.openssh.forwardX11</option> on the client.
|
||||
|
||||
This option requires slurm to be compiled without native X11 support.
|
||||
The default behavior is to re-compile the slurm package with native X11
|
||||
support disabled if this option is set to true.
|
||||
|
||||
To use the native X11 support add <literal>PrologFlags=X11</literal> in <option>extraConfig</option>.
|
||||
Note that this method will only work RSA SSH host keys.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -356,7 +393,11 @@ in
|
||||
requires = [ "munged.service" "mysql.service" ];
|
||||
|
||||
# slurm strips the last component off the path
|
||||
environment.SLURM_CONF = "${slurmdbdConf}/slurm.conf";
|
||||
environment.SLURM_CONF =
|
||||
if (cfg.dbdserver.configFile == null) then
|
||||
"${slurmdbdConf}/slurm.conf"
|
||||
else
|
||||
cfg.dbdserver.configFile;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
|
@ -8,15 +8,11 @@ let
|
||||
|
||||
mysql = cfg.package;
|
||||
|
||||
isMariaDB =
|
||||
let
|
||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
||||
in pName mysql == pName pkgs.mariadb;
|
||||
isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb;
|
||||
|
||||
isMysqlAtLeast57 =
|
||||
let
|
||||
pName = _p: (builtins.parseDrvName (_p.name)).name;
|
||||
in (pName mysql == pName pkgs.mysql57)
|
||||
&& ((builtins.compareVersions mysql.version "5.7") >= 0);
|
||||
(lib.getName mysql == lib.getName pkgs.mysql57)
|
||||
&& (builtins.compareVersions mysql.version "5.7" >= 0);
|
||||
|
||||
mysqldOptions =
|
||||
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}";
|
||||
|
23
nixos/modules/services/desktops/neard.nix
Normal file
23
nixos/modules/services/desktops/neard.nix
Normal file
@ -0,0 +1,23 @@
|
||||
# neard service.
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
###### interface
|
||||
options = {
|
||||
services.neard = {
|
||||
enable = mkEnableOption "neard, NFC daemon";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
config = mkIf config.services.neard.enable {
|
||||
environment.systemPackages = [ pkgs.neard ];
|
||||
|
||||
services.dbus.packages = [ pkgs.neard ];
|
||||
|
||||
systemd.packages = [ pkgs.neard ];
|
||||
};
|
||||
}
|
@ -7,12 +7,17 @@ with lib;
|
||||
let
|
||||
|
||||
cfg = config.services.tumbler;
|
||||
tumbler = cfg.package;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule
|
||||
[ "services" "tumbler" "package" ]
|
||||
"")
|
||||
];
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
@ -21,13 +26,6 @@ in
|
||||
|
||||
enable = mkEnableOption "Tumbler, A D-Bus thumbnailer service";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.xfce4-14.tumbler;
|
||||
description = "Which tumbler package to use";
|
||||
example = pkgs.xfce4-12.tumbler;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
@ -37,11 +35,11 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [
|
||||
environment.systemPackages = with pkgs.xfce; [
|
||||
tumbler
|
||||
];
|
||||
|
||||
services.dbus.packages = [
|
||||
services.dbus.packages = with pkgs.xfce; [
|
||||
tumbler
|
||||
];
|
||||
|
||||
|
47
nixos/modules/services/development/lorri.nix
Normal file
47
nixos/modules/services/development/lorri.nix
Normal file
@ -0,0 +1,47 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.lorri;
|
||||
socketPath = "lorri/daemon.socket";
|
||||
in {
|
||||
options = {
|
||||
services.lorri = {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Enables the daemon for `lorri`, a nix-shell replacement for project
|
||||
development. The socket-activated daemon starts on the first request
|
||||
issued by the `lorri` command.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.user.sockets.lorri = {
|
||||
description = "Socket for Lorri Daemon";
|
||||
wantedBy = [ "sockets.target" ];
|
||||
socketConfig = {
|
||||
ListenStream = "%t/${socketPath}";
|
||||
RuntimeDirectory = "lorri";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.services.lorri = {
|
||||
description = "Lorri Daemon";
|
||||
requires = [ "lorri.socket" ];
|
||||
after = [ "lorri.socket" ];
|
||||
path = with pkgs; [ config.nix.package gnutar gzip ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.lorri}/bin/lorri daemon";
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = "read-only";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.lorri ];
|
||||
};
|
||||
}
|
@ -43,7 +43,7 @@ in
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "openarena";
|
||||
ExecStart = "${pkgs.openarena}/bin/openarena-server +set fs_basepath ${pkgs.openarena}/openarena-0.8.8 +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
|
||||
ExecStart = "${pkgs.openarena}/bin/oa_ded +set fs_basepath ${pkgs.openarena}/openarena-0.8.8 +set fs_homepath /var/lib/openarena ${concatStringsSep " " cfg.extraFlags}";
|
||||
Restart = "on-failure";
|
||||
|
||||
# Hardening
|
||||
|
@ -36,17 +36,25 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = with types; attrsOf (attrsOf (oneOf [ bool int str ]));
|
||||
example = {
|
||||
General = {
|
||||
ControllerMode = "bredr";
|
||||
};
|
||||
};
|
||||
description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf).";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
type = with types; nullOr lines;
|
||||
default = null;
|
||||
example = ''
|
||||
[General]
|
||||
ControllerMode = bredr
|
||||
'';
|
||||
description = ''
|
||||
Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
|
||||
|
||||
NOTE: We already include [Policy], so any configuration under the Policy group should come first.
|
||||
'';
|
||||
};
|
||||
};
|
||||
@ -56,16 +64,18 @@ in {
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
warnings = optional (cfg.extraConfig != null) "hardware.bluetooth.`extraConfig` is deprecated, please use hardware.bluetooth.`config`.";
|
||||
|
||||
environment.systemPackages = [ bluez-bluetooth pkgs.openobex pkgs.obexftp ];
|
||||
hardware.bluetooth.config = {
|
||||
Policy = {
|
||||
AutoEnable = mkDefault cfg.powerOnBoot;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ bluez-bluetooth ];
|
||||
|
||||
environment.etc = singleton {
|
||||
source = pkgs.writeText "main.conf" ''
|
||||
[Policy]
|
||||
AutoEnable=${lib.boolToString cfg.powerOnBoot}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
source = pkgs.writeText "main.conf" (generators.toINI { } cfg.config + optionalString (cfg.extraConfig != null) cfg.extraConfig);
|
||||
target = "bluetooth/main.conf";
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ in {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable test remote. This is used by
|
||||
<link xlink:href="https://github.com/hughsie/fwupd/blob/master/data/installed-tests/README.md">installed tests</link>.
|
||||
<link xlink:href="https://github.com/fwupd/fwupd/blob/master/data/installed-tests/README.md">installed tests</link>.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -115,10 +115,6 @@ in {
|
||||
services.udev.packages = [ cfg.package ];
|
||||
|
||||
systemd.packages = [ cfg.package ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/fwupd 0755 root root -"
|
||||
];
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
@ -37,7 +37,7 @@ in
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable the TLP daemon.";
|
||||
description = "Whether to enable the TLP power management daemon.";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
|
@ -25,6 +25,13 @@ in
|
||||
description = "The port address of the http server.";
|
||||
};
|
||||
|
||||
http.path = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = "Prefix to all HTTP paths.";
|
||||
example = "/mailcatcher";
|
||||
};
|
||||
|
||||
smtp.ip = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
@ -53,7 +60,7 @@ in
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
ExecStart = "${pkgs.mailcatcher}/bin/mailcatcher --foreground --no-quit --http-ip ${cfg.http.ip} --http-port ${toString cfg.http.port} --smtp-ip ${cfg.smtp.ip} --smtp-port ${toString cfg.smtp.port}";
|
||||
ExecStart = "${pkgs.mailcatcher}/bin/mailcatcher --foreground --no-quit --http-ip ${cfg.http.ip} --http-port ${toString cfg.http.port} --smtp-ip ${cfg.smtp.ip} --smtp-port ${toString cfg.smtp.port}" + optionalString (cfg.http.path != null) " --http-path ${cfg.http.path}";
|
||||
AmbientCapabilities = optionalString (cfg.http.port < 1024 || cfg.smtp.port < 1024) "cap_net_bind_service";
|
||||
};
|
||||
};
|
||||
|
@ -631,6 +631,14 @@ in
|
||||
setgid = true;
|
||||
};
|
||||
|
||||
security.wrappers.mailq = {
|
||||
program = "mailq";
|
||||
source = "${pkgs.postfix}/bin/mailq";
|
||||
group = setgidGroup;
|
||||
setuid = false;
|
||||
setgid = true;
|
||||
};
|
||||
|
||||
security.wrappers.postqueue = {
|
||||
program = "postqueue";
|
||||
source = "${pkgs.postfix}/bin/postqueue";
|
||||
|
@ -160,7 +160,7 @@ in
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql postgres -c "create role ${cfg.database.username} with login password '${cfg.database.password}'";
|
||||
${pkgs.sudo}/bin/sudo -u ${pgSuperUser} psql postgres -c "create database ${cfg.database.dbname} with owner ${cfg.database.username}";
|
||||
fi
|
||||
PGPASSWORD=${cfg.database.password} ${pkgs.postgresql}/bin/psql -U ${cfg.database.username} \
|
||||
PGPASSWORD="${cfg.database.password}" ${pkgs.postgresql}/bin/psql -U ${cfg.database.username} \
|
||||
-f ${cfg.package}/SQL/postgres.initial.sql \
|
||||
-h ${cfg.database.host} ${cfg.database.dbname}
|
||||
touch /var/lib/roundcube/db-created
|
||||
|
@ -60,7 +60,7 @@ let
|
||||
};
|
||||
type = mkOption {
|
||||
type = types.nullOr (types.enum [
|
||||
"normal" "controller" "fuzzy_storage" "rspamd_proxy" "lua" "proxy"
|
||||
"normal" "controller" "fuzzy" "rspamd_proxy" "lua" "proxy"
|
||||
]);
|
||||
description = ''
|
||||
The type of this worker. The type <literal>proxy</literal> is
|
||||
|
@ -44,7 +44,8 @@ in
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
ExecStart = "${pkg}/bin/beanstalkd -l ${cfg.listen.address} -p ${toString cfg.listen.port}";
|
||||
ExecStart = "${pkg}/bin/beanstalkd -l ${cfg.listen.address} -p ${toString cfg.listen.port} -b $STATE_DIRECTORY";
|
||||
StateDirectory = "beanstalkd";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -394,6 +394,28 @@ in
|
||||
WorkingDirectory = cfg.stateDir;
|
||||
ExecStart = "${gitea.bin}/bin/gitea web";
|
||||
Restart = "always";
|
||||
|
||||
# Filesystem
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
ReadWritePaths = cfg.stateDir;
|
||||
# Caps
|
||||
CapabilityBoundingSet = "";
|
||||
NoNewPrivileges = true;
|
||||
# Misc.
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
PrivateMounts = true;
|
||||
PrivateUsers = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
SystemCallFilter = "~@chown @clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap";
|
||||
SystemCallArchitectures = "native";
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
};
|
||||
|
||||
environment = {
|
||||
|
@ -43,7 +43,7 @@ let
|
||||
|
||||
ANALYTICS_REPORTING_ENABLED = boolToString cfg.analytics.reporting.enable;
|
||||
|
||||
SMTP_ENABLE = boolToString cfg.smtp.enable;
|
||||
SMTP_ENABLED = boolToString cfg.smtp.enable;
|
||||
SMTP_HOST = cfg.smtp.host;
|
||||
SMTP_USER = cfg.smtp.user;
|
||||
SMTP_PASSWORD = cfg.smtp.password;
|
||||
|
@ -1,91 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with builtins;
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.osquery;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
services.osquery = {
|
||||
|
||||
enable = mkEnableOption "osquery";
|
||||
|
||||
loggerPath = mkOption {
|
||||
type = types.path;
|
||||
description = "Base directory used for logging.";
|
||||
default = "/var/log/osquery";
|
||||
};
|
||||
|
||||
pidfile = mkOption {
|
||||
type = types.path;
|
||||
description = "Path used for pid file.";
|
||||
default = "/var/osquery/osqueryd.pidfile";
|
||||
};
|
||||
|
||||
utc = mkOption {
|
||||
type = types.bool;
|
||||
description = "Attempt to convert all UNIX calendar times to UTC.";
|
||||
default = true;
|
||||
};
|
||||
|
||||
databasePath = mkOption {
|
||||
type = types.path;
|
||||
description = "Path used for database file.";
|
||||
default = "/var/osquery/osquery.db";
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs // {
|
||||
merge = loc: foldl' (res: def: recursiveUpdate res def.value) {};
|
||||
};
|
||||
description = "Extra config to be recursively merged into the JSON config file.";
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.osquery ];
|
||||
|
||||
environment.etc."osquery/osquery.conf".text = toJSON (
|
||||
recursiveUpdate {
|
||||
options = {
|
||||
config_plugin = "filesystem";
|
||||
logger_plugin = "filesystem";
|
||||
logger_path = cfg.loggerPath;
|
||||
database_path = cfg.databasePath;
|
||||
utc = cfg.utc;
|
||||
};
|
||||
} cfg.extraConfig
|
||||
);
|
||||
|
||||
systemd.services.osqueryd = {
|
||||
description = "The osquery Daemon";
|
||||
after = [ "network.target" "syslog.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.osquery ];
|
||||
preStart = ''
|
||||
mkdir -p ${escapeShellArg cfg.loggerPath}
|
||||
mkdir -p "$(dirname ${escapeShellArg cfg.pidfile})"
|
||||
mkdir -p "$(dirname ${escapeShellArg cfg.databasePath})"
|
||||
'';
|
||||
serviceConfig = {
|
||||
TimeoutStartSec = "infinity";
|
||||
ExecStart = "${pkgs.osquery}/bin/osqueryd --logger_path ${escapeShellArg cfg.loggerPath} --pidfile ${escapeShellArg cfg.pidfile} --database_path ${escapeShellArg cfg.databasePath}";
|
||||
KillMode = "process";
|
||||
KillSignal = "SIGTERM";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -197,6 +197,9 @@ in
|
||||
services.prometheus.exporters.minio.minioAccessSecret = mkDefault config.services.minio.secretKey;
|
||||
})] ++ [(mkIf config.services.rspamd.enable {
|
||||
services.prometheus.exporters.rspamd.url = mkDefault "http://localhost:11334/stat";
|
||||
})] ++ [(mkIf config.services.nginx.enable {
|
||||
systemd.services.prometheus-nginx-exporter.after = [ "nginx.service" ];
|
||||
systemd.services.prometheus-nginx-exporter.requires = [ "nginx.service" ];
|
||||
})] ++ (mapAttrsToList (name: conf:
|
||||
mkExporterConf {
|
||||
inherit name;
|
||||
|
@ -1,357 +0,0 @@
|
||||
{ config, lib, pkgs, ...} :
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.beegfs;
|
||||
|
||||
# functions for the generations of config files
|
||||
|
||||
configMgmtd = name: cfg: pkgs.writeText "mgmt-${name}.conf" ''
|
||||
storeMgmtdDirectory = ${cfg.mgmtd.storeDir}
|
||||
storeAllowFirstRunInit = false
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
connPortShift = ${toString cfg.connPortShift}
|
||||
|
||||
${cfg.mgmtd.extraConfig}
|
||||
'';
|
||||
|
||||
configAdmon = name: cfg: pkgs.writeText "admon-${name}.conf" ''
|
||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
connPortShift = ${toString cfg.connPortShift}
|
||||
|
||||
${cfg.admon.extraConfig}
|
||||
'';
|
||||
|
||||
configMeta = name: cfg: pkgs.writeText "meta-${name}.conf" ''
|
||||
storeMetaDirectory = ${cfg.meta.storeDir}
|
||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
connPortShift = ${toString cfg.connPortShift}
|
||||
storeAllowFirstRunInit = false
|
||||
|
||||
${cfg.meta.extraConfig}
|
||||
'';
|
||||
|
||||
configStorage = name: cfg: pkgs.writeText "storage-${name}.conf" ''
|
||||
storeStorageDirectory = ${cfg.storage.storeDir}
|
||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
connPortShift = ${toString cfg.connPortShift}
|
||||
storeAllowFirstRunInit = false
|
||||
|
||||
${cfg.storage.extraConfig}
|
||||
'';
|
||||
|
||||
configHelperd = name: cfg: pkgs.writeText "helperd-${name}.conf" ''
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
${cfg.helperd.extraConfig}
|
||||
'';
|
||||
|
||||
configClientFilename = name : "/etc/beegfs/client-${name}.conf";
|
||||
|
||||
configClient = name: cfg: ''
|
||||
sysMgmtdHost = ${cfg.mgmtdHost}
|
||||
connAuthFile = ${cfg.connAuthFile}
|
||||
connPortShift = ${toString cfg.connPortShift}
|
||||
|
||||
${cfg.client.extraConfig}
|
||||
'';
|
||||
|
||||
serviceList = [
|
||||
{ service = "admon"; cfgFile = configAdmon; }
|
||||
{ service = "meta"; cfgFile = configMeta; }
|
||||
{ service = "mgmtd"; cfgFile = configMgmtd; }
|
||||
{ service = "storage"; cfgFile = configStorage; }
|
||||
];
|
||||
|
||||
# functions to generate systemd.service entries
|
||||
|
||||
systemdEntry = service: cfgFile: (mapAttrs' ( name: cfg:
|
||||
(nameValuePair "beegfs-${service}-${name}" (mkIf cfg.${service}.enable {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
serviceConfig = rec {
|
||||
ExecStart = ''
|
||||
${pkgs.beegfs}/bin/beegfs-${service} \
|
||||
cfgFile=${cfgFile name cfg} \
|
||||
pidFile=${PIDFile}
|
||||
'';
|
||||
PIDFile = "/run/beegfs-${service}-${name}.pid";
|
||||
TimeoutStopSec = "300";
|
||||
};
|
||||
}))) cfg);
|
||||
|
||||
systemdHelperd = mapAttrs' ( name: cfg:
|
||||
(nameValuePair "beegfs-helperd-${name}" (mkIf cfg.client.enable {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
serviceConfig = rec {
|
||||
ExecStart = ''
|
||||
${pkgs.beegfs}/bin/beegfs-helperd \
|
||||
cfgFile=${configHelperd name cfg} \
|
||||
pidFile=${PIDFile}
|
||||
'';
|
||||
PIDFile = "/run/beegfs-helperd-${name}.pid";
|
||||
TimeoutStopSec = "300";
|
||||
};
|
||||
}))) cfg;
|
||||
|
||||
# wrappers to beegfs tools. Avoid typing path of config files
|
||||
utilWrappers = mapAttrsToList ( name: cfg:
|
||||
( pkgs.runCommand "beegfs-utils-${name}" {
|
||||
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-check-servers \
|
||||
$out/bin/beegfs-check-servers-${name} \
|
||||
--add-flags "-c ${configClientFilename name}" \
|
||||
--prefix PATH : ${lib.makeBinPath [ pkgs.beegfs ]}
|
||||
|
||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
|
||||
$out/bin/beegfs-ctl-${name} \
|
||||
--add-flags "--cfgFile=${configClientFilename name}"
|
||||
|
||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
|
||||
$out/bin/beegfs-df-${name} \
|
||||
--add-flags "--cfgFile=${configClientFilename name}" \
|
||||
--add-flags --listtargets \
|
||||
--add-flags --hidenodeid \
|
||||
--add-flags --pools \
|
||||
--add-flags --spaceinfo
|
||||
|
||||
makeWrapper ${pkgs.beegfs}/bin/beegfs-fsck \
|
||||
$out/bin/beegfs-fsck-${name} \
|
||||
--add-flags "--cfgFile=${configClientFilename name}"
|
||||
''
|
||||
)) cfg;
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
services.beegfsEnable = mkEnableOption "BeeGFS";
|
||||
|
||||
services.beegfs = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
BeeGFS configurations. Every mount point requires a separate configuration.
|
||||
'';
|
||||
type = with types; attrsOf (submodule ({ ... } : {
|
||||
options = {
|
||||
mgmtdHost = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
example = "master";
|
||||
description = ''Hostname of managament host.'';
|
||||
};
|
||||
|
||||
connAuthFile = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "/etc/my.key";
|
||||
description = "File containing shared secret authentication.";
|
||||
};
|
||||
|
||||
connPortShift = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
example = 5;
|
||||
description = ''
|
||||
For each additional beegfs configuration shift all
|
||||
service TCP/UDP ports by at least 5.
|
||||
'';
|
||||
};
|
||||
|
||||
client = {
|
||||
enable = mkEnableOption "BeeGFS client";
|
||||
|
||||
mount = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Create fstab entry automatically";
|
||||
};
|
||||
|
||||
mountPoint = mkOption {
|
||||
type = types.str;
|
||||
default = "/run/beegfs";
|
||||
description = ''
|
||||
Mount point under which the beegfs filesytem should be mounted.
|
||||
If mounted manually the mount option specifing the config file is needed:
|
||||
cfgFile=/etc/beegfs/beegfs-client-<name>.conf
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional lines for beegfs-client.conf.
|
||||
See documentation for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
helperd = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable the BeeGFS helperd.
|
||||
The helpered is need for logging purposes on the client.
|
||||
Disabling <literal>helperd</literal> allows for runing the client
|
||||
with <literal>allowUnfree = false</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional lines for beegfs-helperd.conf. See documentation
|
||||
for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
mgmtd = {
|
||||
enable = mkEnableOption "BeeGFS mgmtd daemon";
|
||||
|
||||
storeDir = mkOption {
|
||||
type = types.path;
|
||||
default = null;
|
||||
example = "/data/beegfs-mgmtd";
|
||||
description = ''
|
||||
Data directory for mgmtd.
|
||||
Must not be shared with other beegfs daemons.
|
||||
This directory must exist and it must be initialized
|
||||
with beegfs-setup-mgmtd, e.g. "beegfs-setup-mgmtd -C -p <storeDir>"
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional lines for beegfs-mgmtd.conf. See documentation
|
||||
for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
admon = {
|
||||
enable = mkEnableOption "BeeGFS admon daemon";
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional lines for beegfs-admon.conf. See documentation
|
||||
for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
enable = mkEnableOption "BeeGFS meta data daemon";
|
||||
|
||||
storeDir = mkOption {
|
||||
type = types.path;
|
||||
default = null;
|
||||
example = "/data/beegfs-meta";
|
||||
description = ''
|
||||
Data directory for meta data service.
|
||||
Must not be shared with other beegfs daemons.
|
||||
The underlying filesystem must be mounted with xattr turned on.
|
||||
This directory must exist and it must be initialized
|
||||
with beegfs-setup-meta, e.g.
|
||||
"beegfs-setup-meta -C -s <serviceID> -p <storeDir>"
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional lines for beegfs-meta.conf. See documentation
|
||||
for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
storage = {
|
||||
enable = mkEnableOption "BeeGFS storage daemon";
|
||||
|
||||
storeDir = mkOption {
|
||||
type = types.path;
|
||||
default = null;
|
||||
example = "/data/beegfs-storage";
|
||||
description = ''
|
||||
Data directories for storage service.
|
||||
Must not be shared with other beegfs daemons.
|
||||
The underlying filesystem must be mounted with xattr turned on.
|
||||
This directory must exist and it must be initialized
|
||||
with beegfs-setup-storage, e.g.
|
||||
"beegfs-setup-storage -C -s <serviceID> -i <storageTargetID> -p <storeDir>"
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Addional lines for beegfs-storage.conf. See documentation
|
||||
for further details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config =
|
||||
mkIf config.services.beegfsEnable {
|
||||
|
||||
environment.systemPackages = utilWrappers;
|
||||
|
||||
# Put the client.conf files in /etc since they are needed
|
||||
# by the commandline tools
|
||||
environment.etc = mapAttrs' ( name: cfg:
|
||||
(nameValuePair "beegfs/client-${name}.conf" (mkIf (cfg.client.enable)
|
||||
{
|
||||
enable = true;
|
||||
text = configClient name cfg;
|
||||
}))) cfg;
|
||||
|
||||
# Kernel module, we need it only once per host.
|
||||
boot = mkIf (
|
||||
foldr (a: b: a || b) false
|
||||
(map (x: x.client.enable) (collect (x: x ? client) cfg)))
|
||||
{
|
||||
kernelModules = [ "beegfs" ];
|
||||
extraModulePackages = [ pkgs.linuxPackages.beegfs-module ];
|
||||
};
|
||||
|
||||
# generate fstab entries
|
||||
fileSystems = mapAttrs' (name: cfg:
|
||||
(nameValuePair cfg.client.mountPoint (optionalAttrs cfg.client.mount (mkIf cfg.client.enable {
|
||||
device = "beegfs_nodev";
|
||||
fsType = "beegfs";
|
||||
mountPoint = cfg.client.mountPoint;
|
||||
options = [ "cfgFile=${configClientFilename name}" "_netdev" ];
|
||||
})))) cfg;
|
||||
|
||||
# generate systemd services
|
||||
systemd.services = systemdHelperd //
|
||||
foldr (a: b: a // b) {}
|
||||
(map (x: systemdEntry x.service x.cfgFile) serviceList);
|
||||
};
|
||||
}
|
@ -9,12 +9,14 @@ let
|
||||
expandCamelCase = replaceStrings upperChars (map (s: " ${s}") lowerChars);
|
||||
expandCamelCaseAttrs = mapAttrs' (name: value: nameValuePair (expandCamelCase name) value);
|
||||
|
||||
makeServices = (daemonType: daemonIds: extraServiceConfig:
|
||||
makeServices = (daemonType: daemonIds:
|
||||
mkMerge (map (daemonId:
|
||||
{ "ceph-${daemonType}-${daemonId}" = makeService daemonType daemonId cfg.global.clusterName pkgs.ceph extraServiceConfig; })
|
||||
{ "ceph-${daemonType}-${daemonId}" = makeService daemonType daemonId cfg.global.clusterName pkgs.ceph; })
|
||||
daemonIds));
|
||||
|
||||
makeService = (daemonType: daemonId: clusterName: ceph: extraServiceConfig: {
|
||||
makeService = (daemonType: daemonId: clusterName: ceph:
|
||||
let
|
||||
stateDirectory = "ceph/${if daemonType == "rgw" then "radosgw" else daemonType}/${clusterName}-${daemonId}"; in {
|
||||
enable = true;
|
||||
description = "Ceph ${builtins.replaceStrings lowerChars upperChars daemonType} daemon ${daemonId}";
|
||||
after = [ "network-online.target" "time-sync.target" ] ++ optional (daemonType == "osd") "ceph-mon.target";
|
||||
@ -22,6 +24,11 @@ let
|
||||
partOf = [ "ceph-${daemonType}.target" ];
|
||||
wantedBy = [ "ceph-${daemonType}.target" ];
|
||||
|
||||
path = [ pkgs.getopt ];
|
||||
|
||||
# Don't start services that are not yet initialized
|
||||
unitConfig.ConditionPathExists = "/var/lib/${stateDirectory}/keyring";
|
||||
|
||||
serviceConfig = {
|
||||
LimitNOFILE = 1048576;
|
||||
LimitNPROC = 1048576;
|
||||
@ -34,22 +41,22 @@ let
|
||||
Restart = "on-failure";
|
||||
StartLimitBurst = "5";
|
||||
StartLimitInterval = "30min";
|
||||
StateDirectory = stateDirectory;
|
||||
User = "ceph";
|
||||
Group = if daemonType == "osd" then "disk" else "ceph";
|
||||
ExecStart = ''${ceph.out}/bin/${if daemonType == "rgw" then "radosgw" else "ceph-${daemonType}"} \
|
||||
-f --cluster ${clusterName} --id ${daemonId} --setuser ceph \
|
||||
--setgroup ${if daemonType == "osd" then "disk" else "ceph"}'';
|
||||
} // extraServiceConfig
|
||||
// optionalAttrs (daemonType == "osd") { ExecStartPre = ''${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh \
|
||||
--id ${daemonId} --cluster ${clusterName}''; };
|
||||
} // optionalAttrs (builtins.elem daemonType [ "mds" "mon" "rgw" "mgr" ]) {
|
||||
preStart = ''
|
||||
daemonPath="/var/lib/ceph/${if daemonType == "rgw" then "radosgw" else daemonType}/${clusterName}-${daemonId}"
|
||||
if [ ! -d $daemonPath ]; then
|
||||
mkdir -m 755 -p $daemonPath
|
||||
chown -R ceph:ceph $daemonPath
|
||||
fi
|
||||
'';
|
||||
} // optionalAttrs (daemonType == "osd") { path = [ pkgs.getopt ]; }
|
||||
);
|
||||
-f --cluster ${clusterName} --id ${daemonId}'';
|
||||
} // optionalAttrs (daemonType == "osd") {
|
||||
ExecStartPre = ''${ceph.lib}/libexec/ceph/ceph-osd-prestart.sh --id ${daemonId} --cluster ${clusterName}'';
|
||||
StartLimitBurst = "30";
|
||||
RestartSec = "20s";
|
||||
PrivateDevices = "no"; # osd needs disk access
|
||||
} // optionalAttrs ( daemonType == "mon") {
|
||||
RestartSec = "10";
|
||||
} // optionalAttrs (lib.elem daemonType ["mgr" "mds"]) {
|
||||
StartLimitBurst = "3";
|
||||
};
|
||||
});
|
||||
|
||||
makeTarget = (daemonType:
|
||||
{
|
||||
@ -58,6 +65,7 @@ let
|
||||
partOf = [ "ceph.target" ];
|
||||
wantedBy = [ "ceph.target" ];
|
||||
before = [ "ceph.target" ];
|
||||
unitConfig.StopWhenUnneeded = true;
|
||||
};
|
||||
}
|
||||
);
|
||||
@ -377,22 +385,22 @@ in
|
||||
|
||||
systemd.services = let
|
||||
services = []
|
||||
++ optional cfg.mon.enable (makeServices "mon" cfg.mon.daemons { RestartSec = "10"; })
|
||||
++ optional cfg.mds.enable (makeServices "mds" cfg.mds.daemons { StartLimitBurst = "3"; })
|
||||
++ optional cfg.osd.enable (makeServices "osd" cfg.osd.daemons { StartLimitBurst = "30";
|
||||
RestartSec = "20s";
|
||||
PrivateDevices = "no"; # osd needs disk access
|
||||
})
|
||||
++ optional cfg.rgw.enable (makeServices "rgw" cfg.rgw.daemons { })
|
||||
++ optional cfg.mgr.enable (makeServices "mgr" cfg.mgr.daemons { StartLimitBurst = "3"; });
|
||||
++ optional cfg.mon.enable (makeServices "mon" cfg.mon.daemons)
|
||||
++ optional cfg.mds.enable (makeServices "mds" cfg.mds.daemons)
|
||||
++ optional cfg.osd.enable (makeServices "osd" cfg.osd.daemons)
|
||||
++ optional cfg.rgw.enable (makeServices "rgw" cfg.rgw.daemons)
|
||||
++ optional cfg.mgr.enable (makeServices "mgr" cfg.mgr.daemons);
|
||||
in
|
||||
mkMerge services;
|
||||
|
||||
systemd.targets = let
|
||||
targets = [
|
||||
{ ceph = { description = "Ceph target allowing to start/stop all ceph service instances at once";
|
||||
wantedBy = [ "multi-user.target" ]; }; }
|
||||
] ++ optional cfg.mon.enable (makeTarget "mon")
|
||||
{ ceph = {
|
||||
description = "Ceph target allowing to start/stop all ceph service instances at once";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
unitConfig.StopWhenUnneeded = true;
|
||||
}; } ]
|
||||
++ optional cfg.mon.enable (makeTarget "mon")
|
||||
++ optional cfg.mds.enable (makeTarget "mds")
|
||||
++ optional cfg.osd.enable (makeTarget "osd")
|
||||
++ optional cfg.rgw.enable (makeTarget "rgw")
|
||||
@ -401,7 +409,11 @@ in
|
||||
mkMerge targets;
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /etc/ceph - ceph ceph - -"
|
||||
"d /run/ceph 0770 ceph ceph -"
|
||||
];
|
||||
"d /var/lib/ceph - ceph ceph - -"]
|
||||
++ optionals cfg.mgr.enable [ "d /var/lib/ceph/mgr - ceph ceph - -"]
|
||||
++ optionals cfg.mon.enable [ "d /var/lib/ceph/mon - ceph ceph - -"]
|
||||
++ optionals cfg.osd.enable [ "d /var/lib/ceph/osd - ceph ceph - -"];
|
||||
};
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ let
|
||||
daemonService = appName: args:
|
||||
{ description = "Samba Service Daemon ${appName}";
|
||||
|
||||
after = [ "network.target" ];
|
||||
after = [ (mkIf (cfg.enableNmbd && "${appName}" == "smbd") "samba-nmbd.service") ];
|
||||
requiredBy = [ "samba.target" ];
|
||||
partOf = [ "samba.target" ];
|
||||
|
||||
@ -115,7 +115,7 @@ in
|
||||
type = types.package;
|
||||
default = pkgs.samba;
|
||||
defaultText = "pkgs.samba";
|
||||
example = literalExample "pkgs.samba3";
|
||||
example = literalExample "pkgs.samba4Full";
|
||||
description = ''
|
||||
Defines which package should be used for the samba server.
|
||||
'';
|
||||
|
@ -78,7 +78,11 @@ in
|
||||
cacheNetworks = mkOption {
|
||||
default = ["127.0.0.0/24"];
|
||||
description = "
|
||||
What networks are allowed to use us as a resolver.
|
||||
What networks are allowed to use us as a resolver. Note
|
||||
that this is for recursive queries -- all networks are
|
||||
allowed to query zones configured with the `zones` option.
|
||||
It is recommended that you limit cacheNetworks to avoid your
|
||||
server being used for DNS amplification attacks.
|
||||
";
|
||||
};
|
||||
|
||||
|
@ -177,9 +177,6 @@ in {
|
||||
NoNewPrivileges = "true";
|
||||
PrivateDevices = "true";
|
||||
MemoryDenyWriteExecute = "true";
|
||||
|
||||
# Permission for preStart
|
||||
PermissionsStartOnly = "true";
|
||||
};
|
||||
};
|
||||
users.users.${cfg.user} = {
|
||||
|
@ -4,7 +4,7 @@ with pkgs;
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking.connman;
|
||||
cfg = config.services.connman;
|
||||
configFile = pkgs.writeText "connman.conf" ''
|
||||
[General]
|
||||
NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
|
||||
@ -17,7 +17,7 @@ in {
|
||||
|
||||
options = {
|
||||
|
||||
networking.connman = {
|
||||
services.connman = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
@ -71,13 +71,13 @@ in {
|
||||
|
||||
assertions = [{
|
||||
assertion = !config.networking.useDHCP;
|
||||
message = "You can not use services.networking.connman with services.networking.useDHCP";
|
||||
message = "You can not use services.connman with networking.useDHCP";
|
||||
}{
|
||||
assertion = config.networking.wireless.enable;
|
||||
message = "You must use services.networking.connman with services.networking.wireless";
|
||||
message = "You must use services.connman with networking.wireless";
|
||||
}{
|
||||
assertion = !config.networking.networkmanager.enable;
|
||||
message = "You can not use services.networking.connman with services.networking.networkmanager";
|
||||
message = "You can not use services.connman with networking.networkmanager";
|
||||
}];
|
||||
|
||||
environment.systemPackages = [ connman ];
|
||||
|
@ -137,7 +137,7 @@ in
|
||||
];
|
||||
|
||||
services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
|
||||
forwardZones =
|
||||
forwardZonesRecurse =
|
||||
{ bit = "127.0.0.1:${toString cfg.dns.port}";
|
||||
dns = "127.0.0.1:${toString cfg.dns.port}";
|
||||
};
|
||||
|
@ -23,6 +23,8 @@ in
|
||||
type = types.int;
|
||||
description = ''
|
||||
The port the server should listen on. Will use the server's default (2022) if not specified.
|
||||
|
||||
Make sure to open this port in the firewall if necessary.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -86,4 +88,8 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ pingiun ];
|
||||
};
|
||||
}
|
||||
|
@ -90,11 +90,19 @@ in {
|
||||
};
|
||||
|
||||
forwardZones = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
DNS zones to be forwarded to other authoritative servers.
|
||||
'';
|
||||
};
|
||||
|
||||
forwardZonesRecurse = mkOption {
|
||||
type = types.attrs;
|
||||
example = { eth = "127.0.0.1:5353"; };
|
||||
default = {};
|
||||
description = ''
|
||||
DNS zones to be forwarded to other servers.
|
||||
DNS zones to be forwarded to other recursive servers.
|
||||
'';
|
||||
};
|
||||
|
||||
@ -158,7 +166,8 @@ in {
|
||||
webserver-port = cfg.api.port;
|
||||
webserver-allow-from = cfg.api.allowFrom;
|
||||
|
||||
forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
|
||||
forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
|
||||
forward-zones-recurse = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZonesRecurse;
|
||||
export-etc-hosts = cfg.exportHosts;
|
||||
dnssec = cfg.dnssecValidation;
|
||||
serve-rfc1918 = cfg.serveRFC1918;
|
||||
|
@ -18,6 +18,7 @@ let
|
||||
fsWatcherEnabled = folder.watch;
|
||||
fsWatcherDelayS = folder.watchDelay;
|
||||
ignorePerms = folder.ignorePerms;
|
||||
versioning = folder.versioning;
|
||||
}) (filterAttrs (
|
||||
_: folder:
|
||||
folder.enable
|
||||
@ -220,6 +221,69 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
versioning = mkOption {
|
||||
default = null;
|
||||
description = ''
|
||||
How to keep changed/deleted files with syncthing.
|
||||
There are 4 different types of versioning with different parameters.
|
||||
See https://docs.syncthing.net/users/versioning.html
|
||||
'';
|
||||
example = [
|
||||
{
|
||||
versioning = {
|
||||
type = "simple";
|
||||
params.keep = "10";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "trashcan";
|
||||
params.cleanoutDays = "1000";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "31536000";
|
||||
versionsPath = "/syncthing/backup";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "external";
|
||||
params.versionsPath = pkgs.writers.writeBash "backup" ''
|
||||
folderpath="$1"
|
||||
filepath="$2"
|
||||
rm -rf "$folderpath/$filepath"
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
type = with types; nullOr (submodule {
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = enum [ "external" "simple" "staggered" "trashcan" ];
|
||||
description = ''
|
||||
Type of versioning.
|
||||
See https://docs.syncthing.net/users/versioning.html
|
||||
'';
|
||||
};
|
||||
params = mkOption {
|
||||
type = attrsOf (either str path);
|
||||
description = ''
|
||||
Parameters for versioning. Structure depends on versioning.type.
|
||||
See https://docs.syncthing.net/users/versioning.html
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
rescanInterval = mkOption {
|
||||
type = types.int;
|
||||
default = 3600;
|
||||
|
@ -34,6 +34,15 @@ let
|
||||
};
|
||||
|
||||
optionDescription = [
|
||||
(yesNoOption "allowWriteableChroot" "allow_writeable_chroot" false ''
|
||||
Allow the use of writeable root inside chroot().
|
||||
'')
|
||||
(yesNoOption "virtualUseLocalPrivs" "virtual_use_local_privs" false ''
|
||||
If enabled, virtual users will use the same privileges as local
|
||||
users. By default, virtual users will use the same privileges as
|
||||
anonymous users, which tends to be more restrictive (especially
|
||||
in terms of write access).
|
||||
'')
|
||||
(yesNoOption "anonymousUser" "anonymous_enable" false ''
|
||||
Whether to enable the anonymous FTP user.
|
||||
'')
|
||||
@ -76,9 +85,21 @@ let
|
||||
outgoing data connections can only connect to the client. Only enable if you
|
||||
know what you are doing!
|
||||
'')
|
||||
(yesNoOption "ssl_tlsv1" "ssl_tlsv1" true '' '')
|
||||
(yesNoOption "ssl_sslv2" "ssl_sslv2" false '' '')
|
||||
(yesNoOption "ssl_sslv3" "ssl_sslv3" false '' '')
|
||||
(yesNoOption "ssl_tlsv1" "ssl_tlsv1" true ''
|
||||
Only applies if <option>ssl_enable</option> is activated. If
|
||||
enabled, this option will permit TLS v1 protocol connections.
|
||||
TLS v1 connections are preferred.
|
||||
'')
|
||||
(yesNoOption "ssl_sslv2" "ssl_sslv2" false ''
|
||||
Only applies if <option>ssl_enable</option> is activated. If
|
||||
enabled, this option will permit SSL v2 protocol connections.
|
||||
TLS v1 connections are preferred.
|
||||
'')
|
||||
(yesNoOption "ssl_sslv3" "ssl_sslv3" false ''
|
||||
Only applies if <option>ssl_enable</option> is activated. If
|
||||
enabled, this option will permit SSL v3 protocol connections.
|
||||
TLS v1 connections are preferred.
|
||||
'')
|
||||
];
|
||||
|
||||
configFile = pkgs.writeText "vsftpd.conf"
|
||||
@ -98,6 +119,9 @@ let
|
||||
listen=YES
|
||||
nopriv_user=vsftpd
|
||||
secure_chroot_dir=/var/empty
|
||||
${optionalString (cfg.localRoot != null) ''
|
||||
local_root=${cfg.localRoot}
|
||||
''}
|
||||
syslog_enable=YES
|
||||
${optionalString (pkgs.stdenv.hostPlatform.system == "x86_64-linux") ''
|
||||
seccomp_sandbox=NO
|
||||
@ -106,6 +130,11 @@ let
|
||||
${optionalString cfg.anonymousUser ''
|
||||
anon_root=${cfg.anonymousUserHome}
|
||||
''}
|
||||
${optionalString cfg.enableVirtualUsers ''
|
||||
guest_enable=YES
|
||||
guest_username=vsftpd
|
||||
pam_service_name=vsftpd
|
||||
''}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
@ -119,10 +148,7 @@ in
|
||||
|
||||
services.vsftpd = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = "Whether to enable the vsftpd FTP server.";
|
||||
};
|
||||
enable = mkEnableOption "vsftpd";
|
||||
|
||||
userlist = mkOption {
|
||||
default = [];
|
||||
@ -143,6 +169,61 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
enableVirtualUsers = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the <literal>pam_userdb</literal>-based
|
||||
virtual user system
|
||||
'';
|
||||
};
|
||||
|
||||
userDbPath = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
example = "/etc/vsftpd/userDb";
|
||||
default = null;
|
||||
description = ''
|
||||
Only applies if <option>enableVirtualUsers</option> is true.
|
||||
Path pointing to the <literal>pam_userdb</literal> user
|
||||
database used by vsftpd to authenticate the virtual users.
|
||||
|
||||
This user list should be stored in the Berkeley DB database
|
||||
format.
|
||||
|
||||
To generate a new user database, create a text file, add
|
||||
your users using the following format:
|
||||
<programlisting>
|
||||
user1
|
||||
password1
|
||||
user2
|
||||
password2
|
||||
</programlisting>
|
||||
|
||||
You can then install <literal>pkgs.db</literal> to generate
|
||||
the Berkeley DB using
|
||||
<programlisting>
|
||||
db_load -T -t hash -f logins.txt userDb.db
|
||||
</programlisting>
|
||||
|
||||
Caution: <literal>pam_userdb</literal> will automatically
|
||||
append a <literal>.db</literal> suffix to the filename you
|
||||
provide though this option. This option shouldn't include
|
||||
this filetype suffix.
|
||||
'';
|
||||
};
|
||||
|
||||
localRoot = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/www/$USER";
|
||||
description = ''
|
||||
This option represents a directory which vsftpd will try to
|
||||
change into after a local (i.e. non- anonymous) login.
|
||||
|
||||
Failure is silently ignored.
|
||||
'';
|
||||
};
|
||||
|
||||
anonymousUserHome = mkOption {
|
||||
type = types.path;
|
||||
default = "/home/ftp/";
|
||||
@ -186,18 +267,25 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = singleton
|
||||
assertions = [
|
||||
{ assertion =
|
||||
(cfg.forceLocalLoginsSSL -> cfg.rsaCertFile != null)
|
||||
&& (cfg.forceLocalDataSSL -> cfg.rsaCertFile != null);
|
||||
message = "vsftpd: If forceLocalLoginsSSL or forceLocalDataSSL is true then a rsaCertFile must be provided!";
|
||||
};
|
||||
}
|
||||
{
|
||||
assertion = (cfg.enableVirtualUsers -> cfg.userDbPath != null)
|
||||
&& (cfg.enableVirtualUsers -> cfg.localUsers != null);
|
||||
message = "vsftpd: If enableVirtualUsers is true, you need to setup both the userDbPath and localUsers options.";
|
||||
}];
|
||||
|
||||
users.users =
|
||||
[ { name = "vsftpd";
|
||||
uid = config.ids.uids.vsftpd;
|
||||
description = "VSFTPD user";
|
||||
home = "/homeless-shelter";
|
||||
home = if cfg.localRoot != null
|
||||
then cfg.localRoot # <= Necessary for virtual users.
|
||||
else "/homeless-shelter";
|
||||
}
|
||||
] ++ optional cfg.anonymousUser
|
||||
{ name = "ftp";
|
||||
@ -213,23 +301,24 @@ in
|
||||
# = false and whitelist root
|
||||
services.vsftpd.userlist = if cfg.userlistDeny then ["root"] else [];
|
||||
|
||||
systemd.services.vsftpd =
|
||||
{ description = "Vsftpd Server";
|
||||
systemd = {
|
||||
tmpfiles.rules = optional cfg.anonymousUser
|
||||
#Type Path Mode User Gr Age Arg
|
||||
"d '${builtins.toString cfg.anonymousUserHome}' 0555 'ftp' 'ftp' - -";
|
||||
services.vsftpd = {
|
||||
description = "Vsftpd Server";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
preStart =
|
||||
optionalString cfg.anonymousUser
|
||||
''
|
||||
mkdir -p -m 555 ${cfg.anonymousUserHome}
|
||||
chown -R ftp:ftp ${cfg.anonymousUserHome}
|
||||
'';
|
||||
|
||||
serviceConfig.ExecStart = "@${vsftpd}/sbin/vsftpd vsftpd ${configFile}";
|
||||
serviceConfig.Restart = "always";
|
||||
serviceConfig.Type = "forking";
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.services.vsftpd.text = mkIf (cfg.enableVirtualUsers && cfg.userDbPath != null)''
|
||||
auth required pam_userdb.so db=${cfg.userDbPath}
|
||||
account required pam_userdb.so db=${cfg.userDbPath}
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -112,6 +112,32 @@ let
|
||||
Determines whether to add allowed IPs as routes or not.
|
||||
'';
|
||||
};
|
||||
|
||||
socketNamespace = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr str;
|
||||
example = "container";
|
||||
description = ''The pre-existing network namespace in which the
|
||||
WireGuard interface is created, and which retains the socket even if the
|
||||
interface is moved via <option>interfaceNamespace</option>. When
|
||||
<literal>null</literal>, the interface is created in the init namespace.
|
||||
See <link
|
||||
xlink:href="https://www.wireguard.com/netns/">documentation</link>.
|
||||
'';
|
||||
};
|
||||
|
||||
interfaceNamespace = mkOption {
|
||||
default = null;
|
||||
type = with types; nullOr str;
|
||||
example = "init";
|
||||
description = ''The pre-existing network namespace the WireGuard
|
||||
interface is moved to. The special value <literal>init</literal> means
|
||||
the init namespace. When <literal>null</literal>, the interface is not
|
||||
moved.
|
||||
See <link
|
||||
xlink:href="https://www.wireguard.com/netns/">documentation</link>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
@ -239,6 +265,10 @@ let
|
||||
if peer.presharedKey != null
|
||||
then pkgs.writeText "wg-psk" peer.presharedKey
|
||||
else peer.presharedKeyFile;
|
||||
src = interfaceCfg.socketNamespace;
|
||||
dst = interfaceCfg.interfaceNamespace;
|
||||
ip = nsWrap "ip" src dst;
|
||||
wg = nsWrap "wg" src dst;
|
||||
in nameValuePair "wireguard-${interfaceName}-peer-${unitName}"
|
||||
{
|
||||
description = "WireGuard Peer - ${interfaceName} - ${peer.publicKey}";
|
||||
@ -255,16 +285,16 @@ let
|
||||
};
|
||||
|
||||
script = let
|
||||
wg_setup = "wg set ${interfaceName} peer ${peer.publicKey}" +
|
||||
wg_setup = "${wg} set ${interfaceName} peer ${peer.publicKey}" +
|
||||
optionalString (psk != null) " preshared-key ${psk}" +
|
||||
optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" +
|
||||
optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" +
|
||||
optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}";
|
||||
route_setup =
|
||||
optionalString (interfaceCfg.allowedIPsAsRoutes != false)
|
||||
optionalString interfaceCfg.allowedIPsAsRoutes
|
||||
(concatMapStringsSep "\n"
|
||||
(allowedIP:
|
||||
"ip route replace ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}"
|
||||
"${ip} route replace ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}"
|
||||
) peer.allowedIPs);
|
||||
in ''
|
||||
${wg_setup}
|
||||
@ -272,13 +302,13 @@ let
|
||||
'';
|
||||
|
||||
postStop = let
|
||||
route_destroy = optionalString (interfaceCfg.allowedIPsAsRoutes != false)
|
||||
route_destroy = optionalString interfaceCfg.allowedIPsAsRoutes
|
||||
(concatMapStringsSep "\n"
|
||||
(allowedIP:
|
||||
"ip route delete ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}"
|
||||
"${ip} route delete ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}"
|
||||
) peer.allowedIPs);
|
||||
in ''
|
||||
wg set ${interfaceName} peer ${peer.publicKey} remove
|
||||
${wg} set ${interfaceName} peer ${peer.publicKey} remove
|
||||
${route_destroy}
|
||||
'';
|
||||
};
|
||||
@ -287,6 +317,13 @@ let
|
||||
# exactly one way to specify the private key must be set
|
||||
#assert (values.privateKey != null) != (values.privateKeyFile != null);
|
||||
let privKey = if values.privateKeyFile != null then values.privateKeyFile else pkgs.writeText "wg-key" values.privateKey;
|
||||
src = values.socketNamespace;
|
||||
dst = values.interfaceNamespace;
|
||||
ipPreMove = nsWrap "ip" src null;
|
||||
ipPostMove = nsWrap "ip" src dst;
|
||||
wg = nsWrap "wg" src dst;
|
||||
ns = if dst == "init" then "1" else dst;
|
||||
|
||||
in
|
||||
nameValuePair "wireguard-${name}"
|
||||
{
|
||||
@ -307,26 +344,33 @@ let
|
||||
|
||||
${values.preSetup}
|
||||
|
||||
ip link add dev ${name} type wireguard
|
||||
${ipPreMove} link add dev ${name} type wireguard
|
||||
${optionalString (values.interfaceNamespace != null && values.interfaceNamespace != values.socketNamespace) "${ipPreMove} link set ${name} netns ${ns}"}
|
||||
|
||||
${concatMapStringsSep "\n" (ip:
|
||||
"ip address add ${ip} dev ${name}"
|
||||
"${ipPostMove} address add ${ip} dev ${name}"
|
||||
) values.ips}
|
||||
|
||||
wg set ${name} private-key ${privKey} ${
|
||||
${wg} set ${name} private-key ${privKey} ${
|
||||
optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}"}
|
||||
|
||||
ip link set up dev ${name}
|
||||
${ipPostMove} link set up dev ${name}
|
||||
|
||||
${values.postSetup}
|
||||
'';
|
||||
|
||||
postStop = ''
|
||||
ip link del dev ${name}
|
||||
${ipPostMove} link del dev ${name}
|
||||
${values.postShutdown}
|
||||
'';
|
||||
};
|
||||
|
||||
nsWrap = cmd: src: dst:
|
||||
let
|
||||
nsList = filter (ns: ns != null) [ src dst ];
|
||||
ns = last nsList;
|
||||
in
|
||||
if (length nsList > 0 && ns != "init") then "ip netns exec ${ns} ${cmd}" else cmd;
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -236,9 +236,12 @@ in {
|
||||
${if ifaces == [] then ''
|
||||
for i in $(cd /sys/class/net && echo *); do
|
||||
DEVTYPE=
|
||||
source /sys/class/net/$i/uevent
|
||||
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
||||
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
||||
UEVENT_PATH=/sys/class/net/$i/uevent
|
||||
if [ -e "$UEVENT_PATH" ]; then
|
||||
source "$UEVENT_PATH"
|
||||
if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
|
||||
ifaces="$ifaces''${ifaces:+ -N} -i$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
'' else ''
|
||||
|
@ -128,12 +128,6 @@ in {
|
||||
}
|
||||
];
|
||||
|
||||
environment.etc."yggdrasil.conf" = {
|
||||
enable = true;
|
||||
mode = "symlink";
|
||||
source = "/run/yggdrasil/yggdrasil.conf";
|
||||
};
|
||||
|
||||
systemd.services.yggdrasil = {
|
||||
description = "Yggdrasil Network Service";
|
||||
path = [ cfg.package ] ++ optional (configProvided && configFileProvided) pkgs.jq;
|
||||
@ -146,7 +140,7 @@ in {
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/yggdrasil -useconffile /etc/yggdrasil.conf";
|
||||
ExecStart = "${cfg.package}/bin/yggdrasil -useconffile /run/yggdrasil/yggdrasil.conf";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
Restart = "always";
|
||||
|
||||
|
@ -239,7 +239,7 @@ in
|
||||
services.znc = {
|
||||
configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString);
|
||||
config = {
|
||||
Version = (builtins.parseDrvName pkgs.znc.name).version;
|
||||
Version = lib.getVersion pkgs.znc;
|
||||
Listener.l.Port = mkDefault 5000;
|
||||
Listener.l.SSL = mkDefault true;
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ let
|
||||
(if (cfg.web.credentialsFile != null || cfg.web.credentials != { })
|
||||
then "--credentials=${toString credFile}"
|
||||
else "--no-auth")
|
||||
"--addr=${address}:${toString port}"
|
||||
] ++ extraOptions);
|
||||
|
||||
in {
|
||||
@ -177,7 +178,7 @@ in {
|
||||
systemd.services.magneticod = {
|
||||
description = "Magnetico DHT crawler";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = "magnetico";
|
||||
@ -189,7 +190,7 @@ in {
|
||||
systemd.services.magneticow = {
|
||||
description = "Magnetico web interface";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" "magneticod.service"];
|
||||
after = [ "network.target" "magneticod.service"];
|
||||
|
||||
serviceConfig = {
|
||||
User = "magnetico";
|
||||
@ -202,7 +203,7 @@ in {
|
||||
assertions =
|
||||
[
|
||||
{
|
||||
assertion = cfg.web.credentialsFile != null || cfg.web.credentials != { };
|
||||
assertion = cfg.web.credentialsFile == null || cfg.web.credentials == { };
|
||||
message = ''
|
||||
The options services.magnetico.web.credentialsFile and
|
||||
services.magnetico.web.credentials are mutually exclusives.
|
||||
|
@ -84,12 +84,6 @@ GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
|
||||
<title>Issues</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Matomo's file integrity check will warn you. This is due to the patches
|
||||
necessary for NixOS, you can safely ignore this.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Matomo will warn you that the JavaScript tracker is not writable. This is
|
||||
|
@ -390,6 +390,7 @@ in {
|
||||
in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
before = [ "phpfpm-nextcloud.service" ];
|
||||
path = [ occ ];
|
||||
script = ''
|
||||
chmod og+x ${cfg.home}
|
||||
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
|
||||
|
@ -1,4 +1,4 @@
|
||||
# This file defines the options that can be used both for the Apache
|
||||
# This file defines the options that can be used both for the Nginx
|
||||
# main server configuration, and for the virtual hosts. (The latter
|
||||
# has additional options that affect the web server as a whole, like
|
||||
# the user/group to run under.)
|
||||
@ -92,4 +92,3 @@ with lib;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# This file defines the options that can be used both for the Apache
|
||||
# This file defines the options that can be used both for the Nginx
|
||||
# main server configuration, and for the virtual hosts. (The latter
|
||||
# has additional options that affect the web server as a whole, like
|
||||
# the user/group to run under.)
|
||||
|
@ -31,7 +31,7 @@ let
|
||||
'';
|
||||
passAsFile = [ "nixDefaults" "phpOptions" ];
|
||||
} ''
|
||||
cat $phpPackage/etc/php.ini $nixDefaultsPath $phpOptionsPath > $out
|
||||
cat ${poolOpts.phpPackage}/etc/php.ini $nixDefaultsPath $phpOptionsPath > $out
|
||||
'';
|
||||
|
||||
poolOpts = { name, ... }:
|
||||
@ -69,8 +69,6 @@ let
|
||||
|
||||
phpOptions = mkOption {
|
||||
type = types.lines;
|
||||
default = cfg.phpOptions;
|
||||
defaultText = "config.services.phpfpm.phpOptions";
|
||||
description = ''
|
||||
"Options appended to the PHP configuration file <filename>php.ini</filename> used for this PHP-FPM pool."
|
||||
'';
|
||||
@ -137,6 +135,7 @@ let
|
||||
config = {
|
||||
socket = if poolOpts.listen == "" then "${runtimeDir}/${name}.sock" else poolOpts.listen;
|
||||
group = mkDefault poolOpts.user;
|
||||
phpOptions = mkBefore cfg.phpOptions;
|
||||
|
||||
settings = mapAttrs (name: mkDefault){
|
||||
listen = poolOpts.socket;
|
||||
@ -263,6 +262,7 @@ in {
|
||||
in {
|
||||
Slice = "phpfpm.slice";
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "full";
|
||||
ProtectHome = true;
|
||||
# XXX: We need AF_NETLINK to make the sendmail SUID binary from postfix work
|
||||
|
196
nixos/modules/services/web-servers/ttyd.nix
Normal file
196
nixos/modules/services/web-servers/ttyd.nix
Normal file
@ -0,0 +1,196 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.ttyd;
|
||||
|
||||
# Command line arguments for the ttyd daemon
|
||||
args = [ "--port" (toString cfg.port) ]
|
||||
++ optionals (cfg.socket != null) [ "--interface" cfg.socket ]
|
||||
++ optionals (cfg.interface != null) [ "--interface" cfg.interface ]
|
||||
++ [ "--signal" (toString cfg.signal) ]
|
||||
++ (concatLists (mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions))
|
||||
++ [ "--terminal-type" cfg.terminalType ]
|
||||
++ optionals cfg.checkOrigin [ "--check-origin" ]
|
||||
++ [ "--max-clients" (toString cfg.maxClients) ]
|
||||
++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ]
|
||||
++ optionals cfg.enableIPv6 [ "--ipv6" ]
|
||||
++ optionals cfg.enableSSL [ "--ssl-cert" cfg.certFile
|
||||
"--ssl-key" cfg.keyFile
|
||||
"--ssl-ca" cfg.caFile ]
|
||||
++ [ "--debug" (toString cfg.logLevel) ];
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
services.ttyd = {
|
||||
enable = mkEnableOption "ttyd daemon";
|
||||
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 7681;
|
||||
description = "Port to listen on (use 0 for random port)";
|
||||
};
|
||||
|
||||
socket = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/var/run/ttyd.sock";
|
||||
description = "UNIX domain socket path to bind.";
|
||||
};
|
||||
|
||||
interface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "eth0";
|
||||
description = "Network interface to bind.";
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Username for basic authentication.";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
apply = value: if value == null then null else toString value;
|
||||
description = ''
|
||||
File containing the password to use for basic authentication.
|
||||
For insecurely putting the password in the globally readable store use
|
||||
<literal>pkgs.writeText "ttydpw" "MyPassword"</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
signal = mkOption {
|
||||
type = types.ints.u8;
|
||||
default = 1;
|
||||
description = "Signal to send to the command on session close.";
|
||||
};
|
||||
|
||||
clientOptions = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
example = literalExample ''{
|
||||
fontSize = "16";
|
||||
fontFamily = "Fira Code";
|
||||
|
||||
}'';
|
||||
description = ''
|
||||
Attribute set of client options for xtermjs.
|
||||
<link xlink:href="https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/"/>
|
||||
'';
|
||||
};
|
||||
|
||||
terminalType = mkOption {
|
||||
type = types.str;
|
||||
default = "xterm-256color";
|
||||
description = "Terminal type to report.";
|
||||
};
|
||||
|
||||
checkOrigin = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether to allow a websocket connection from a different origin.";
|
||||
};
|
||||
|
||||
maxClients = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
description = "Maximum clients to support (0, no limit)";
|
||||
};
|
||||
|
||||
indexFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Custom index.html path";
|
||||
};
|
||||
|
||||
enableIPv6 = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether or not to enable IPv6 support.";
|
||||
};
|
||||
|
||||
enableSSL = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Whether or not to enable SSL (https) support.";
|
||||
};
|
||||
|
||||
certFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "SSL certificate file path.";
|
||||
};
|
||||
|
||||
keyFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
apply = value: if value == null then null else toString value;
|
||||
description = ''
|
||||
SSL key file path.
|
||||
For insecurely putting the keyFile in the globally readable store use
|
||||
<literal>pkgs.writeText "ttydKeyFile" "SSLKEY"</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
caFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "SSL CA file path for client certificate verification.";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.int;
|
||||
default = 7;
|
||||
description = "Set log level.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions =
|
||||
[ { assertion = cfg.enableSSL
|
||||
-> cfg.certFile != null && cfg.keyFile != null && cfg.caFile != null;
|
||||
message = "SSL is enabled for ttyd, but no certFile, keyFile or caFile has been specefied."; }
|
||||
{ assertion = ! (cfg.interface != null && cfg.socket != null);
|
||||
message = "Cannot set both interface and socket for ttyd."; }
|
||||
{ assertion = (cfg.username != null) == (cfg.passwordFile != null);
|
||||
message = "Need to set both username and passwordFile for ttyd"; }
|
||||
];
|
||||
|
||||
systemd.services.ttyd = {
|
||||
description = "ttyd Web Server Daemon";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
# Runs login which needs to be run as root
|
||||
# login: Cannot possibly work without effective root
|
||||
User = "root";
|
||||
};
|
||||
|
||||
script = if cfg.passwordFile != null then ''
|
||||
PASSWORD=$(cat ${escapeShellArg cfg.passwordFile})
|
||||
${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \
|
||||
--credential ${escapeShellArg cfg.username}:"$PASSWORD" \
|
||||
${pkgs.shadow}/bin/login
|
||||
''
|
||||
else ''
|
||||
${pkgs.ttyd}/bin/ttyd ${lib.escapeShellArgs args} \
|
||||
${pkgs.shadow}/bin/login
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
@ -15,8 +15,8 @@ in
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.varnish5;
|
||||
defaultText = "pkgs.varnish5";
|
||||
default = pkgs.varnish;
|
||||
defaultText = "pkgs.varnish";
|
||||
description = ''
|
||||
The package to use
|
||||
'';
|
||||
@ -48,7 +48,7 @@ in
|
||||
extraModules = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
example = literalExample "[ pkgs.varnish5Packages.geoip ]";
|
||||
example = literalExample "[ pkgs.varnishPackages.geoip ]";
|
||||
description = "
|
||||
Varnish modules (except 'std').
|
||||
";
|
||||
|
@ -18,7 +18,7 @@ in
|
||||
# determines the default: later modules (if enabled) are preferred.
|
||||
# E.g., if Plasma 5 is enabled, it supersedes xterm.
|
||||
imports = [
|
||||
./none.nix ./xterm.nix ./xfce.nix ./xfce4-14.nix ./plasma5.nix ./lumina.nix
|
||||
./none.nix ./xterm.nix ./xfce.nix ./plasma5.nix ./lumina.nix
|
||||
./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix ./maxx.nix
|
||||
./mate.nix ./pantheon.nix ./surf-display.nix
|
||||
];
|
||||
|
@ -184,6 +184,13 @@ in
|
||||
enableGnomeKeyring = true;
|
||||
};
|
||||
|
||||
systemd.packages = with pkgs.gnome3; [
|
||||
gnome-flashback
|
||||
] ++ (map
|
||||
(wm: gnome-flashback.mkSystemdTargetForWm {
|
||||
inherit (wm) wmName;
|
||||
}) cfg.flashback.customSessions);
|
||||
|
||||
services.dbus.packages = [
|
||||
pkgs.gnome3.gnome-screensaver
|
||||
];
|
||||
@ -271,6 +278,26 @@ in
|
||||
source-sans-pro
|
||||
];
|
||||
|
||||
## Enable soft realtime scheduling, only supported on wayland ##
|
||||
|
||||
security.wrappers.".gnome-shell-wrapped" = {
|
||||
source = "${pkgs.gnome3.gnome-shell}/bin/.gnome-shell-wrapped";
|
||||
capabilities = "cap_sys_nice=ep";
|
||||
};
|
||||
|
||||
systemd.user.services.gnome-shell-wayland = let
|
||||
gnomeShellRT = with pkgs.gnome3; pkgs.runCommand "gnome-shell-rt" {} ''
|
||||
mkdir -p $out/bin/
|
||||
cp ${gnome-shell}/bin/gnome-shell $out/bin
|
||||
sed -i "s@${gnome-shell}/bin/@${config.security.wrapperDir}/@" $out/bin/gnome-shell
|
||||
'';
|
||||
in {
|
||||
# Note we need to clear ExecStart before overriding it
|
||||
serviceConfig.ExecStart = ["" "${gnomeShellRT}/bin/gnome-shell"];
|
||||
# Do not use the default environment, it provides a broken PATH
|
||||
environment = mkForce {};
|
||||
};
|
||||
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-32/elements/core/meta-gnome-core-shell.bst
|
||||
environment.systemPackages = with pkgs.gnome3; [
|
||||
adwaita-icon-theme
|
||||
@ -282,7 +309,7 @@ in
|
||||
gnome-shell
|
||||
gnome-shell-extensions
|
||||
gnome-themes-extra
|
||||
gnome-user-docs
|
||||
pkgs.gnome-user-docs
|
||||
pkgs.orca
|
||||
pkgs.glib # for gsettings
|
||||
pkgs.gnome-menus
|
||||
|
@ -159,7 +159,7 @@ in
|
||||
# Override GSettings schemas
|
||||
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
|
||||
|
||||
environment.sessionVariables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1";
|
||||
environment.sessionVariables.GNOME_SESSION_DEBUG = mkIf cfg.debug "1";
|
||||
|
||||
# Settings from elementary-default-settings
|
||||
environment.sessionVariables.GTK_CSD = "1";
|
||||
|
@ -27,20 +27,13 @@ in
|
||||
example = "vlc";
|
||||
description = "Phonon audio backend to install.";
|
||||
};
|
||||
|
||||
enableQt4Support = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable support for Qt 4-based applications. Particularly, install a
|
||||
default backend for Phonon.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "enableQt4Support" ] "Phonon no longer supports Qt 4.")
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
@ -173,12 +166,10 @@ in
|
||||
|
||||
# Phonon audio backend
|
||||
++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
|
||||
++ lib.optional (cfg.phononBackend == "gstreamer" && cfg.enableQt4Support) pkgs.phonon-backend-gstreamer
|
||||
++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
|
||||
++ lib.optional (cfg.phononBackend == "vlc" && cfg.enableQt4Support) pkgs.phonon-backend-vlc
|
||||
|
||||
# Optional hardware support features
|
||||
++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt ]
|
||||
++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt openobex obexftp ]
|
||||
++ lib.optional config.networking.networkmanager.enable plasma-nm
|
||||
++ lib.optional config.hardware.pulseaudio.enable plasma-pa
|
||||
++ lib.optional config.powerManagement.enable powerdevil
|
||||
@ -232,7 +223,6 @@ in
|
||||
security.pam.services.kdm.enableKwallet = true;
|
||||
security.pam.services.lightdm.enableKwallet = true;
|
||||
security.pam.services.sddm.enableKwallet = true;
|
||||
security.pam.services.slim.enableKwallet = true;
|
||||
|
||||
xdg.portal.enable = true;
|
||||
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-kde ];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user