Project import generated by Copybara.
GitOrigin-RevId: 7cb76200088f45cd24a9aa67fd2f9657943d78a4
This commit is contained in:
parent
2345d8b872
commit
170c3b4027
817 changed files with 24103 additions and 8332 deletions
|
@ -1,7 +1,10 @@
|
|||
name: "Checking EditorConfig"
|
||||
|
||||
permissions: read-all
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
# avoids approving first time contributors
|
||||
pull_request_target:
|
||||
branches-ignore:
|
||||
- 'release-**'
|
||||
|
||||
|
@ -21,17 +24,23 @@ jobs:
|
|||
>> $GITHUB_ENV
|
||||
echo 'EOF' >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
if: env.PR_DIFF
|
||||
- name: Fetch editorconfig-checker
|
||||
- uses: cachix/install-nix-action@v13
|
||||
if: env.PR_DIFF
|
||||
with:
|
||||
# nixpkgs commit is pinned so that it doesn't break
|
||||
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/f93ecc4f6bc60414d8b73dbdf615ceb6a2c604df.tar.gz
|
||||
- name: install editorconfig-checker
|
||||
run: nix-env -iA editorconfig-checker -f '<nixpkgs>'
|
||||
if: env.PR_DIFF
|
||||
env:
|
||||
ECC_VERSION: "2.3.5"
|
||||
ECC_URL: "https://github.com/editorconfig-checker/editorconfig-checker/releases/download"
|
||||
run: |
|
||||
curl -sSf -O -L -C - "$ECC_URL/$ECC_VERSION/ec-linux-amd64.tar.gz" && \
|
||||
tar xzf ec-linux-amd64.tar.gz && \
|
||||
mv ./bin/ec-linux-amd64 ./bin/editorconfig-checker
|
||||
- name: Checking EditorConfig
|
||||
if: env.PR_DIFF
|
||||
run: |
|
||||
echo "$PR_DIFF" | xargs ./bin/editorconfig-checker -disable-indent-size
|
||||
echo "$PR_DIFF" | xargs editorconfig-checker -disable-indent-size
|
||||
- if: ${{ failure() }}
|
||||
run: |
|
||||
echo "::error :: Hey! It looks like your changes don't follow our editorconfig settings. Read https://editorconfig.org/#download to configure your editor so you never see this error again."
|
||||
|
||||
|
|
|
@ -171,7 +171,8 @@
|
|||
|
||||
- Arguments should be listed in the order they are used, with the exception of `lib`, which always goes first.
|
||||
|
||||
- Prefer using the top-level `lib` over its alias `stdenv.lib`. `lib` is unrelated to `stdenv`, and so `stdenv.lib` should only be used as a convenience alias when developing to avoid having to modify the function inputs just to test something out.
|
||||
- The top-level `lib` must be used in the master and 21.05 branch over its alias `stdenv.lib` as it now causes evaluation errors when aliases are disabled which is the case for ofborg.
|
||||
`lib` is unrelated to `stdenv`, and so `stdenv.lib` should only be used as a convenience alias when developing locally to avoid having to modify the function inputs just to test something out.
|
||||
|
||||
## Package naming {#sec-package-naming}
|
||||
|
||||
|
@ -512,3 +513,73 @@ If you do need to do create this sort of patch file, one way to do so is with gi
|
|||
```ShellSession
|
||||
$ git diff > nixpkgs/pkgs/the/package/0001-changes.patch
|
||||
```
|
||||
|
||||
## Package tests {#sec-package-tests}
|
||||
|
||||
Tests are important to ensure quality and make reviews and automatic updates easy.
|
||||
|
||||
Nix package tests are a lightweight alternative to [NixOS module tests](https://nixos.org/manual/nixos/stable/#sec-nixos-tests). They can be used to create simple integration tests for packages while the module tests are used to test services or programs with a graphical user interface on a NixOS VM. Unittests that are included in the source code of a package should be executed in the `checkPhase`.
|
||||
|
||||
### Writing package tests {#ssec-package-tests-writing}
|
||||
|
||||
This is an example using the `phoronix-test-suite` package with the current best practices.
|
||||
|
||||
Add the tests in `passthru.tests` to the package definition like this:
|
||||
|
||||
```nix
|
||||
{ stdenv, lib, fetchurl, callPackage }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
…
|
||||
|
||||
passthru.tests = {
|
||||
simple-execution = callPackage ./tests.nix { };
|
||||
};
|
||||
|
||||
meta = { … };
|
||||
}
|
||||
```
|
||||
|
||||
Create `tests.nix` in the package directory:
|
||||
|
||||
```nix
|
||||
{ runCommand, phoronix-test-suite }:
|
||||
|
||||
let
|
||||
inherit (phoronix-test-suite) pname version;
|
||||
in
|
||||
|
||||
runCommand "${pname}-tests" { meta.timeout = 3; }
|
||||
''
|
||||
# automatic initial setup to prevent interactive questions
|
||||
${phoronix-test-suite}/bin/phoronix-test-suite enterprise-setup >/dev/null
|
||||
# get version of installed program and compare with package version
|
||||
if [[ `${phoronix-test-suite}/bin/phoronix-test-suite version` != *"${version}"* ]]; then
|
||||
echo "Error: program version does not match package version"
|
||||
exit 1
|
||||
fi
|
||||
# run dummy command
|
||||
${phoronix-test-suite}/bin/phoronix-test-suite dummy_module.dummy-command >/dev/null
|
||||
# needed for Nix to register the command as successful
|
||||
touch $out
|
||||
''
|
||||
```
|
||||
|
||||
### Running package tests {#ssec-package-tests-running}
|
||||
|
||||
You can run these tests with:
|
||||
|
||||
```ShellSession
|
||||
$ cd path/to/nixpkgs
|
||||
$ nix-build -A phoronix-test-suite.tests
|
||||
```
|
||||
|
||||
### Examples of package tests {#ssec-package-tests-examples}
|
||||
|
||||
Here are examples of package tests:
|
||||
|
||||
- [Jasmin compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/jasmin/test-assemble-hello-world/default.nix)
|
||||
- [Lobster compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/lobster/test-can-run-hello-world.nix)
|
||||
- [Spacy annotation test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/spacy/annotation-test/default.nix)
|
||||
- [Libtorch test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/science/math/libtorch/test/default.nix)
|
||||
- [Multiple tests for nanopb](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/nanopb/default.nix)
|
||||
|
|
|
@ -2,16 +2,19 @@
|
|||
|
||||
## How to use Agda
|
||||
|
||||
Agda can be installed from `agda`:
|
||||
```ShellSession
|
||||
$ nix-env -iA agda
|
||||
```
|
||||
Agda is available as the [agda](https://search.nixos.org/packages?channel=unstable&show=agda&from=0&size=30&sort=relevance&query=agda)
|
||||
package.
|
||||
|
||||
To use Agda with libraries, the `agda.withPackages` function can be used. This function either takes:
|
||||
The `agda` package installs an Agda-wrapper, which calls `agda` with `--library-file`
|
||||
set to a generated library-file within the nix store, this means your library-file in
|
||||
`$HOME/.agda/libraries` will be ignored. By default the agda package installs Agda
|
||||
with no libraries, i.e. the generated library-file is empty. To use Agda with libraries,
|
||||
the `agda.withPackages` function can be used. This function either takes:
|
||||
|
||||
* A list of packages,
|
||||
* or a function which returns a list of packages when given the `agdaPackages` attribute set,
|
||||
* or an attribute set containing a list of packages and a GHC derivation for compilation (see below).
|
||||
* or an attribute set containing a function which returns a list of packages when given the `agdaPackages` attribute set and a GHC derivation for compilation (see below).
|
||||
|
||||
For example, suppose we wanted a version of Agda which has access to the standard library. This can be obtained with the expressions:
|
||||
|
||||
|
@ -27,9 +30,66 @@ agda.withPackages (p: [ p.standard-library ])
|
|||
|
||||
or can be called as in the [Compiling Agda](#compiling-agda) section.
|
||||
|
||||
If you want to use a library in your home directory (for instance if it is a development version) then typecheck it manually (using `agda.withPackages` if necessary) and then override the `src` attribute of the package to point to your local repository.
|
||||
If you want to use a different version of a library (for instance a development version)
|
||||
override the `src` attribute of the package to point to your local repository
|
||||
|
||||
Agda will not by default use these libraries. To tell Agda to use the library we have some options:
|
||||
```nix
|
||||
agda.withPackages (p: [
|
||||
(p.standard-library.overrideAttrs (oldAttrs: {
|
||||
version = "local version";
|
||||
src = /path/to/local/repo/agda-stdlib;
|
||||
}))
|
||||
])
|
||||
```
|
||||
|
||||
You can also reference a GitHub repository
|
||||
```nix
|
||||
agda.withPackages (p: [
|
||||
(p.standard-library.overrideAttrs (oldAttrs: {
|
||||
version = "1.5";
|
||||
src = fetchFromGitHub {
|
||||
repo = "agda-stdlib";
|
||||
owner = "agda";
|
||||
rev = "v1.5";
|
||||
sha256 = "16fcb7ssj6kj687a042afaa2gq48rc8abihpm14k684ncihb2k4w";
|
||||
};
|
||||
}))
|
||||
])
|
||||
```
|
||||
|
||||
If you want to use a library not added to Nixpkgs, you can add a
|
||||
dependency to a local library by calling `agdaPackages.mkDerivation`.
|
||||
```nix
|
||||
agda.withPackages (p: [
|
||||
(p.mkDerivation {
|
||||
pname = "your-agda-lib";
|
||||
version = "1.0.0";
|
||||
src = /path/to/your-agda-lib;
|
||||
})
|
||||
])
|
||||
```
|
||||
|
||||
Again you can reference GitHub
|
||||
|
||||
```nix
|
||||
agda.withPackages (p: [
|
||||
(p.mkDerivation {
|
||||
pname = "your-agda-lib";
|
||||
version = "1.0.0";
|
||||
src = fetchFromGitHub {
|
||||
repo = "repo";
|
||||
owner = "owner";
|
||||
version = "...";
|
||||
rev = "...";
|
||||
sha256 = "...";
|
||||
};
|
||||
})
|
||||
])
|
||||
```
|
||||
|
||||
See [Building Agda Packages](#building-agda-packages) for more information on `mkDerivation`.
|
||||
|
||||
Agda will not by default use these libraries. To tell Agda to use a library we have some options:
|
||||
|
||||
* Call `agda` with the library flag:
|
||||
```ShellSession
|
||||
|
@ -46,7 +106,7 @@ depend: standard-library
|
|||
More information can be found in the [official Agda documentation on library management](https://agda.readthedocs.io/en/v2.6.1/tools/package-system.html).
|
||||
|
||||
## Compiling Agda
|
||||
Agda modules can be compiled with the `--compile` flag. A version of `ghc` with `ieee754` is made available to the Agda program via the `--with-compiler` flag.
|
||||
Agda modules can be compiled using the GHC backend with the `--compile` flag. A version of `ghc` with `ieee754` is made available to the Agda program via the `--with-compiler` flag.
|
||||
This can be overridden by a different version of `ghc` as follows:
|
||||
|
||||
```nix
|
||||
|
@ -65,6 +125,21 @@ A derivation can then be written using `agdaPackages.mkDerivation`. This has sim
|
|||
* `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
|
||||
* `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
|
||||
|
||||
Here is an example `default.nix`
|
||||
|
||||
```nix
|
||||
{ nixpkgs ? <nixpkgs> }:
|
||||
with (import nixpkgs {});
|
||||
agdaPackages.mkDerivation {
|
||||
version = "1.0";
|
||||
pname = "my-agda-lib";
|
||||
src = ./.;
|
||||
buildInputs = [
|
||||
agdaPackages.standard-library
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Building Agda packages
|
||||
The default build phase for `agdaPackages.mkDerivation` simply runs `agda` on the `Everything.agda` file.
|
||||
If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden.
|
||||
|
@ -80,10 +155,16 @@ By default, Agda sources are files ending on `.agda`, or literate Agda files end
|
|||
## Adding Agda packages to Nixpkgs
|
||||
|
||||
To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other Agda libraries, so the top line of the `default.nix` can look like:
|
||||
|
||||
```nix
|
||||
{ mkDerivation, standard-library, fetchFromGitHub }:
|
||||
```
|
||||
and `mkDerivation` should be called instead of `agdaPackages.mkDerivation`. Here is an example skeleton derivation for iowa-stdlib:
|
||||
|
||||
Note that the derivation function is called with `mkDerivation` set to `agdaPackages.mkDerivation`, therefore you
|
||||
could use a similar set as in your `default.nix` from [Writing Agda Packages](#writing-agda-packages) with
|
||||
`agdaPackages.mkDerivation` replaced with `mkDerivation`.
|
||||
|
||||
Here is an example skeleton derivation for iowa-stdlib:
|
||||
|
||||
```nix
|
||||
mkDerivation {
|
||||
|
|
5
third_party/nixpkgs/lib/default.nix
vendored
5
third_party/nixpkgs/lib/default.nix
vendored
|
@ -66,8 +66,9 @@ let
|
|||
stringLength sub substring tail trace;
|
||||
inherit (self.trivial) id const pipe concat or and bitAnd bitOr bitXor
|
||||
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
|
||||
importJSON importTOML warn info showWarnings nixpkgsVersion version mod compare
|
||||
splitByAndCompare functionArgs setFunctionArgs isFunction toHexString toBaseDigits;
|
||||
importJSON importTOML warn warnIf info showWarnings nixpkgsVersion version
|
||||
mod compare splitByAndCompare functionArgs setFunctionArgs isFunction
|
||||
toHexString toBaseDigits;
|
||||
inherit (self.fixedPoints) fix fix' converge extends composeExtensions
|
||||
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
|
||||
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
|
||||
|
|
6
third_party/nixpkgs/lib/modules.nix
vendored
6
third_party/nixpkgs/lib/modules.nix
vendored
|
@ -37,7 +37,7 @@ let
|
|||
setAttrByPath
|
||||
toList
|
||||
types
|
||||
warn
|
||||
warnIf
|
||||
;
|
||||
inherit (lib.options)
|
||||
isOption
|
||||
|
@ -516,8 +516,8 @@ rec {
|
|||
value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue;
|
||||
|
||||
warnDeprecation =
|
||||
if opt.type.deprecationMessage == null then id
|
||||
else warn "The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}";
|
||||
warnIf (opt.type.deprecationMessage != null)
|
||||
"The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}";
|
||||
|
||||
in warnDeprecation opt //
|
||||
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
|
||||
|
|
6
third_party/nixpkgs/lib/strings.nix
vendored
6
third_party/nixpkgs/lib/strings.nix
vendored
|
@ -606,7 +606,7 @@ rec {
|
|||
This function will fail if the input string is longer than the
|
||||
requested length.
|
||||
|
||||
Type: fixedWidthString :: int -> string -> string
|
||||
Type: fixedWidthString :: int -> string -> string -> string
|
||||
|
||||
Example:
|
||||
fixedWidthString 5 "0" (toString 15)
|
||||
|
@ -644,8 +644,8 @@ rec {
|
|||
floatToString = float: let
|
||||
result = toString float;
|
||||
precise = float == fromJSON result;
|
||||
in if precise then result
|
||||
else lib.warn "Imprecise conversion from float to string ${result}" result;
|
||||
in lib.warnIf (!precise) "Imprecise conversion from float to string ${result}"
|
||||
result;
|
||||
|
||||
/* Check whether a value can be coerced to a string */
|
||||
isCoercibleToString = x:
|
||||
|
|
3
third_party/nixpkgs/lib/trivial.nix
vendored
3
third_party/nixpkgs/lib/trivial.nix
vendored
|
@ -297,12 +297,15 @@ rec {
|
|||
# Usage:
|
||||
# {
|
||||
# foo = lib.warn "foo is deprecated" oldFoo;
|
||||
# bar = lib.warnIf (bar == "") "Empty bar is deprecated" bar;
|
||||
# }
|
||||
#
|
||||
# TODO: figure out a clever way to integrate location information from
|
||||
# something like __unsafeGetAttrPos.
|
||||
|
||||
warn = msg: builtins.trace "[1;31mwarning: ${msg}[0m";
|
||||
warnIf = cond: msg: if cond then warn msg else id;
|
||||
|
||||
info = msg: builtins.trace "INFO: ${msg}";
|
||||
|
||||
showWarnings = warnings: res: lib.fold (w: x: warn w x) res warnings;
|
||||
|
|
2
third_party/nixpkgs/lib/types.nix
vendored
2
third_party/nixpkgs/lib/types.nix
vendored
|
@ -337,7 +337,7 @@ rec {
|
|||
};
|
||||
|
||||
shellPackage = package // {
|
||||
check = x: (package.check x) && (hasAttr "shellPath" x);
|
||||
check = x: isDerivation x && hasAttr "shellPath" x;
|
||||
};
|
||||
|
||||
path = mkOptionType {
|
||||
|
|
|
@ -2177,6 +2177,12 @@
|
|||
githubId = 990767;
|
||||
name = "Daniel Olsen";
|
||||
};
|
||||
daneads = {
|
||||
email = "me@daneads.com";
|
||||
github = "daneads";
|
||||
githubId = 24708079;
|
||||
name = "Dan Eads";
|
||||
};
|
||||
danharaj = {
|
||||
email = "dan@obsidian.systems";
|
||||
github = "danharaj";
|
||||
|
@ -2439,6 +2445,12 @@
|
|||
githubId = 8404455;
|
||||
name = "Diego Lelis";
|
||||
};
|
||||
diogox = {
|
||||
name = "Diogo Xavier";
|
||||
email = "13244408+diogox@users.noreply.github.com";
|
||||
github = "diogox";
|
||||
githubId = 13244408;
|
||||
};
|
||||
dipinhora = {
|
||||
email = "dipinhora+github@gmail.com";
|
||||
github = "dipinhora";
|
||||
|
@ -3029,6 +3041,12 @@
|
|||
fingerprint = "F178 B4B4 6165 6D1B 7C15 B55D 4029 3358 C7B9 326B";
|
||||
}];
|
||||
};
|
||||
erikbackman = {
|
||||
email = "contact@ebackman.net";
|
||||
github = "erikbackman";
|
||||
githubId = 46724898;
|
||||
name = "Erik Backman";
|
||||
};
|
||||
erikryb = {
|
||||
email = "erik.rybakken@math.ntnu.no";
|
||||
github = "erikryb";
|
||||
|
@ -3107,6 +3125,16 @@
|
|||
githubId = 2147649;
|
||||
name = "Euan Kemp";
|
||||
};
|
||||
evalexpr = {
|
||||
name = "Jonathan Wilkins";
|
||||
email = "nixos@wilkins.tech";
|
||||
github = "evalexpr";
|
||||
githubId = 23485511;
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x2D1D402E17763DD6";
|
||||
fingerprint = "8129 5B85 9C5A F703 C2F4 1E29 2D1D 402E 1776 3DD6";
|
||||
}];
|
||||
};
|
||||
evanjs = {
|
||||
email = "evanjsx@gmail.com";
|
||||
github = "evanjs";
|
||||
|
@ -3991,6 +4019,16 @@
|
|||
githubId = 19825977;
|
||||
name = "Hiren Shah";
|
||||
};
|
||||
hiro98 = {
|
||||
email = "hiro@protagon.space";
|
||||
github = "vale981";
|
||||
githubId = 4025991;
|
||||
name = "Valentin Boettcher";
|
||||
keys = [{
|
||||
longkeyid = "rsa2048/0xC22D4DE4D7B32D19";
|
||||
fingerprint = "45A9 9917 578C D629 9F5F B5B4 C22D 4DE4 D7B3 2D19";
|
||||
}];
|
||||
};
|
||||
hjones2199 = {
|
||||
email = "hjones2199@gmail.com";
|
||||
github = "hjones2199";
|
||||
|
@ -4715,6 +4753,12 @@
|
|||
githubId = 1102396;
|
||||
name = "Jussi Maki";
|
||||
};
|
||||
joaquinito2051 = {
|
||||
email = "joaquinito2051@gmail.com";
|
||||
github = "heroku-miraheze";
|
||||
githubId = 61781343;
|
||||
name = "Joaquín Rufo Gutierrez";
|
||||
};
|
||||
jobojeha = {
|
||||
email = "jobojeha@jeppener.de";
|
||||
github = "jobojeha";
|
||||
|
@ -6134,11 +6178,11 @@
|
|||
fingerprint = "B573 5118 0375 A872 FBBF 7770 B629 036B E399 EEE9";
|
||||
}];
|
||||
};
|
||||
mausch = {
|
||||
email = "mauricioscheffer@gmail.com";
|
||||
github = "mausch";
|
||||
githubId = 95194;
|
||||
name = "Mauricio Scheffer";
|
||||
masipcat = {
|
||||
email = "jordi@masip.cat";
|
||||
github = "masipcat";
|
||||
githubId = 775189;
|
||||
name = "Jordi Masip";
|
||||
};
|
||||
matejc = {
|
||||
email = "cotman.matej@gmail.com";
|
||||
|
@ -6194,6 +6238,12 @@
|
|||
githubId = 136037;
|
||||
name = "Matthew Maurer";
|
||||
};
|
||||
mausch = {
|
||||
email = "mauricioscheffer@gmail.com";
|
||||
github = "mausch";
|
||||
githubId = 95194;
|
||||
name = "Mauricio Scheffer";
|
||||
};
|
||||
maxdamantus = {
|
||||
email = "maxdamantus@gmail.com";
|
||||
github = "Maxdamantus";
|
||||
|
@ -7031,6 +7081,12 @@
|
|||
githubId = 628342;
|
||||
name = "Tim Steinbach";
|
||||
};
|
||||
netcrns = {
|
||||
email = "jason.wing@gmx.de";
|
||||
github = "netcrns";
|
||||
githubId = 34162313;
|
||||
name = "Jason Wing";
|
||||
};
|
||||
netixx = {
|
||||
email = "dev.espinetfrancois@gmail.com";
|
||||
github = "netixx";
|
||||
|
@ -10305,6 +10361,12 @@
|
|||
githubId = 2212422;
|
||||
name = "uwap";
|
||||
};
|
||||
V = {
|
||||
name = "V";
|
||||
email = "v@anomalous.eu";
|
||||
github = "deviant";
|
||||
githubId = 68829907;
|
||||
};
|
||||
va1entin = {
|
||||
email = "github@valentinsblog.com";
|
||||
github = "va1entin";
|
||||
|
@ -10515,7 +10577,12 @@
|
|||
githubId = 45292658;
|
||||
name = "Julius Schmitt";
|
||||
};
|
||||
|
||||
vojta001 = {
|
||||
email = "vojtech.kane@gmail.com";
|
||||
github = "vojta001";
|
||||
githubId = 7038383;
|
||||
name = "Vojta Káně";
|
||||
};
|
||||
volhovm = {
|
||||
email = "volhovm.cs@gmail.com";
|
||||
github = "volhovm";
|
||||
|
|
|
@ -110,7 +110,6 @@ with lib.maintainers; {
|
|||
members = [
|
||||
mmilata
|
||||
petabyteboy
|
||||
prusnak
|
||||
ryantm
|
||||
];
|
||||
scope = "Maintain Jitsi.";
|
||||
|
@ -136,6 +135,7 @@ with lib.maintainers; {
|
|||
mguentner
|
||||
ekleog
|
||||
ralith
|
||||
mjlbach
|
||||
];
|
||||
scope = "Maintain the ecosystem around Matrix, a decentralized messenger.";
|
||||
};
|
||||
|
|
|
@ -94,6 +94,12 @@
|
|||
been introduced.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://nginx.org">Nginx</link> has been updated to stable version 1.20.0.
|
||||
Now nginx uses the zlib-ng library by default.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
@ -324,7 +330,18 @@
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>vim</literal> switched to Python 3, dropping all Python 2 support.
|
||||
<literal>vim</literal> and <literal>neovim</literal> switched to Python 3, dropping all Python 2 support.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link linkend="opt-networking.wireguard.interfaces">networking.wireguard.interfaces.<name>.generatePrivateKeyFile</link>,
|
||||
which is off by default, had a <literal>chmod</literal> race condition
|
||||
fixed. As an aside, the parent directory's permissions were widened,
|
||||
and the key files were made owner-writable.
|
||||
This only affects newly created keys.
|
||||
However, if the exact permissions are important for your setup, read
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/121294">#121294</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
|
@ -687,6 +704,17 @@ environment.systemPackages = [
|
|||
as for each interface in <varname>services.babeld.interfaces</varname>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <option>services.zigbee2mqtt.config</option> option has been renamed to <option>services.zigbee2mqtt.settings</option> and
|
||||
now follows <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC 0042</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <package>yadm</package> dotfile manager has been updated from 2.x to 3.x, which has new (XDG) default locations for some data/state files. Most yadm commands will fail and print a legacy path warning (which describes how to upgrade/migrate your repository). If you have scripts, daemons, scheduled jobs, shell profiles, etc. that invoke yadm, expect them to fail or misbehave until you perform this migration and prepare accordingly.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
@ -801,6 +829,23 @@ environment.systemPackages = [
|
|||
default in the CLI tooling which in turn enables us to use
|
||||
<literal>unbound-control</literal> without passing a custom configuration location.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The module has also been reworked to be <link
|
||||
xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
|
||||
0042</link> compliant. As such,
|
||||
<option>sevices.unbound.extraConfig</option> has been removed and replaced
|
||||
by <xref linkend="opt-services.unbound.settings"/>. <option>services.unbound.interfaces</option>
|
||||
has been renamed to <option>services.unbound.settings.server.interface</option>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>services.unbound.forwardAddresses</option> and
|
||||
<option>services.unbound.allowedAccess</option> have also been changed to
|
||||
use the new settings interface. You can follow the instructions when
|
||||
executing <literal>nixos-rebuild</literal> to upgrade your configuration to
|
||||
use the new interface.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
|
@ -972,6 +1017,24 @@ environment.systemPackages = [
|
|||
PostgreSQL 9.5 is scheduled EOL during the 21.05 life cycle and has been removed.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://www.xfce.org/">Xfce4</link> relies on
|
||||
GIO/GVfs for userspace virtual filesystem access in applications
|
||||
like <link xlink:href="https://docs.xfce.org/xfce/thunar/">thunar</link> and
|
||||
<link xlink:href="https://docs.xfce.org/apps/gigolo/">gigolo</link>.
|
||||
For that to work, the gvfs nixos service is enabled by default,
|
||||
and it can be configured with the specific package that provides
|
||||
GVfs. Until now Xfce4 was setting it to use a lighter version of
|
||||
GVfs (without support for samba). To avoid conflicts with other
|
||||
desktop environments this setting has been dropped. Users that
|
||||
still want it should add the following to their system
|
||||
configuration:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.gvfs.package" /> = pkgs.gvfs.override { samba = null; };
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
|
22
third_party/nixpkgs/nixos/lib/testing-python.nix
vendored
22
third_party/nixpkgs/nixos/lib/testing-python.nix
vendored
|
@ -54,8 +54,13 @@ rec {
|
|||
};
|
||||
|
||||
# Run an automated test suite in the given virtual network.
|
||||
# `driver' is the script that runs the network.
|
||||
runTests = driver:
|
||||
runTests = {
|
||||
# the script that runs the network
|
||||
driver,
|
||||
# a source position in the format of builtins.unsafeGetAttrPos
|
||||
# for meta.position
|
||||
pos,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "vm-test-run-${driver.testName}";
|
||||
|
||||
|
@ -69,6 +74,8 @@ rec {
|
|||
'';
|
||||
|
||||
passthru = driver.passthru;
|
||||
|
||||
inherit pos;
|
||||
};
|
||||
|
||||
|
||||
|
@ -79,6 +86,11 @@ rec {
|
|||
# Skip linting (mainly intended for faster dev cycles)
|
||||
, skipLint ? false
|
||||
, passthru ? {}
|
||||
, # For meta.position
|
||||
pos ? # position used in error messages and for meta.position
|
||||
(if t.meta.description or null != null
|
||||
then builtins.unsafeGetAttrPos "description" t.meta
|
||||
else builtins.unsafeGetAttrPos "testScript" t)
|
||||
, ...
|
||||
} @ t:
|
||||
let
|
||||
|
@ -131,10 +143,8 @@ rec {
|
|||
"it's currently ${toString testNameLen} characters long.")
|
||||
else
|
||||
"nixos-test-driver-${name}";
|
||||
|
||||
warn = if skipLint then lib.warn "Linting is disabled!" else lib.id;
|
||||
in
|
||||
warn (runCommand testDriverName
|
||||
lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
|
||||
{
|
||||
buildInputs = [ makeWrapper ];
|
||||
testScript = testScript';
|
||||
|
@ -176,7 +186,7 @@ rec {
|
|||
driver = mkDriver null;
|
||||
driverInteractive = mkDriver pkgs.qemu;
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
test = passMeta (runTests { inherit driver pos; });
|
||||
|
||||
nodeNames = builtins.attrNames driver.nodes;
|
||||
invalidNodeNames = lib.filter
|
||||
|
|
|
@ -41,7 +41,7 @@ in {
|
|||
|
||||
sizeMB = mkOption {
|
||||
type = with types; either (enum [ "auto" ]) int;
|
||||
default = "auto";
|
||||
default = if config.ec2.hvm then 2048 else 8192;
|
||||
example = 8192;
|
||||
description = "The size in MB of the image";
|
||||
};
|
||||
|
|
|
@ -126,6 +126,13 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
expandOnBoot = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to configure the sd image to expand it's partition on boot.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
@ -215,7 +222,7 @@ in
|
|||
'';
|
||||
}) {};
|
||||
|
||||
boot.postBootCommands = ''
|
||||
boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot ''
|
||||
# On the first boot do some maintenance tasks
|
||||
if [ -f /nix-path-registration ]; then
|
||||
set -euo pipefail
|
||||
|
|
|
@ -114,6 +114,9 @@
|
|||
./programs/autojump.nix
|
||||
./programs/bandwhich.nix
|
||||
./programs/bash/bash.nix
|
||||
./programs/bash/bash-completion.nix
|
||||
./programs/bash/ls-colors.nix
|
||||
./programs/bash/undistract-me.nix
|
||||
./programs/bash-my-aws.nix
|
||||
./programs/bcc.nix
|
||||
./programs/browserpass.nix
|
||||
|
@ -130,6 +133,7 @@
|
|||
./programs/droidcam.nix
|
||||
./programs/environment.nix
|
||||
./programs/evince.nix
|
||||
./programs/feedbackd.nix
|
||||
./programs/file-roller.nix
|
||||
./programs/firejail.nix
|
||||
./programs/fish.nix
|
||||
|
@ -163,6 +167,7 @@
|
|||
./programs/partition-manager.nix
|
||||
./programs/plotinus.nix
|
||||
./programs/proxychains.nix
|
||||
./programs/phosh.nix
|
||||
./programs/qt5ct.nix
|
||||
./programs/screen.nix
|
||||
./programs/sedutil.nix
|
||||
|
@ -469,6 +474,7 @@
|
|||
./services/misc/couchpotato.nix
|
||||
./services/misc/devmon.nix
|
||||
./services/misc/dictd.nix
|
||||
./services/misc/duckling.nix
|
||||
./services/misc/dwm-status.nix
|
||||
./services/misc/dysnomia.nix
|
||||
./services/misc/disnix.nix
|
||||
|
@ -508,6 +514,7 @@
|
|||
./services/misc/mame.nix
|
||||
./services/misc/matrix-appservice-discord.nix
|
||||
./services/misc/matrix-appservice-irc.nix
|
||||
./services/misc/matrix-dendrite.nix
|
||||
./services/misc/matrix-synapse.nix
|
||||
./services/misc/mautrix-telegram.nix
|
||||
./services/misc/mbpfan.nix
|
||||
|
@ -631,6 +638,7 @@
|
|||
./services/network-filesystems/xtreemfs.nix
|
||||
./services/network-filesystems/ceph.nix
|
||||
./services/networking/3proxy.nix
|
||||
./services/networking/adguardhome.nix
|
||||
./services/networking/amuled.nix
|
||||
./services/networking/aria2.nix
|
||||
./services/networking/asterisk.nix
|
||||
|
@ -973,6 +981,7 @@
|
|||
./services/web-servers/shellinabox.nix
|
||||
./services/web-servers/tomcat.nix
|
||||
./services/web-servers/traefik.nix
|
||||
./services/web-servers/trafficserver.nix
|
||||
./services/web-servers/ttyd.nix
|
||||
./services/web-servers/uwsgi.nix
|
||||
./services/web-servers/varnish/default.nix
|
||||
|
|
37
third_party/nixpkgs/nixos/modules/programs/bash/bash-completion.nix
vendored
Normal file
37
third_party/nixpkgs/nixos/modules/programs/bash/bash-completion.nix
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
enable = config.programs.bash.enableCompletion;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.enableCompletion = mkEnableOption "Bash completion for all interactive bash shells" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
# Check whether we're running a version of Bash that has support for
|
||||
# programmable completion. If we do, enable all modules installed in
|
||||
# the system and user profile in obsolete /etc/bash_completion.d/
|
||||
# directories. Bash loads completions in all
|
||||
# $XDG_DATA_DIRS/bash-completion/completions/
|
||||
# on demand, so they do not need to be sourced here.
|
||||
if shopt -q progcomp &>/dev/null; then
|
||||
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
|
||||
nullglobStatus=$(shopt -p nullglob)
|
||||
shopt -s nullglob
|
||||
for p in $NIX_PROFILES; do
|
||||
for m in "$p/etc/bash_completion.d/"*; do
|
||||
. $m
|
||||
done
|
||||
done
|
||||
eval "$nullglobStatus"
|
||||
unset nullglobStatus p m
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -11,31 +11,6 @@ let
|
|||
|
||||
cfg = config.programs.bash;
|
||||
|
||||
bashCompletion = optionalString cfg.enableCompletion ''
|
||||
# Check whether we're running a version of Bash that has support for
|
||||
# programmable completion. If we do, enable all modules installed in
|
||||
# the system and user profile in obsolete /etc/bash_completion.d/
|
||||
# directories. Bash loads completions in all
|
||||
# $XDG_DATA_DIRS/bash-completion/completions/
|
||||
# on demand, so they do not need to be sourced here.
|
||||
if shopt -q progcomp &>/dev/null; then
|
||||
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
|
||||
nullglobStatus=$(shopt -p nullglob)
|
||||
shopt -s nullglob
|
||||
for p in $NIX_PROFILES; do
|
||||
for m in "$p/etc/bash_completion.d/"*; do
|
||||
. $m
|
||||
done
|
||||
done
|
||||
eval "$nullglobStatus"
|
||||
unset nullglobStatus p m
|
||||
fi
|
||||
'';
|
||||
|
||||
lsColors = optionalString cfg.enableLsColors ''
|
||||
eval "$(${pkgs.coreutils}/bin/dircolors -b)"
|
||||
'';
|
||||
|
||||
bashAliases = concatStringsSep "\n" (
|
||||
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
|
||||
(filterAttrs (k: v: v != null) cfg.shellAliases)
|
||||
|
@ -123,20 +98,13 @@ in
|
|||
type = types.lines;
|
||||
};
|
||||
|
||||
enableCompletion = mkOption {
|
||||
default = true;
|
||||
promptPluginInit = mkOption {
|
||||
default = "";
|
||||
description = ''
|
||||
Enable Bash completion for all interactive bash shells.
|
||||
Shell script code used to initialise bash prompt plugins.
|
||||
'';
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
enableLsColors = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
Enable extra colors in directory listings.
|
||||
'';
|
||||
type = types.bool;
|
||||
type = types.lines;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -167,8 +135,7 @@ in
|
|||
set +h
|
||||
|
||||
${cfg.promptInit}
|
||||
${bashCompletion}
|
||||
${lsColors}
|
||||
${cfg.promptPluginInit}
|
||||
${bashAliases}
|
||||
|
||||
${cfge.interactiveShellInit}
|
||||
|
|
20
third_party/nixpkgs/nixos/modules/programs/bash/ls-colors.nix
vendored
Normal file
20
third_party/nixpkgs/nixos/modules/programs/bash/ls-colors.nix
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
enable = config.programs.bash.enableLsColors;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.enableLsColors = mkEnableOption "extra colors in directory listings" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
eval "$(${pkgs.coreutils}/bin/dircolors -b)"
|
||||
'';
|
||||
};
|
||||
}
|
36
third_party/nixpkgs/nixos/modules/programs/bash/undistract-me.nix
vendored
Normal file
36
third_party/nixpkgs/nixos/modules/programs/bash/undistract-me.nix
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.bash.undistractMe;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.undistractMe = {
|
||||
enable = mkEnableOption "notifications when long-running terminal commands complete";
|
||||
|
||||
playSound = mkEnableOption "notification sounds when long-running terminal commands complete";
|
||||
|
||||
timeout = mkOption {
|
||||
default = 10;
|
||||
description = ''
|
||||
Number of seconds it would take for a command to be considered long-running.
|
||||
'';
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
export LONG_RUNNING_COMMAND_TIMEOUT=${toString cfg.timeout}
|
||||
export UDM_PLAY_SOUND=${if cfg.playSound then "1" else "0"}
|
||||
. "${pkgs.undistract-me}/etc/profile.d/undistract-me.sh"
|
||||
'';
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with maintainers; [ metadark ];
|
||||
};
|
||||
}
|
|
@ -17,7 +17,7 @@ in {
|
|||
type = types.listOf types.str;
|
||||
description = "Nix top-level packages to be compiled using CCache";
|
||||
default = [];
|
||||
example = [ "wxGTK30" "qt48" "ffmpeg_3_3" "libav_all" ];
|
||||
example = [ "wxGTK30" "ffmpeg" "libav_all" ];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
32
third_party/nixpkgs/nixos/modules/programs/feedbackd.nix
vendored
Normal file
32
third_party/nixpkgs/nixos/modules/programs/feedbackd.nix
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.feedbackd;
|
||||
in {
|
||||
options = {
|
||||
programs.feedbackd = {
|
||||
enable = mkEnableOption ''
|
||||
Whether to enable the feedbackd D-BUS service and udev rules.
|
||||
|
||||
Your user needs to be in the `feedbackd` group to trigger effects.
|
||||
'';
|
||||
package = mkOption {
|
||||
description = ''
|
||||
Which feedbackd package to use.
|
||||
'';
|
||||
type = types.package;
|
||||
default = pkgs.feedbackd;
|
||||
};
|
||||
};
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.dbus.packages = [ cfg.package ];
|
||||
services.udev.packages = [ cfg.package ];
|
||||
|
||||
users.groups.feedbackd = {};
|
||||
};
|
||||
}
|
167
third_party/nixpkgs/nixos/modules/programs/phosh.nix
vendored
Normal file
167
third_party/nixpkgs/nixos/modules/programs/phosh.nix
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.phosh;
|
||||
|
||||
# Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop
|
||||
oskItem = pkgs.makeDesktopItem {
|
||||
name = "sm.puri.OSK0";
|
||||
type = "Application";
|
||||
desktopName = "On-screen keyboard";
|
||||
exec = "${pkgs.squeekboard}/bin/squeekboard";
|
||||
categories = "GNOME;Core;";
|
||||
extraEntries = ''
|
||||
OnlyShowIn=GNOME;
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=Panel
|
||||
X-GNOME-Provides=inputmethod
|
||||
X-GNOME-Autostart-Notify=true
|
||||
X-GNOME-AutoRestart=true
|
||||
'';
|
||||
};
|
||||
|
||||
phocConfigType = types.submodule {
|
||||
options = {
|
||||
xwayland = mkOption {
|
||||
description = ''
|
||||
Whether to enable XWayland support.
|
||||
|
||||
To start XWayland immediately, use `immediate`.
|
||||
'';
|
||||
type = types.enum [ "true" "false" "immediate" ];
|
||||
default = "false";
|
||||
};
|
||||
cursorTheme = mkOption {
|
||||
description = ''
|
||||
Cursor theme to use in Phosh.
|
||||
'';
|
||||
type = types.str;
|
||||
default = "default";
|
||||
};
|
||||
outputs = mkOption {
|
||||
description = ''
|
||||
Output configurations.
|
||||
'';
|
||||
type = types.attrsOf phocOutputType;
|
||||
default = {
|
||||
DSI-1 = {
|
||||
scale = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
phocOutputType = types.submodule {
|
||||
options = {
|
||||
modeline = mkOption {
|
||||
description = ''
|
||||
One or more modelines.
|
||||
'';
|
||||
type = types.either types.str (types.listOf types.str);
|
||||
default = [];
|
||||
example = [
|
||||
"87.25 720 776 848 976 1440 1443 1453 1493 -hsync +vsync"
|
||||
"65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync"
|
||||
];
|
||||
};
|
||||
mode = mkOption {
|
||||
description = ''
|
||||
Default video mode.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "768x1024";
|
||||
};
|
||||
scale = mkOption {
|
||||
description = ''
|
||||
Display scaling factor.
|
||||
'';
|
||||
type = types.nullOr types.ints.unsigned;
|
||||
default = null;
|
||||
example = 2;
|
||||
};
|
||||
rotate = mkOption {
|
||||
description = ''
|
||||
Screen transformation.
|
||||
'';
|
||||
type = types.enum [
|
||||
"90" "180" "270" "flipped" "flipped-90" "flipped-180" "flipped-270" null
|
||||
];
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
optionalKV = k: v: if v == null then "" else "${k} = ${builtins.toString v}";
|
||||
|
||||
renderPhocOutput = name: output: let
|
||||
modelines = if builtins.isList output.modeline
|
||||
then output.modeline
|
||||
else [ output.modeline ];
|
||||
renderModeline = l: "modeline = ${l}";
|
||||
in ''
|
||||
[output:${name}]
|
||||
${concatStringsSep "\n" (map renderModeline modelines)}
|
||||
${optionalKV "mode" output.mode}
|
||||
${optionalKV "scale" output.scale}
|
||||
${optionalKV "rotate" output.rotate}
|
||||
'';
|
||||
|
||||
renderPhocConfig = phoc: let
|
||||
outputs = mapAttrsToList renderPhocOutput phoc.outputs;
|
||||
in ''
|
||||
[core]
|
||||
xwayland = ${phoc.xwayland}
|
||||
${concatStringsSep "\n" outputs}
|
||||
[cursor]
|
||||
theme = ${phoc.cursorTheme}
|
||||
'';
|
||||
in {
|
||||
options = {
|
||||
programs.phosh = {
|
||||
enable = mkEnableOption ''
|
||||
Whether to enable, Phosh, related packages and default configurations.
|
||||
'';
|
||||
phocConfig = mkOption {
|
||||
description = ''
|
||||
Configurations for the Phoc compositor.
|
||||
'';
|
||||
type = types.oneOf [ types.lines types.path phocConfigType ];
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
pkgs.phoc
|
||||
pkgs.phosh
|
||||
pkgs.squeekboard
|
||||
oskItem
|
||||
];
|
||||
|
||||
programs.feedbackd.enable = true;
|
||||
|
||||
# https://source.puri.sm/Librem5/phosh/-/issues/303
|
||||
security.pam.services.phosh = {
|
||||
text = ''
|
||||
auth requisite pam_nologin.so
|
||||
auth required pam_succeed_if.so user != root quiet_success
|
||||
auth required pam_securetty.so
|
||||
auth requisite pam_nologin.so
|
||||
'';
|
||||
};
|
||||
|
||||
services.gnome3.core-shell.enable = true;
|
||||
services.gnome3.core-os-services.enable = true;
|
||||
services.xserver.displayManager.sessionPackages = [ pkgs.phosh ];
|
||||
|
||||
environment.etc."phosh/phoc.ini".source =
|
||||
if builtins.isPath cfg.phocConfig then cfg.phocConfig
|
||||
else if builtins.isString cfg.phocConfig then pkgs.writeText "phoc.ini" cfg.phocConfig
|
||||
else pkgs.writeText "phoc.ini" (renderPhocConfig cfg.phocConfig);
|
||||
};
|
||||
}
|
|
@ -145,7 +145,7 @@ in
|
|||
extraOpts = mkOption {
|
||||
description = "Kubernetes apiserver extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
extraSANs = mkOption {
|
||||
|
|
|
@ -38,7 +38,7 @@ in
|
|||
extraOpts = mkOption {
|
||||
description = "Kubernetes controller manager extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
|
|
@ -142,7 +142,7 @@ in
|
|||
extraOpts = mkOption {
|
||||
description = "Kubernetes kubelet extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
|
|
@ -25,7 +25,7 @@ in
|
|||
extraOpts = mkOption {
|
||||
description = "Kubernetes proxy extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
|
|
@ -21,7 +21,7 @@ in
|
|||
extraOpts = mkOption {
|
||||
description = "Kubernetes scheduler extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
|
|
@ -76,7 +76,7 @@ let
|
|||
};
|
||||
|
||||
tags = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
type = types.attrsOf (types.either types.str (types.listOf types.str));
|
||||
default = {};
|
||||
example = { queue = "default"; docker = "true"; ruby2 ="true"; };
|
||||
description = ''
|
||||
|
@ -230,7 +230,11 @@ in
|
|||
## don't end up in the Nix store.
|
||||
preStart = let
|
||||
sshDir = "${cfg.dataDir}/.ssh";
|
||||
tagStr = lib.concatStringsSep "," (lib.mapAttrsToList (name: value: "${name}=${value}") cfg.tags);
|
||||
tagStr = name: value:
|
||||
if lib.isList value
|
||||
then lib.concatStringsSep "," (builtins.map (v: "${name}=${v}") value)
|
||||
else "${name}=${value}";
|
||||
tagsStr = lib.concatStringsSep "," (lib.mapAttrsToList tagStr cfg.tags);
|
||||
in
|
||||
optionalString (cfg.privateSshKeyPath != null) ''
|
||||
mkdir -m 0700 -p "${sshDir}"
|
||||
|
@ -241,7 +245,7 @@ in
|
|||
token="$(cat ${toString cfg.tokenPath})"
|
||||
name="${cfg.name}"
|
||||
shell="${cfg.shell}"
|
||||
tags="${tagStr}"
|
||||
tags="${tagsStr}"
|
||||
build-path="${cfg.dataDir}/builds"
|
||||
hooks-path="${cfg.hooksPath}"
|
||||
${cfg.extraConfig}
|
||||
|
|
|
@ -1,12 +1,27 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
flip
|
||||
literalExample
|
||||
optionalAttrs
|
||||
optionals
|
||||
recursiveUpdate
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
types
|
||||
versionAtLeast
|
||||
;
|
||||
|
||||
cfg = config.services.cassandra;
|
||||
|
||||
defaultUser = "cassandra";
|
||||
cassandraConfig = flip recursiveUpdate cfg.extraConfig
|
||||
({ commitlog_sync = "batch";
|
||||
|
||||
cassandraConfig = flip recursiveUpdate cfg.extraConfig (
|
||||
{
|
||||
commitlog_sync = "batch";
|
||||
commitlog_sync_batch_window_in_ms = 2;
|
||||
start_native_transport = cfg.allowClients;
|
||||
cluster_name = cfg.clusterName;
|
||||
|
@ -15,17 +30,20 @@ let
|
|||
data_file_directories = [ "${cfg.homeDir}/data" ];
|
||||
commitlog_directory = "${cfg.homeDir}/commitlog";
|
||||
saved_caches_directory = "${cfg.homeDir}/saved_caches";
|
||||
} // (lib.optionalAttrs (cfg.seedAddresses != []) {
|
||||
seed_provider = [{
|
||||
} // optionalAttrs (cfg.seedAddresses != [ ]) {
|
||||
seed_provider = [
|
||||
{
|
||||
class_name = "org.apache.cassandra.locator.SimpleSeedProvider";
|
||||
parameters = [{ seeds = concatStringsSep "," cfg.seedAddresses; }];
|
||||
}];
|
||||
}) // (lib.optionalAttrs (lib.versionAtLeast cfg.package.version "3") {
|
||||
}
|
||||
];
|
||||
} // optionalAttrs (versionAtLeast cfg.package.version "3") {
|
||||
hints_directory = "${cfg.homeDir}/hints";
|
||||
})
|
||||
}
|
||||
);
|
||||
cassandraConfigWithAddresses = cassandraConfig //
|
||||
( if cfg.listenAddress == null
|
||||
|
||||
cassandraConfigWithAddresses = cassandraConfig // (
|
||||
if cfg.listenAddress == null
|
||||
then { listen_interface = cfg.listenInterface; }
|
||||
else { listen_address = cfg.listenAddress; }
|
||||
) // (
|
||||
|
@ -33,13 +51,17 @@ let
|
|||
then { rpc_interface = cfg.rpcInterface; }
|
||||
else { rpc_address = cfg.rpcAddress; }
|
||||
);
|
||||
cassandraEtc = pkgs.stdenv.mkDerivation
|
||||
{ name = "cassandra-etc";
|
||||
|
||||
cassandraEtc = pkgs.stdenv.mkDerivation {
|
||||
name = "cassandra-etc";
|
||||
|
||||
cassandraYaml = builtins.toJSON cassandraConfigWithAddresses;
|
||||
cassandraEnvPkg = "${cfg.package}/conf/cassandra-env.sh";
|
||||
cassandraLogbackConfig = pkgs.writeText "logback.xml" cfg.logbackConfig;
|
||||
|
||||
passAsFile = [ "extraEnvSh" ];
|
||||
inherit (cfg) extraEnvSh;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p "$out"
|
||||
|
||||
|
@ -58,22 +80,29 @@ let
|
|||
sed -i '/-Dcom.sun.management.jmxremote.password.file=\/etc\/cassandra\/jmxremote.password/d' "$out/cassandra-env.sh"
|
||||
'';
|
||||
};
|
||||
defaultJmxRolesFile = builtins.foldl'
|
||||
|
||||
defaultJmxRolesFile =
|
||||
builtins.foldl'
|
||||
(left: right: left + right) ""
|
||||
(map (role: "${role.username} ${role.password}") cfg.jmxRoles);
|
||||
fullJvmOptions = cfg.jvmOpts
|
||||
++ lib.optionals (cfg.jmxRoles != []) [
|
||||
|
||||
fullJvmOptions =
|
||||
cfg.jvmOpts
|
||||
++ optionals (cfg.jmxRoles != [ ]) [
|
||||
"-Dcom.sun.management.jmxremote.authenticate=true"
|
||||
"-Dcom.sun.management.jmxremote.password.file=${cfg.jmxRolesFile}"
|
||||
]
|
||||
++ lib.optionals cfg.remoteJmx [
|
||||
] ++ optionals cfg.remoteJmx [
|
||||
"-Djava.rmi.server.hostname=${cfg.rpcAddress}"
|
||||
];
|
||||
in {
|
||||
|
||||
in
|
||||
{
|
||||
options.services.cassandra = {
|
||||
|
||||
enable = mkEnableOption ''
|
||||
Apache Cassandra – Scalable and highly available database.
|
||||
'';
|
||||
|
||||
clusterName = mkOption {
|
||||
type = types.str;
|
||||
default = "Test Cluster";
|
||||
|
@ -83,16 +112,19 @@ in {
|
|||
another. All nodes in a cluster must have the same value.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
description = "Run Apache Cassandra under this user.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
description = "Run Apache Cassandra under this group.";
|
||||
};
|
||||
|
||||
homeDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/cassandra";
|
||||
|
@ -100,6 +132,7 @@ in {
|
|||
Home directory for Apache Cassandra.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.cassandra;
|
||||
|
@ -109,6 +142,7 @@ in {
|
|||
The Apache Cassandra package to use.
|
||||
'';
|
||||
};
|
||||
|
||||
jvmOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
|
@ -116,10 +150,11 @@ in {
|
|||
Populate the JVM_OPT environment variable.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "127.0.0.1";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Address or interface to bind to and tell other Cassandra nodes
|
||||
to connect to. You _must_ change this if you want multiple
|
||||
|
@ -136,6 +171,7 @@ in {
|
|||
Setting listen_address to 0.0.0.0 is always wrong.
|
||||
'';
|
||||
};
|
||||
|
||||
listenInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -146,10 +182,11 @@ in {
|
|||
supported.
|
||||
'';
|
||||
};
|
||||
|
||||
rpcAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "127.0.0.1";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
The address or interface to bind the native transport server to.
|
||||
|
||||
|
@ -167,6 +204,7 @@ in {
|
|||
internet. Firewall it if needed.
|
||||
'';
|
||||
};
|
||||
|
||||
rpcInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -176,6 +214,7 @@ in {
|
|||
correspond to a single address, IP aliasing is not supported.
|
||||
'';
|
||||
};
|
||||
|
||||
logbackConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
|
@ -197,6 +236,7 @@ in {
|
|||
XML logback configuration for cassandra
|
||||
'';
|
||||
};
|
||||
|
||||
seedAddresses = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.1" ];
|
||||
|
@ -207,6 +247,7 @@ in {
|
|||
Set to 127.0.0.1 for a single node cluster.
|
||||
'';
|
||||
};
|
||||
|
||||
allowClients = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -219,16 +260,19 @@ in {
|
|||
<literal>extraConfig</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = { };
|
||||
example =
|
||||
{ commitlog_sync_batch_window_in_ms = 3;
|
||||
{
|
||||
commitlog_sync_batch_window_in_ms = 3;
|
||||
};
|
||||
description = ''
|
||||
Extra options to be merged into cassandra.yaml as nix attribute set.
|
||||
'';
|
||||
};
|
||||
|
||||
extraEnvSh = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
|
@ -237,10 +281,11 @@ in {
|
|||
Extra shell lines to be appended onto cassandra-env.sh.
|
||||
'';
|
||||
};
|
||||
|
||||
fullRepairInterval = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "3w";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Set the interval how often full repairs are run, i.e.
|
||||
<literal>nodetool repair --full</literal> is executed. See
|
||||
|
@ -250,6 +295,7 @@ in {
|
|||
Set to <literal>null</literal> to disable full repairs.
|
||||
'';
|
||||
};
|
||||
|
||||
fullRepairOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
|
@ -258,10 +304,11 @@ in {
|
|||
Options passed through to the full repair command.
|
||||
'';
|
||||
};
|
||||
|
||||
incrementalRepairInterval = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "3d";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Set the interval how often incremental repairs are run, i.e.
|
||||
<literal>nodetool repair</literal> is executed. See
|
||||
|
@ -271,6 +318,7 @@ in {
|
|||
Set to <literal>null</literal> to disable incremental repairs.
|
||||
'';
|
||||
};
|
||||
|
||||
incrementalRepairOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
|
@ -279,6 +327,7 @@ in {
|
|||
Options passed through to the incremental repair command.
|
||||
'';
|
||||
};
|
||||
|
||||
maxHeapSize = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -299,6 +348,7 @@ in {
|
|||
expensive GC will be (usually).
|
||||
'';
|
||||
};
|
||||
|
||||
heapNewSize = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -322,6 +372,7 @@ in {
|
|||
100 MB per physical CPU core.
|
||||
'';
|
||||
};
|
||||
|
||||
mallocArenaMax = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
|
@ -330,6 +381,7 @@ in {
|
|||
Set this to control the amount of arenas per-thread in glibc.
|
||||
'';
|
||||
};
|
||||
|
||||
remoteJmx = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -341,6 +393,7 @@ in {
|
|||
See: https://wiki.apache.org/cassandra/JmxSecurity
|
||||
'';
|
||||
};
|
||||
|
||||
jmxPort = mkOption {
|
||||
type = types.int;
|
||||
default = 7199;
|
||||
|
@ -351,6 +404,7 @@ in {
|
|||
Firewall it if needed.
|
||||
'';
|
||||
};
|
||||
|
||||
jmxRoles = mkOption {
|
||||
default = [ ];
|
||||
description = ''
|
||||
|
@ -375,9 +429,11 @@ in {
|
|||
};
|
||||
});
|
||||
};
|
||||
|
||||
jmxRolesFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = if (lib.versionAtLeast cfg.package.version "3.11")
|
||||
default =
|
||||
if versionAtLeast cfg.package.version "3.11"
|
||||
then pkgs.writeText "jmx-roles-file" defaultJmxRolesFile
|
||||
else null;
|
||||
example = "/var/lib/cassandra/jmx.password";
|
||||
|
@ -391,17 +447,21 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions =
|
||||
[ { assertion = (cfg.listenAddress == null) != (cfg.listenInterface == null);
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.listenAddress == null) != (cfg.listenInterface == null);
|
||||
message = "You have to set either listenAddress or listenInterface";
|
||||
}
|
||||
{ assertion = (cfg.rpcAddress == null) != (cfg.rpcInterface == null);
|
||||
{
|
||||
assertion = (cfg.rpcAddress == null) != (cfg.rpcInterface == null);
|
||||
message = "You have to set either rpcAddress or rpcInterface";
|
||||
}
|
||||
{ assertion = (cfg.maxHeapSize == null) == (cfg.heapNewSize == null);
|
||||
{
|
||||
assertion = (cfg.maxHeapSize == null) == (cfg.heapNewSize == null);
|
||||
message = "If you set either of maxHeapSize or heapNewSize you have to set both";
|
||||
}
|
||||
{ assertion = cfg.remoteJmx -> cfg.jmxRolesFile != null;
|
||||
{
|
||||
assertion = cfg.remoteJmx -> cfg.jmxRolesFile != null;
|
||||
message = ''
|
||||
If you want JMX available remotely you need to set a password using
|
||||
<literal>jmxRoles</literal> or <literal>jmxRolesFile</literal> if
|
||||
|
@ -410,21 +470,21 @@ in {
|
|||
}
|
||||
];
|
||||
users = mkIf (cfg.user == defaultUser) {
|
||||
extraUsers.${defaultUser} =
|
||||
{ group = cfg.group;
|
||||
users.${defaultUser} = {
|
||||
group = cfg.group;
|
||||
home = cfg.homeDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.cassandra;
|
||||
description = "Cassandra service user";
|
||||
};
|
||||
extraGroups.${defaultUser}.gid = config.ids.gids.cassandra;
|
||||
groups.${defaultUser}.gid = config.ids.gids.cassandra;
|
||||
};
|
||||
|
||||
systemd.services.cassandra =
|
||||
{ description = "Apache Cassandra service";
|
||||
systemd.services.cassandra = {
|
||||
description = "Apache Cassandra service";
|
||||
after = [ "network.target" ];
|
||||
environment =
|
||||
{ CASSANDRA_CONF = "${cassandraEtc}";
|
||||
environment = {
|
||||
CASSANDRA_CONF = "${cassandraEtc}";
|
||||
JVM_OPTS = builtins.concatStringsSep " " fullJvmOptions;
|
||||
MAX_HEAP_SIZE = toString cfg.maxHeapSize;
|
||||
HEAP_NEWSIZE = toString cfg.heapNewSize;
|
||||
|
@ -433,60 +493,69 @@ in {
|
|||
JMX_PORT = toString cfg.jmxPort;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = "${cfg.package}/bin/cassandra -f";
|
||||
SuccessExitStatus = 143;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.cassandra-full-repair =
|
||||
{ description = "Perform a full repair on this Cassandra node";
|
||||
systemd.services.cassandra-full-repair = {
|
||||
description = "Perform a full repair on this Cassandra node";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
lib.concatStringsSep " "
|
||||
([ "${cfg.package}/bin/nodetool" "repair" "--full"
|
||||
concatStringsSep " "
|
||||
([
|
||||
"${cfg.package}/bin/nodetool"
|
||||
"repair"
|
||||
"--full"
|
||||
] ++ cfg.fullRepairOptions);
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.cassandra-full-repair =
|
||||
mkIf (cfg.fullRepairInterval != null) {
|
||||
description = "Schedule full repairs on Cassandra";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig =
|
||||
{ OnBootSec = cfg.fullRepairInterval;
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.fullRepairInterval;
|
||||
OnUnitActiveSec = cfg.fullRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.cassandra-incremental-repair =
|
||||
{ description = "Perform an incremental repair on this cassandra node.";
|
||||
systemd.services.cassandra-incremental-repair = {
|
||||
description = "Perform an incremental repair on this cassandra node.";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
lib.concatStringsSep " "
|
||||
([ "${cfg.package}/bin/nodetool" "repair"
|
||||
concatStringsSep " "
|
||||
([
|
||||
"${cfg.package}/bin/nodetool"
|
||||
"repair"
|
||||
] ++ cfg.incrementalRepairOptions);
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.cassandra-incremental-repair =
|
||||
mkIf (cfg.incrementalRepairInterval != null) {
|
||||
description = "Schedule incremental repairs on Cassandra";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig =
|
||||
{ OnBootSec = cfg.incrementalRepairInterval;
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.incrementalRepairInterval;
|
||||
OnUnitActiveSec = cfg.incrementalRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ roberth ];
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# Updating
|
||||
|
||||
1. Update the version & hash in pkgs/development/libraries/pipewire/default.nix
|
||||
2. run `nix build -f /path/to/nixpkgs/checkout pipewire pipewire.mediaSession`
|
||||
3. copy all JSON files from result/etc/pipewire and result-mediaSession/etc/pipewire/media-session.d to this directory
|
||||
4. add new files to the module config and passthru tests
|
|
@ -9,7 +9,7 @@
|
|||
],
|
||||
"actions": {
|
||||
"update-props": {
|
||||
"bluez5.reconnect-profiles": [
|
||||
"bluez5.auto-connect": [
|
||||
"hfp_hf",
|
||||
"hsp_hs",
|
||||
"a2dp_sink"
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
"with-pulseaudio": [
|
||||
"with-audio",
|
||||
"bluez5",
|
||||
"logind",
|
||||
"restore-stream",
|
||||
"streams-follow-default"
|
||||
]
|
||||
|
|
|
@ -30,7 +30,10 @@
|
|||
"args": {
|
||||
"server.address": [
|
||||
"unix:native"
|
||||
]
|
||||
],
|
||||
"vm.overrides": {
|
||||
"pulse.min.quantum": "1024/48000"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
"context.properties": {
|
||||
"link.max-buffers": 16,
|
||||
"core.daemon": true,
|
||||
"core.name": "pipewire-0"
|
||||
"core.name": "pipewire-0",
|
||||
"vm.overrides": {
|
||||
"default.clock.min-quantum": 1024
|
||||
}
|
||||
},
|
||||
"context.spa-libs": {
|
||||
"audio.convert.*": "audioconvert/libspa-audioconvert",
|
||||
|
|
|
@ -50,6 +50,7 @@ in
|
|||
|
||||
environment.etc."reader.conf".source = cfgFile;
|
||||
|
||||
environment.systemPackages = [ pkgs.pcsclite ];
|
||||
systemd.packages = [ (getBin pkgs.pcsclite) ];
|
||||
|
||||
systemd.sockets.pcscd.wantedBy = [ "sockets.target" ];
|
||||
|
@ -57,6 +58,16 @@ in
|
|||
systemd.services.pcscd = {
|
||||
environment.PCSCLITE_HP_DROPDIR = pluginEnv;
|
||||
restartTriggers = [ "/etc/reader.conf" ];
|
||||
|
||||
# If the cfgFile is empty and not specified (in which case the default
|
||||
# /etc/reader.conf is assumed), pcscd will happily start going through the
|
||||
# entire confdir (/etc in our case) looking for a config file and try to
|
||||
# parse everything it finds. Doesn't take a lot of imagination to see how
|
||||
# well that works. It really shouldn't do that to begin with, but to work
|
||||
# around it, we force the path to the cfgFile.
|
||||
#
|
||||
# https://github.com/NixOS/nixpkgs/issues/121088
|
||||
serviceConfig.ExecStart = [ "" "${getBin pkgs.pcsclite}/bin/pcscd -f -x -c ${cfgFile}" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ in {
|
|||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
TimeoutStopSec = 10;
|
||||
|
||||
ExecStart = "${pkgs.grafana-loki}/bin/promtail -config.file=${prettyJSON cfg.configuration} ${escapeShellArgs cfg.extraFlags}";
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ in {
|
|||
ReadWritePaths = [ cfg.keyPath ];
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
|
|
@ -773,7 +773,7 @@ in
|
|||
};
|
||||
|
||||
services.postfix.config = (mapAttrs (_: v: mkDefault v) {
|
||||
compatibility_level = "9999";
|
||||
compatibility_level = pkgs.postfix.version;
|
||||
mail_owner = cfg.user;
|
||||
default_privs = "nobody";
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ in
|
|||
StateDirectoryMode = "0700";
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
|
|
|
@ -118,7 +118,7 @@ in {
|
|||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
|
||||
${pkgs.jre8}/bin/java -Xmx${toString cfg.maxMemory}m \
|
||||
-Dairsonic.home=${cfg.home} \
|
||||
-Dserver.address=${cfg.listenAddress} \
|
||||
-Dserver.port=${toString cfg.port} \
|
||||
|
|
39
third_party/nixpkgs/nixos/modules/services/misc/duckling.nix
vendored
Normal file
39
third_party/nixpkgs/nixos/modules/services/misc/duckling.nix
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.duckling;
|
||||
in {
|
||||
options = {
|
||||
services.duckling = {
|
||||
enable = mkEnableOption "duckling";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Port on which duckling will run.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.duckling = {
|
||||
description = "Duckling server service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
environment = {
|
||||
PORT = builtins.toString cfg.port;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.haskellPackages.duckling}/bin/duckling-example-exe --no-access-log --no-error-log";
|
||||
Restart = "always";
|
||||
DynamicUser = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -477,6 +477,7 @@ in
|
|||
in ''
|
||||
# copy custom configuration and generate a random secret key if needed
|
||||
${optionalString (cfg.useWizard == false) ''
|
||||
function gitea_setup {
|
||||
cp -f ${configFile} ${runConfig}
|
||||
|
||||
if [ ! -e ${secretKey} ]; then
|
||||
|
@ -517,7 +518,8 @@ in
|
|||
-e "s,#internaltoken#,$INTERNALTOKEN,g" \
|
||||
-e "s,#mailerpass#,$MAILERPASSWORD,g" \
|
||||
-i ${runConfig}
|
||||
chmod 640 ${runConfig} ${secretKey} ${oauth2JwtSecret} ${lfsJwtSecret} ${internalToken}
|
||||
}
|
||||
(umask 027; gitea_setup)
|
||||
''}
|
||||
|
||||
# update all hooks' binary paths
|
||||
|
|
|
@ -155,6 +155,7 @@ let
|
|||
GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "redis.yml" (builtins.toJSON redisConfig);
|
||||
prometheus_multiproc_dir = "/run/gitlab";
|
||||
RAILS_ENV = "production";
|
||||
MALLOC_ARENA_MAX = "2";
|
||||
};
|
||||
|
||||
gitlab-rake = pkgs.stdenv.mkDerivation {
|
||||
|
@ -588,7 +589,7 @@ in {
|
|||
the DB. If you change or lose this key you will be unable to
|
||||
access variables stored in database.
|
||||
|
||||
Make sure the secret is at least 30 characters and all random,
|
||||
Make sure the secret is at least 32 characters and all random,
|
||||
no regular words or you'll be exposed to dictionary attacks.
|
||||
|
||||
This should be a string, not a nix path, since nix paths are
|
||||
|
@ -604,7 +605,7 @@ in {
|
|||
the DB. If you change or lose this key you will be unable to
|
||||
access variables stored in database.
|
||||
|
||||
Make sure the secret is at least 30 characters and all random,
|
||||
Make sure the secret is at least 32 characters and all random,
|
||||
no regular words or you'll be exposed to dictionary attacks.
|
||||
|
||||
This should be a string, not a nix path, since nix paths are
|
||||
|
@ -620,7 +621,7 @@ in {
|
|||
tokens. If you change or lose this key, users which have 2FA
|
||||
enabled for login won't be able to login anymore.
|
||||
|
||||
Make sure the secret is at least 30 characters and all random,
|
||||
Make sure the secret is at least 32 characters and all random,
|
||||
no regular words or you'll be exposed to dictionary attacks.
|
||||
|
||||
This should be a string, not a nix path, since nix paths are
|
||||
|
@ -652,6 +653,105 @@ in {
|
|||
description = "Extra configuration to merge into shell-config.yml";
|
||||
};
|
||||
|
||||
puma.workers = mkOption {
|
||||
type = types.int;
|
||||
default = 2;
|
||||
apply = x: builtins.toString x;
|
||||
description = ''
|
||||
The number of worker processes Puma should spawn. This
|
||||
controls the amount of parallel Ruby code can be
|
||||
executed. GitLab recommends <quote>Number of CPU cores -
|
||||
1</quote>, but at least two.
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Each worker consumes quite a bit of memory, so
|
||||
be careful when increasing this.
|
||||
</para>
|
||||
</note>
|
||||
'';
|
||||
};
|
||||
|
||||
puma.threadsMin = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
apply = x: builtins.toString x;
|
||||
description = ''
|
||||
The minimum number of threads Puma should use per
|
||||
worker.
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Each thread consumes memory and contributes to Global VM
|
||||
Lock contention, so be careful when increasing this.
|
||||
</para>
|
||||
</note>
|
||||
'';
|
||||
};
|
||||
|
||||
puma.threadsMax = mkOption {
|
||||
type = types.int;
|
||||
default = 4;
|
||||
apply = x: builtins.toString x;
|
||||
description = ''
|
||||
The maximum number of threads Puma should use per
|
||||
worker. This limits how many threads Puma will automatically
|
||||
spawn in response to requests. In contrast to workers,
|
||||
threads will never be able to run Ruby code in parallel, but
|
||||
give higher IO parallelism.
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Each thread consumes memory and contributes to Global VM
|
||||
Lock contention, so be careful when increasing this.
|
||||
</para>
|
||||
</note>
|
||||
'';
|
||||
};
|
||||
|
||||
sidekiq.memoryKiller.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether the Sidekiq MemoryKiller should be turned
|
||||
on. MemoryKiller kills Sidekiq when its memory consumption
|
||||
exceeds a certain limit.
|
||||
|
||||
See <link xlink:href="https://docs.gitlab.com/ee/administration/operations/sidekiq_memory_killer.html"/>
|
||||
for details.
|
||||
'';
|
||||
};
|
||||
|
||||
sidekiq.memoryKiller.maxMemory = mkOption {
|
||||
type = types.int;
|
||||
default = 2000;
|
||||
apply = x: builtins.toString (x * 1024);
|
||||
description = ''
|
||||
The maximum amount of memory, in MiB, a Sidekiq worker is
|
||||
allowed to consume before being killed.
|
||||
'';
|
||||
};
|
||||
|
||||
sidekiq.memoryKiller.graceTime = mkOption {
|
||||
type = types.int;
|
||||
default = 900;
|
||||
apply = x: builtins.toString x;
|
||||
description = ''
|
||||
The time MemoryKiller waits after noticing excessive memory
|
||||
consumption before killing Sidekiq.
|
||||
'';
|
||||
};
|
||||
|
||||
sidekiq.memoryKiller.shutdownWait = mkOption {
|
||||
type = types.int;
|
||||
default = 30;
|
||||
apply = x: builtins.toString x;
|
||||
description = ''
|
||||
The time allowed for all jobs to finish before Sidekiq is
|
||||
killed forcefully.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
|
@ -993,7 +1093,11 @@ in {
|
|||
] ++ optional (cfg.databaseHost == "") "postgresql.service";
|
||||
wantedBy = [ "gitlab.target" ];
|
||||
partOf = [ "gitlab.target" ];
|
||||
environment = gitlabEnv;
|
||||
environment = gitlabEnv // (optionalAttrs cfg.sidekiq.memoryKiller.enable {
|
||||
SIDEKIQ_MEMORY_KILLER_MAX_RSS = cfg.sidekiq.memoryKiller.maxMemory;
|
||||
SIDEKIQ_MEMORY_KILLER_GRACE_TIME = cfg.sidekiq.memoryKiller.graceTime;
|
||||
SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT = cfg.sidekiq.memoryKiller.shutdownWait;
|
||||
});
|
||||
path = with pkgs; [
|
||||
postgresqlPackage
|
||||
git
|
||||
|
@ -1005,13 +1109,15 @@ in {
|
|||
# Needed for GitLab project imports
|
||||
gnutar
|
||||
gzip
|
||||
|
||||
procps # Sidekiq MemoryKiller
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
TimeoutSec = "infinity";
|
||||
Restart = "on-failure";
|
||||
Restart = "always";
|
||||
WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
|
||||
ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production";
|
||||
};
|
||||
|
@ -1145,7 +1251,13 @@ in {
|
|||
TimeoutSec = "infinity";
|
||||
Restart = "on-failure";
|
||||
WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
|
||||
ExecStart = "${cfg.packages.gitlab.rubyEnv}/bin/puma -C ${cfg.statePath}/config/puma.rb -e production";
|
||||
ExecStart = concatStringsSep " " [
|
||||
"${cfg.packages.gitlab.rubyEnv}/bin/puma"
|
||||
"-e production"
|
||||
"-C ${cfg.statePath}/config/puma.rb"
|
||||
"-w ${cfg.puma.workers}"
|
||||
"-t ${cfg.puma.threadsMin}:${cfg.puma.threadsMax}"
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -245,22 +245,85 @@ in {
|
|||
rm -f "${cfg.configDir}/ui-lovelace.yaml"
|
||||
ln -s ${lovelaceConfigFile} "${cfg.configDir}/ui-lovelace.yaml"
|
||||
'');
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
|
||||
serviceConfig = let
|
||||
# List of capabilities to equip home-assistant with, depending on configured components
|
||||
capabilities = [
|
||||
# Empty string first, so we will never accidentally have an empty capability bounding set
|
||||
# https://github.com/NixOS/nixpkgs/issues/120617#issuecomment-830685115
|
||||
""
|
||||
] ++ (unique (optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||
# Required for interaction with hci devices and bluetooth sockets
|
||||
# https://www.home-assistant.io/integrations/bluetooth_le_tracker/#rootless-setup-on-core-installs
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_RAW"
|
||||
] ++ lib.optionals (useComponent "emulated_hue") [
|
||||
# Alexa looks for the service on port 80
|
||||
# https://www.home-assistant.io/integrations/emulated_hue
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
] ++ lib.optionals (useComponent "nmap_tracker") [
|
||||
# https://www.home-assistant.io/integrations/nmap_tracker#linux-capabilities
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
"CAP_NET_RAW"
|
||||
]));
|
||||
in {
|
||||
ExecStart = "${package}/bin/hass --runner --config '${cfg.configDir}'";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
User = "hass";
|
||||
Group = "hass";
|
||||
Restart = "on-failure";
|
||||
RestartForceExitStatus = "100";
|
||||
SuccessExitStatus = "100";
|
||||
KillSignal = "SIGINT";
|
||||
|
||||
# Hardening
|
||||
AmbientCapabilities = capabilities;
|
||||
CapabilityBoundingSet = capabilities;
|
||||
DeviceAllow = [
|
||||
"char-ttyACM rw"
|
||||
"char-ttyAMA rw"
|
||||
"char-ttyUSB rw"
|
||||
];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false; # prevents gaining capabilities in the host namespace
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
RemoveIPC = true;
|
||||
ReadWritePaths = let
|
||||
# Allow rw access to explicitly configured paths
|
||||
cfgPath = [ "config" "homeassistant" "allowlist_external_dirs" ];
|
||||
value = attrByPath cfgPath [] cfg;
|
||||
allowPaths = if isList value then value else singleton value;
|
||||
in [ "${cfg.configDir}" ] ++ allowPaths;
|
||||
KillSignal = "SIGINT";
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
AmbientCapabilities = "cap_net_raw,cap_net_admin+eip";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
] ++ optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||
"AF_BLUETOOTH"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SupplementaryGroups = [ "dialout" ];
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
path = [
|
||||
"/run/wrappers" # needed for ping
|
||||
|
@ -278,7 +341,6 @@ in {
|
|||
home = cfg.configDir;
|
||||
createHome = true;
|
||||
group = "hass";
|
||||
extraGroups = [ "dialout" ];
|
||||
uid = config.ids.uids.hass;
|
||||
};
|
||||
|
||||
|
|
181
third_party/nixpkgs/nixos/modules/services/misc/matrix-dendrite.nix
vendored
Normal file
181
third_party/nixpkgs/nixos/modules/services/misc/matrix-dendrite.nix
vendored
Normal file
|
@ -0,0 +1,181 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.matrix-dendrite;
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
configurationYaml = settingsFormat.generate "dendrite.yaml" cfg.settings;
|
||||
workingDir = "/var/lib/matrix-dendrite";
|
||||
in
|
||||
{
|
||||
options.services.matrix-dendrite = {
|
||||
enable = lib.mkEnableOption "matrix.org dendrite";
|
||||
httpPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = 8008;
|
||||
description = ''
|
||||
The port to listen for HTTP requests on.
|
||||
'';
|
||||
};
|
||||
httpsPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
description = ''
|
||||
The port to listen for HTTPS requests on.
|
||||
'';
|
||||
};
|
||||
tlsCert = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/server.cert";
|
||||
default = null;
|
||||
description = ''
|
||||
The path to the TLS certificate.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
tlsKey = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/server.key";
|
||||
default = null;
|
||||
description = ''
|
||||
The path to the TLS key.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/registration_secret";
|
||||
default = null;
|
||||
description = ''
|
||||
Environment file as defined in <citerefentry>
|
||||
<refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
|
||||
</citerefentry>.
|
||||
Secrets may be passed to the service without adding them to the world-readable
|
||||
Nix store, by specifying placeholder variables as the option value in Nix and
|
||||
setting these variables accordingly in the environment file. Currently only used
|
||||
for the registration secret to allow secure registration when
|
||||
client_api.registration_disabled is true.
|
||||
|
||||
<programlisting>
|
||||
# snippet of dendrite-related config
|
||||
services.matrix-dendrite.settings.client_api.registration_shared_secret = "$REGISTRATION_SHARED_SECRET";
|
||||
</programlisting>
|
||||
|
||||
<programlisting>
|
||||
# content of the environment file
|
||||
REGISTRATION_SHARED_SECRET=verysecretpassword
|
||||
</programlisting>
|
||||
|
||||
Note that this file needs to be available on the host on which
|
||||
<literal>dendrite</literal> is running.
|
||||
'';
|
||||
};
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options.global = {
|
||||
server_name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "example.com";
|
||||
description = ''
|
||||
The domain name of the server, with optional explicit port.
|
||||
This is used by remote servers to connect to this server.
|
||||
This is also the last part of your UserID.
|
||||
'';
|
||||
};
|
||||
private_key = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
example = "${workingDir}/matrix_key.pem";
|
||||
description = ''
|
||||
The path to the signing private key file, used to sign
|
||||
requests and events.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --private-key matrix_key.pem"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
trusted_third_party_id_servers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
example = [ "matrix.org" ];
|
||||
default = [ "matrix.org" "vector.im" ];
|
||||
description = ''
|
||||
Lists of domains that the server will trust as identity
|
||||
servers to verify third party identifiers such as phone
|
||||
numbers and email addresses
|
||||
'';
|
||||
};
|
||||
};
|
||||
options.client_api = {
|
||||
registration_disabled = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to disable user registration to the server
|
||||
without the shared secret.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for dendrite, see:
|
||||
<link xlink:href="https://github.com/matrix-org/dendrite/blob/master/dendrite-config.yaml"/>
|
||||
for available options with which to populate settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [{
|
||||
assertion = cfg.httpsPort != null -> (cfg.tlsCert != null && cfg.tlsKey != null);
|
||||
message = ''
|
||||
If Dendrite is configured to use https, tlsCert and tlsKey must be provided.
|
||||
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
'';
|
||||
}];
|
||||
|
||||
systemd.services.matrix-dendrite = {
|
||||
description = "Dendrite Matrix homeserver";
|
||||
after = [
|
||||
"network.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "matrix-dendrite";
|
||||
WorkingDirectory = workingDir;
|
||||
RuntimeDirectory = "matrix-dendrite";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
ExecStartPre =
|
||||
if (cfg.environmentFile != null) then ''
|
||||
${pkgs.envsubst}/bin/envsubst \
|
||||
-i ${configurationYaml} \
|
||||
-o /run/matrix-dendrite/dendrite.yaml
|
||||
'' else ''
|
||||
${pkgs.coreutils}/bin/cp ${configurationYaml} /run/matrix-dendrite/dendrite.yaml
|
||||
'';
|
||||
ExecStart = lib.strings.concatStringsSep " " ([
|
||||
"${pkgs.matrix-dendrite}/bin/dendrite-monolith-server"
|
||||
"--config /run/matrix-dendrite/dendrite.yaml"
|
||||
] ++ lib.optionals (cfg.httpPort != null) [
|
||||
"--http-bind-address :${builtins.toString cfg.httpPort}"
|
||||
] ++ lib.optionals (cfg.httpsPort != null) [
|
||||
"--https-bind-address :${builtins.toString cfg.httpsPort}"
|
||||
"--tls-cert ${cfg.tlsCert}"
|
||||
"--tls-key ${cfg.tlsKey}"
|
||||
]);
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
meta.maintainers = lib.teams.matrix.members;
|
||||
}
|
|
@ -70,6 +70,7 @@ in {
|
|||
|
||||
users.users = mkIf (cfg.user == "ombi") {
|
||||
ombi = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
home = cfg.dataDir;
|
||||
};
|
||||
|
|
|
@ -24,55 +24,80 @@ in
|
|||
Your <filename>pinnwand.toml</filename> as a Nix attribute set. Look up
|
||||
possible options in the <link xlink:href="https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example">pinnwand.toml-example</link>.
|
||||
'';
|
||||
default = {
|
||||
# https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example
|
||||
database_uri = "sqlite:///var/lib/pinnwand/pinnwand.db";
|
||||
preferred_lexeres = [];
|
||||
paste_size = 262144;
|
||||
paste_help = ''
|
||||
<p>Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.</p><p>People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.</p>
|
||||
'';
|
||||
footer = ''
|
||||
View <a href="//github.com/supakeen/pinnwand" target="_BLANK">source code</a>, the <a href="/removal">removal</a> or <a href="/expiry">expiry</a> stories, or read the <a href="/about">about</a> page.
|
||||
'';
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.pinnwand = {
|
||||
description = "Pinnwannd HTTP Server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
services.pinnwand.settings = {
|
||||
database_uri = mkDefault "sqlite:////var/lib/pinnwand/pinnwand.db";
|
||||
paste_size = mkDefault 262144;
|
||||
paste_help = mkDefault ''
|
||||
<p>Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.</p><p>People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.</p>
|
||||
'';
|
||||
footer = mkDefault ''
|
||||
View <a href="//github.com/supakeen/pinnwand" target="_BLANK">source code</a>, the <a href="/removal">removal</a> or <a href="/expiry">expiry</a> stories, or read the <a href="/about">about</a> page.
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services = let
|
||||
hardeningOptions = {
|
||||
User = "pinnwand";
|
||||
DynamicUser = true;
|
||||
|
||||
unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/";
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile} http --port ${toString(cfg.port)}";
|
||||
StateDirectory = "pinnwand";
|
||||
StateDirectoryMode = "0700";
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
DynamicUser = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
ProtectProc = "invisible";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "0077";
|
||||
};
|
||||
|
||||
command = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile}";
|
||||
in {
|
||||
pinnwand = {
|
||||
description = "Pinnwannd HTTP Server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/";
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${command} http --port ${toString(cfg.port)}";
|
||||
} // hardeningOptions;
|
||||
};
|
||||
|
||||
pinnwand-reaper = {
|
||||
description = "Pinnwand Reaper";
|
||||
startAt = "daily";
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${command} -vvvv reap"; # verbosity increased to show number of deleted pastes
|
||||
} // hardeningOptions;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,29 +5,17 @@ with lib;
|
|||
let
|
||||
cfg = config.services.zigbee2mqtt;
|
||||
|
||||
configJSON = pkgs.writeText "configuration.json"
|
||||
(builtins.toJSON (recursiveUpdate defaultConfig cfg.config));
|
||||
configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
|
||||
${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
|
||||
'';
|
||||
format = pkgs.formats.yaml { };
|
||||
configFile = format.generate "zigbee2mqtt.yaml" cfg.settings;
|
||||
|
||||
# the default config contains all required settings,
|
||||
# so the service starts up without crashing.
|
||||
defaultConfig = {
|
||||
homeassistant = false;
|
||||
permit_join = false;
|
||||
mqtt = {
|
||||
base_topic = "zigbee2mqtt";
|
||||
server = "mqtt://localhost:1883";
|
||||
};
|
||||
serial.port = "/dev/ttyACM0";
|
||||
# put device configuration into separate file because configuration.yaml
|
||||
# is copied from the store on startup
|
||||
devices = "devices.yaml";
|
||||
};
|
||||
in
|
||||
{
|
||||
meta.maintainers = with maintainers; [ sweber ];
|
||||
meta.maintainers = with maintainers; [ sweber hexa ];
|
||||
|
||||
imports = [
|
||||
# Remove warning before the 21.11 release
|
||||
(mkRenamedOptionModule [ "services" "zigbee2mqtt" "config" ] [ "services" "zigbee2mqtt" "settings" ])
|
||||
];
|
||||
|
||||
options.services.zigbee2mqtt = {
|
||||
enable = mkEnableOption "enable zigbee2mqtt service";
|
||||
|
@ -37,7 +25,11 @@ in
|
|||
default = pkgs.zigbee2mqtt.override {
|
||||
dataDir = cfg.dataDir;
|
||||
};
|
||||
defaultText = "pkgs.zigbee2mqtt";
|
||||
defaultText = literalExample ''
|
||||
pkgs.zigbee2mqtt {
|
||||
dataDir = services.zigbee2mqtt.dataDir
|
||||
}
|
||||
'';
|
||||
type = types.package;
|
||||
};
|
||||
|
||||
|
@ -47,9 +39,9 @@ in
|
|||
type = types.path;
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
settings = mkOption {
|
||||
type = format.type;
|
||||
default = {};
|
||||
type = with types; nullOr attrs;
|
||||
example = literalExample ''
|
||||
{
|
||||
homeassistant = config.services.home-assistant.enable;
|
||||
|
@ -61,11 +53,28 @@ in
|
|||
'';
|
||||
description = ''
|
||||
Your <filename>configuration.yaml</filename> as a Nix attribute set.
|
||||
Check the <link xlink:href="https://www.zigbee2mqtt.io/information/configuration.html">documentation</link>
|
||||
for possible options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable) {
|
||||
|
||||
# preset config values
|
||||
services.zigbee2mqtt.settings = {
|
||||
homeassistant = mkDefault config.services.home-assistant.enable;
|
||||
permit_join = mkDefault false;
|
||||
mqtt = {
|
||||
base_topic = mkDefault "zigbee2mqtt";
|
||||
server = mkDefault "mqtt://localhost:1883";
|
||||
};
|
||||
serial.port = mkDefault "/dev/ttyACM0";
|
||||
# reference device configuration, that is kept in a separate file
|
||||
# to prevent it being overwritten in the units ExecStartPre script
|
||||
devices = mkDefault "devices.yaml";
|
||||
};
|
||||
|
||||
systemd.services.zigbee2mqtt = {
|
||||
description = "Zigbee2mqtt Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
@ -76,10 +85,48 @@ in
|
|||
User = "zigbee2mqtt";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
Restart = "on-failure";
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
DeviceAllow = [
|
||||
config.services.zigbee2mqtt.settings.serial.port
|
||||
];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = false;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = false; # prevents access to /dev/serial, because it is set 0700 root:root
|
||||
PrivateUsers = true;
|
||||
PrivateTmp = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SupplementaryGroups = [
|
||||
"dialout"
|
||||
];
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
preStart = ''
|
||||
cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
|
||||
|
@ -90,7 +137,6 @@ in
|
|||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
group = "zigbee2mqtt";
|
||||
extraGroups = [ "dialout" ];
|
||||
uid = config.ids.uids.zigbee2mqtt;
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ let
|
|||
"surfboard"
|
||||
"systemd"
|
||||
"tor"
|
||||
"unbound"
|
||||
"unifi"
|
||||
"unifi-poller"
|
||||
"varnish"
|
||||
|
|
59
third_party/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix
vendored
Normal file
59
third_party/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unbound.nix
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.unbound;
|
||||
in
|
||||
{
|
||||
port = 9167;
|
||||
extraOpts = {
|
||||
fetchType = mkOption {
|
||||
# TODO: add shm when upstream implemented it
|
||||
type = types.enum [ "tcp" "uds" ];
|
||||
default = "uds";
|
||||
description = ''
|
||||
Which methods the exporter uses to get the information from unbound.
|
||||
'';
|
||||
};
|
||||
|
||||
telemetryPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/metrics";
|
||||
description = ''
|
||||
Path under which to expose metrics.
|
||||
'';
|
||||
};
|
||||
|
||||
controlInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/run/unbound/unbound.socket";
|
||||
description = ''
|
||||
Path to the unbound socket for uds mode or the control interface port for tcp mode.
|
||||
|
||||
Example:
|
||||
uds-mode: /run/unbound/unbound.socket
|
||||
tcp-mode: 127.0.0.1:8953
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
serviceOpts = mkMerge ([{
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.prometheus-unbound-exporter}/bin/unbound-telemetry \
|
||||
${cfg.fetchType} \
|
||||
--bind ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--path ${cfg.telemetryPath} \
|
||||
${optionalString (cfg.controlInterface != null) "--control-interface ${cfg.controlInterface}"} \
|
||||
${toString cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
}] ++ [
|
||||
(mkIf config.services.unbound.enable {
|
||||
after = [ "unbound.service" ];
|
||||
requires = [ "unbound.service" ];
|
||||
})
|
||||
]);
|
||||
}
|
78
third_party/nixpkgs/nixos/modules/services/networking/adguardhome.nix
vendored
Normal file
78
third_party/nixpkgs/nixos/modules/services/networking/adguardhome.nix
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.adguardhome;
|
||||
|
||||
args = concatStringsSep " " ([
|
||||
"--no-check-update"
|
||||
"--pidfile /run/AdGuardHome/AdGuardHome.pid"
|
||||
"--work-dir /var/lib/AdGuardHome/"
|
||||
"--config /var/lib/AdGuardHome/AdGuardHome.yaml"
|
||||
"--host ${cfg.host}"
|
||||
"--port ${toString cfg.port}"
|
||||
] ++ cfg.extraArgs);
|
||||
|
||||
in
|
||||
{
|
||||
options.services.adguardhome = with types; {
|
||||
enable = mkEnableOption "AdGuard Home network-wide ad blocker";
|
||||
|
||||
host = mkOption {
|
||||
default = "0.0.0.0";
|
||||
type = str;
|
||||
description = ''
|
||||
Host address to bind HTTP server to.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
default = 3000;
|
||||
type = port;
|
||||
description = ''
|
||||
Port to serve HTTP pages on.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
default = false;
|
||||
type = bool;
|
||||
description = ''
|
||||
Open ports in the firewall for the AdGuard Home web interface. Does not
|
||||
open the port needed to access the DNS resolver.
|
||||
'';
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
default = [ ];
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Extra command line parameters to be passed to the adguardhome binary.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.adguardhome = {
|
||||
description = "AdGuard Home: Network-level blocker";
|
||||
after = [ "syslog.target" "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
unitConfig = {
|
||||
StartLimitIntervalSec = 5;
|
||||
StartLimitBurst = 10;
|
||||
};
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = "${pkgs.adguardhome}/bin/adguardhome ${args}";
|
||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
RuntimeDirectory = "AdGuardHome";
|
||||
StateDirectory = "AdGuardHome";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||||
};
|
||||
}
|
|
@ -32,6 +32,8 @@ in
|
|||
|
||||
{
|
||||
|
||||
meta.maintainers = with maintainers; [ hexa ];
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
|
|
@ -8,9 +8,13 @@ let
|
|||
|
||||
bindUser = "named";
|
||||
|
||||
bindZoneOptions = {
|
||||
bindZoneCoerce = list: builtins.listToAttrs (lib.forEach list (zone: { name = zone.name; value = zone; }));
|
||||
|
||||
bindZoneOptions = { name, config, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = "Name of the zone.";
|
||||
};
|
||||
master = mkOption {
|
||||
|
@ -36,6 +40,7 @@ let
|
|||
default = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
confFile = pkgs.writeText "named.conf"
|
||||
''
|
||||
|
@ -84,7 +89,7 @@ let
|
|||
${extraConfig}
|
||||
};
|
||||
'')
|
||||
cfg.zones }
|
||||
(attrValues cfg.zones) }
|
||||
'';
|
||||
|
||||
in
|
||||
|
@ -153,18 +158,19 @@ in
|
|||
|
||||
zones = mkOption {
|
||||
default = [];
|
||||
type = types.listOf (types.submodule [ { options = bindZoneOptions; } ]);
|
||||
type = with types; coercedTo (listOf attrs) bindZoneCoerce (attrsOf (types.submodule bindZoneOptions));
|
||||
description = "
|
||||
List of zones we claim authority over.
|
||||
";
|
||||
example = [{
|
||||
name = "example.com";
|
||||
example = {
|
||||
"example.com" = {
|
||||
master = false;
|
||||
file = "/var/dns/example.com";
|
||||
masters = ["192.168.0.1"];
|
||||
slaves = [];
|
||||
extraConfig = "";
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
|
|
|
@ -29,8 +29,6 @@ let
|
|||
+ concatMapStrings (mkListen "doh2") cfg.listenDoH
|
||||
+ cfg.extraConfig
|
||||
);
|
||||
|
||||
package = pkgs.knot-resolver;
|
||||
in {
|
||||
meta.maintainers = [ maintainers.vcunat /* upstream developer */ ];
|
||||
|
||||
|
@ -58,6 +56,15 @@ in {
|
|||
and give commands interactively to kresd@1.service.
|
||||
'';
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = "
|
||||
knot-resolver package to use.
|
||||
";
|
||||
default = pkgs.knot-resolver;
|
||||
defaultText = "pkgs.knot-resolver";
|
||||
example = literalExample "pkgs.knot-resolver.override { extraFeatures = true; }";
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
|
@ -115,7 +122,7 @@ in {
|
|||
};
|
||||
users.groups.knot-resolver.gid = null;
|
||||
|
||||
systemd.packages = [ package ]; # the units are patched inside the package a bit
|
||||
systemd.packages = [ cfg.package ]; # the units are patched inside the package a bit
|
||||
|
||||
systemd.targets.kresd = { # configure units started by default
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
@ -123,8 +130,8 @@ in {
|
|||
++ map (i: "kresd@${toString i}.service") (range 1 cfg.instances);
|
||||
};
|
||||
systemd.services."kresd@".serviceConfig = {
|
||||
ExecStart = "${package}/bin/kresd --noninteractive "
|
||||
+ "-c ${package}/lib/knot-resolver/distro-preconfig.lua -c ${configFile}";
|
||||
ExecStart = "${cfg.package}/bin/kresd --noninteractive "
|
||||
+ "-c ${cfg.package}/lib/knot-resolver/distro-preconfig.lua -c ${configFile}";
|
||||
# Ensure /run/knot-resolver exists
|
||||
RuntimeDirectory = "knot-resolver";
|
||||
RuntimeDirectoryMode = "0770";
|
||||
|
|
|
@ -20,8 +20,7 @@ let
|
|||
acl_file ${aclFile}
|
||||
persistence true
|
||||
allow_anonymous ${boolToString cfg.allowAnonymous}
|
||||
bind_address ${cfg.host}
|
||||
port ${toString cfg.port}
|
||||
listener ${toString cfg.port} ${cfg.host}
|
||||
${passwordConf}
|
||||
${listenerConf}
|
||||
${cfg.extraConf}
|
||||
|
@ -233,15 +232,50 @@ in
|
|||
ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf}";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
NoNewPrivileges = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = [
|
||||
cfg.dataDir
|
||||
"/tmp" # mosquitto_passwd creates files in /tmp before moving them
|
||||
];
|
||||
ReadOnlyPaths = with cfg.ssl; lib.optionals (enable) [
|
||||
certfile
|
||||
keyfile
|
||||
cafile
|
||||
];
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX" # for sd_notify() call
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
preStart = ''
|
||||
rm -f ${cfg.dataDir}/passwd
|
||||
|
|
|
@ -4,51 +4,28 @@ with lib;
|
|||
let
|
||||
cfg = config.services.unbound;
|
||||
|
||||
stateDir = "/var/lib/unbound";
|
||||
yesOrNo = v: if v then "yes" else "no";
|
||||
|
||||
access = concatMapStringsSep "\n " (x: "access-control: ${x} allow") cfg.allowedAccess;
|
||||
toOption = indent: n: v: "${indent}${toString n}: ${v}";
|
||||
|
||||
interfaces = concatMapStringsSep "\n " (x: "interface: ${x}") cfg.interfaces;
|
||||
toConf = indent: n: v:
|
||||
if builtins.isFloat v then (toOption indent n (builtins.toJSON v))
|
||||
else if isInt v then (toOption indent n (toString v))
|
||||
else if isBool v then (toOption indent n (yesOrNo v))
|
||||
else if isString v then (toOption indent n v)
|
||||
else if isList v then (concatMapStringsSep "\n" (toConf indent n) v)
|
||||
else if isAttrs v then (concatStringsSep "\n" (
|
||||
["${indent}${n}:"] ++ (
|
||||
mapAttrsToList (toConf "${indent} ") v
|
||||
)
|
||||
))
|
||||
else throw (traceSeq v "services.unbound.settings: unexpected type");
|
||||
|
||||
isLocalAddress = x: substring 0 3 x == "::1" || substring 0 9 x == "127.0.0.1";
|
||||
confFile = pkgs.writeText "unbound.conf" (concatStringsSep "\n" ((mapAttrsToList (toConf "") cfg.settings) ++ [""]));
|
||||
|
||||
forward =
|
||||
optionalString (any isLocalAddress cfg.forwardAddresses) ''
|
||||
do-not-query-localhost: no
|
||||
''
|
||||
+ optionalString (cfg.forwardAddresses != []) ''
|
||||
forward-zone:
|
||||
name: .
|
||||
''
|
||||
+ concatMapStringsSep "\n" (x: " forward-addr: ${x}") cfg.forwardAddresses;
|
||||
rootTrustAnchorFile = "${cfg.stateDir}/root.key";
|
||||
|
||||
rootTrustAnchorFile = "${stateDir}/root.key";
|
||||
|
||||
trustAnchor = optionalString cfg.enableRootTrustAnchor
|
||||
"auto-trust-anchor-file: ${rootTrustAnchorFile}";
|
||||
|
||||
confFile = pkgs.writeText "unbound.conf" ''
|
||||
server:
|
||||
ip-freebind: yes
|
||||
directory: "${stateDir}"
|
||||
username: unbound
|
||||
chroot: ""
|
||||
pidfile: ""
|
||||
# when running under systemd there is no need to daemonize
|
||||
do-daemonize: no
|
||||
${interfaces}
|
||||
${access}
|
||||
${trustAnchor}
|
||||
${lib.optionalString (cfg.localControlSocketPath != null) ''
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: ${cfg.localControlSocketPath}
|
||||
''}
|
||||
${cfg.extraConfig}
|
||||
${forward}
|
||||
'';
|
||||
in
|
||||
{
|
||||
in {
|
||||
|
||||
###### interface
|
||||
|
||||
|
@ -64,27 +41,32 @@ in
|
|||
description = "The unbound package to use";
|
||||
};
|
||||
|
||||
allowedAccess = mkOption {
|
||||
default = [ "127.0.0.0/24" ];
|
||||
type = types.listOf types.str;
|
||||
description = "What networks are allowed to use unbound as a resolver.";
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "unbound";
|
||||
description = "User account under which unbound runs.";
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
default = [ "127.0.0.1" ] ++ optional config.networking.enableIPv6 "::1";
|
||||
type = types.listOf types.str;
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "unbound";
|
||||
description = "Group under which unbound runs.";
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
default = "/var/lib/unbound";
|
||||
description = "Directory holding all state for unbound to run.";
|
||||
};
|
||||
|
||||
resolveLocalQueries = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
What addresses the server should listen on. This supports the interface syntax documented in
|
||||
<citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
Whether unbound should resolve local queries (i.e. add 127.0.0.1 to
|
||||
/etc/resolv.conf).
|
||||
'';
|
||||
};
|
||||
|
||||
forwardAddresses = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
description = "What servers to forward queries to.";
|
||||
};
|
||||
|
||||
enableRootTrustAnchor = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
|
@ -106,23 +88,66 @@ in
|
|||
and group will be <literal>nogroup</literal>.
|
||||
|
||||
Users that should be permitted to access the socket must be in the
|
||||
<literal>unbound</literal> group.
|
||||
<literal>config.services.unbound.group</literal> group.
|
||||
|
||||
If this option is <literal>null</literal> remote control will not be
|
||||
configured at all. Unbounds default values apply.
|
||||
enabled. Unbounds default values apply.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
settings = mkOption {
|
||||
default = {};
|
||||
type = with types; submodule {
|
||||
|
||||
freeformType = let
|
||||
validSettingsPrimitiveTypes = oneOf [ int str bool float ];
|
||||
validSettingsTypes = oneOf [ validSettingsPrimitiveTypes (listOf validSettingsPrimitiveTypes) ];
|
||||
settingsType = (attrsOf validSettingsTypes);
|
||||
in attrsOf (oneOf [ string settingsType (listOf settingsType) ])
|
||||
// { description = ''
|
||||
unbound.conf configuration type. The format consist of an attribute
|
||||
set of settings. Each settings can be either one value, a list of
|
||||
values or an attribute set. The allowed values are integers,
|
||||
strings, booleans or floats.
|
||||
'';
|
||||
};
|
||||
|
||||
options = {
|
||||
remote-control.control-enable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
example = literalExample ''
|
||||
{
|
||||
server = {
|
||||
interface = [ "127.0.0.1" ];
|
||||
};
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = "1.1.1.1@853#cloudflare-dns.com";
|
||||
}
|
||||
{
|
||||
name = "example.org.";
|
||||
forward-addr = [
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
}
|
||||
];
|
||||
remote-control.control-enable = true;
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Extra unbound config. See
|
||||
<citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8
|
||||
</manvolnum></citerefentry>.
|
||||
Declarative Unbound configuration
|
||||
See the <citerefentry><refentrytitle>unbound.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry> manpage for a list of
|
||||
available options.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -130,23 +155,56 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users.unbound = {
|
||||
description = "unbound daemon user";
|
||||
isSystemUser = true;
|
||||
group = lib.mkIf (cfg.localControlSocketPath != null) (lib.mkDefault "unbound");
|
||||
services.unbound.settings = {
|
||||
server = {
|
||||
directory = mkDefault cfg.stateDir;
|
||||
username = cfg.user;
|
||||
chroot = ''""'';
|
||||
pidfile = ''""'';
|
||||
# when running under systemd there is no need to daemonize
|
||||
do-daemonize = false;
|
||||
interface = mkDefault ([ "127.0.0.1" ] ++ (optional config.networking.enableIPv6 "::1"));
|
||||
access-control = mkDefault ([ "127.0.0.0/8 allow" ] ++ (optional config.networking.enableIPv6 "::1/128 allow"));
|
||||
auto-trust-anchor-file = mkIf cfg.enableRootTrustAnchor rootTrustAnchorFile;
|
||||
tls-cert-bundle = mkDefault "/etc/ssl/certs/ca-certificates.crt";
|
||||
# prevent race conditions on system startup when interfaces are not yet
|
||||
# configured
|
||||
ip-freebind = mkDefault true;
|
||||
};
|
||||
remote-control = {
|
||||
control-enable = mkDefault false;
|
||||
control-interface = mkDefault ([ "127.0.0.1" ] ++ (optional config.networking.enableIPv6 "::1"));
|
||||
server-key-file = mkDefault "${cfg.stateDir}/unbound_server.key";
|
||||
server-cert-file = mkDefault "${cfg.stateDir}/unbound_server.pem";
|
||||
control-key-file = mkDefault "${cfg.stateDir}/unbound_control.key";
|
||||
control-cert-file = mkDefault "${cfg.stateDir}/unbound_control.pem";
|
||||
} // optionalAttrs (cfg.localControlSocketPath != null) {
|
||||
control-enable = true;
|
||||
control-interface = cfg.localControlSocketPath;
|
||||
};
|
||||
};
|
||||
|
||||
# We need a group so that we can give users access to the configured
|
||||
# control socket. Unbound allows access to the socket only to the unbound
|
||||
# user and the primary group.
|
||||
users.groups = lib.mkIf (cfg.localControlSocketPath != null) {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users = mkIf (cfg.user == "unbound") {
|
||||
unbound = {
|
||||
description = "unbound daemon user";
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = mkIf (cfg.group == "unbound") {
|
||||
unbound = {};
|
||||
};
|
||||
|
||||
networking.resolvconf.useLocalResolver = mkDefault true;
|
||||
networking = mkIf cfg.resolveLocalQueries {
|
||||
resolvconf = {
|
||||
useLocalResolver = mkDefault true;
|
||||
};
|
||||
|
||||
networkmanager.dns = "unbound";
|
||||
};
|
||||
|
||||
environment.etc."unbound/unbound.conf".source = confFile;
|
||||
|
||||
|
@ -156,8 +214,15 @@ in
|
|||
before = [ "nss-lookup.target" ];
|
||||
wantedBy = [ "multi-user.target" "nss-lookup.target" ];
|
||||
|
||||
preStart = lib.mkIf cfg.enableRootTrustAnchor ''
|
||||
path = mkIf cfg.settings.remote-control.control-enable [ pkgs.openssl ];
|
||||
|
||||
preStart = ''
|
||||
${optionalString cfg.enableRootTrustAnchor ''
|
||||
${cfg.package}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
|
||||
''}
|
||||
${optionalString cfg.settings.remote-control.control-enable ''
|
||||
${cfg.package}/bin/unbound-control-setup -d ${cfg.stateDir}
|
||||
''}
|
||||
'';
|
||||
|
||||
restartTriggers = [
|
||||
|
@ -181,8 +246,8 @@ in
|
|||
"CAP_SYS_RESOURCE"
|
||||
];
|
||||
|
||||
User = "unbound";
|
||||
Group = lib.mkIf (cfg.localControlSocketPath != null) (lib.mkDefault "unbound");
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
|
@ -211,9 +276,29 @@ in
|
|||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
RestrictSUIDSGID = true;
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
};
|
||||
};
|
||||
# If networkmanager is enabled, ask it to interface with unbound.
|
||||
networking.networkmanager.dns = "unbound";
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "unbound" "interfaces" ] [ "services" "unbound" "settings" "server" "interface" ])
|
||||
(mkChangedOptionModule [ "services" "unbound" "allowedAccess" ] [ "services" "unbound" "settings" "server" "access-control" ] (
|
||||
config: map (value: "${value} allow") (getAttrFromPath [ "services" "unbound" "allowedAccess" ] config)
|
||||
))
|
||||
(mkRemovedOptionModule [ "services" "unbound" "forwardAddresses" ] ''
|
||||
Add a new setting:
|
||||
services.unbound.settings.forward-zone = [{
|
||||
name = ".";
|
||||
forward-addr = [ # Your current services.unbound.forwardAddresses ];
|
||||
}];
|
||||
If any of those addresses are local addresses (127.0.0.1 or ::1), you must
|
||||
also set services.unbound.settings.server.do-not-query-localhost to false.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "services" "unbound" "extraConfig" ] ''
|
||||
You can use services.unbound.settings to add any configuration you want.
|
||||
'')
|
||||
];
|
||||
}
|
||||
|
|
|
@ -246,12 +246,15 @@ let
|
|||
};
|
||||
|
||||
script = ''
|
||||
mkdir --mode 0644 -p "${dirOf values.privateKeyFile}"
|
||||
set -e
|
||||
|
||||
# If the parent dir does not already exist, create it.
|
||||
# Otherwise, does nothing, keeping existing permisions intact.
|
||||
mkdir -p --mode 0755 "${dirOf values.privateKeyFile}"
|
||||
|
||||
if [ ! -f "${values.privateKeyFile}" ]; then
|
||||
touch "${values.privateKeyFile}"
|
||||
chmod 0600 "${values.privateKeyFile}"
|
||||
wg genkey > "${values.privateKeyFile}"
|
||||
chmod 0400 "${values.privateKeyFile}"
|
||||
# Write private key file with atomically-correct permissions.
|
||||
(set -e; umask 077; wg genkey > "${values.privateKeyFile}")
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -62,6 +62,22 @@ in
|
|||
description = "The firewall package used by fail2ban service.";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.package;
|
||||
example = lib.literalExample "[ pkgs.ipset ]";
|
||||
description = ''
|
||||
Extra packages to be made available to the fail2ban service. The example contains
|
||||
the packages needed by the `iptables-ipset-proto6` action.
|
||||
'';
|
||||
};
|
||||
|
||||
maxretry = mkOption {
|
||||
default = 3;
|
||||
type = types.ints.unsigned;
|
||||
description = "Number of failures before a host gets banned.";
|
||||
};
|
||||
|
||||
banaction = mkOption {
|
||||
default = "iptables-multiport";
|
||||
type = types.str;
|
||||
|
@ -243,7 +259,7 @@ in
|
|||
restartTriggers = [ fail2banConf jailConf pathsConf ];
|
||||
reloadIfChanged = true;
|
||||
|
||||
path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ];
|
||||
path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ] ++ cfg.extraPackages;
|
||||
|
||||
unitConfig.Documentation = "man:fail2ban(1)";
|
||||
|
||||
|
@ -291,7 +307,7 @@ in
|
|||
''}
|
||||
# Miscellaneous options
|
||||
ignoreip = 127.0.0.1/8 ${optionalString config.networking.enableIPv6 "::1"} ${concatStringsSep " " cfg.ignoreIP}
|
||||
maxretry = 3
|
||||
maxretry = ${toString cfg.maxretry}
|
||||
backend = systemd
|
||||
# Actions
|
||||
banaction = ${cfg.banaction}
|
||||
|
|
|
@ -23,7 +23,8 @@ in
|
|||
config.services.oauth2_proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
|
||||
enable = true;
|
||||
};
|
||||
config.services.nginx = mkMerge ((optional (cfg.virtualHosts != []) {
|
||||
config.services.nginx = mkIf config.services.oauth2_proxy.enable (mkMerge
|
||||
((optional (cfg.virtualHosts != []) {
|
||||
recommendedProxySettings = true; # needed because duplicate headers
|
||||
}) ++ (map (vhost: {
|
||||
virtualHosts.${vhost} = {
|
||||
|
@ -60,5 +61,5 @@ in
|
|||
'';
|
||||
|
||||
};
|
||||
}) cfg.virtualHosts));
|
||||
}) cfg.virtualHosts)));
|
||||
}
|
||||
|
|
|
@ -93,6 +93,6 @@ in {
|
|||
systemd.defaultUnit = "graphical.target";
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ matthewbauer flokli ];
|
||||
meta.maintainers = with lib.maintainers; [ matthewbauer ];
|
||||
|
||||
}
|
||||
|
|
|
@ -168,9 +168,10 @@ in
|
|||
type = lib.types.str;
|
||||
default = "keycloak";
|
||||
description = ''
|
||||
Username to use when connecting to an external or manually
|
||||
provisioned database; has no effect when a local database is
|
||||
automatically provisioned.
|
||||
Username to use when connecting to the database.
|
||||
This is also used for automatic provisioning of the database.
|
||||
Changing this after the initial installation doesn't delete the
|
||||
old user and can cause further problems.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -587,8 +588,8 @@ in
|
|||
PSQL=${config.services.postgresql.package}/bin/psql
|
||||
|
||||
db_password="$(<'${cfg.databasePasswordFile}')"
|
||||
$PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || $PSQL -tAc "CREATE ROLE keycloak WITH LOGIN PASSWORD '$db_password' CREATEDB"
|
||||
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"'
|
||||
$PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='${cfg.databaseUsername}'" | grep -q 1 || $PSQL -tAc "CREATE ROLE ${cfg.databaseUsername} WITH LOGIN PASSWORD '$db_password' CREATEDB"
|
||||
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "keycloak" OWNER "${cfg.databaseUsername}"'
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -606,9 +607,9 @@ in
|
|||
set -eu
|
||||
|
||||
db_password="$(<'${cfg.databasePasswordFile}')"
|
||||
( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';"
|
||||
( echo "CREATE USER IF NOT EXISTS '${cfg.databaseUsername}'@'localhost' IDENTIFIED BY '$db_password';"
|
||||
echo "CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
|
||||
echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';"
|
||||
echo "GRANT ALL PRIVILEGES ON keycloak.* TO '${cfg.databaseUsername}'@'localhost';"
|
||||
) | ${config.services.mysql.package}/bin/mysql -N
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@ let
|
|||
// (if cfg.smtp.authenticate then { SMTP_LOGIN = cfg.smtp.user; } else {})
|
||||
// cfg.extraConfig;
|
||||
|
||||
systemCallsList = [ "@clock" "@cpu-emulation" "@debug" "@keyring" "@module" "@mount" "@obsolete" "@raw-io" "@reboot" "@resources" "@setuid" "@swap" ];
|
||||
systemCallsList = [ "@clock" "@cpu-emulation" "@debug" "@keyring" "@module" "@mount" "@obsolete" "@raw-io" "@reboot" "@setuid" "@swap" ];
|
||||
|
||||
cfgService = {
|
||||
# User and group
|
||||
|
@ -434,7 +434,7 @@ in {
|
|||
Type = "oneshot";
|
||||
WorkingDirectory = cfg.package;
|
||||
# System Call Filtering
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " systemCallsList;
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@resources" ]);
|
||||
} // cfgService;
|
||||
|
||||
after = [ "network.target" ];
|
||||
|
@ -461,7 +461,7 @@ in {
|
|||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
WorkingDirectory = cfg.package;
|
||||
# System Call Filtering
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " systemCallsList;
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@resources" ]);
|
||||
} // cfgService;
|
||||
after = [ "mastodon-init-dirs.service" "network.target" ] ++ (if databaseActuallyCreateLocally then [ "postgresql.service" ] else []);
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
@ -487,7 +487,7 @@ in {
|
|||
RuntimeDirectory = "mastodon-streaming";
|
||||
RuntimeDirectoryMode = "0750";
|
||||
# System Call Filtering
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]);
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" "@resources" ]);
|
||||
} // cfgService;
|
||||
};
|
||||
|
||||
|
@ -511,7 +511,7 @@ in {
|
|||
RuntimeDirectory = "mastodon-web";
|
||||
RuntimeDirectoryMode = "0750";
|
||||
# System Call Filtering
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]);
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@resources" ]);
|
||||
} // cfgService;
|
||||
path = with pkgs; [ file imagemagick ffmpeg ];
|
||||
};
|
||||
|
@ -532,7 +532,7 @@ in {
|
|||
EnvironmentFile = "/var/lib/mastodon/.secrets_env";
|
||||
WorkingDirectory = cfg.package;
|
||||
# System Call Filtering
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " (systemCallsList ++ [ "@privileged" ]);
|
||||
SystemCallFilter = "~" + lib.concatStringsSep " " systemCallsList;
|
||||
} // cfgService;
|
||||
path = with pkgs; [ file imagemagick ffmpeg ];
|
||||
};
|
||||
|
|
|
@ -819,28 +819,38 @@ in
|
|||
# Logs directory and mode
|
||||
LogsDirectory = "nginx";
|
||||
LogsDirectoryMode = "0750";
|
||||
# Proc filesystem
|
||||
ProcSubset = "pid";
|
||||
ProtectProc = "invisible";
|
||||
# New file permissions
|
||||
UMask = "0027"; # 0640 / 0750
|
||||
# Capabilities
|
||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ];
|
||||
# Security
|
||||
NoNewPrivileges = true;
|
||||
# Sandboxing
|
||||
# Sandboxing (sorted by occurrence in https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = mkDefault true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = !(builtins.any (mod: (mod.allowMemoryWriteExecute or false)) cfg.package.modules);
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RemoveIPC = true;
|
||||
PrivateMounts = true;
|
||||
# System Call Filtering
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@chown @cpu-emulation @debug @keyring @ipc @module @mount @obsolete @privileged @raw-io @reboot @setuid @swap";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
318
third_party/nixpkgs/nixos/modules/services/web-servers/trafficserver.nix
vendored
Normal file
318
third_party/nixpkgs/nixos/modules/services/web-servers/trafficserver.nix
vendored
Normal file
|
@ -0,0 +1,318 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.trafficserver;
|
||||
user = config.users.users.trafficserver.name;
|
||||
group = config.users.groups.trafficserver.name;
|
||||
|
||||
getManualUrl = name: "https://docs.trafficserver.apache.org/en/latest/admin-guide/files/${name}.en.html";
|
||||
getConfPath = name: "${pkgs.trafficserver}/etc/trafficserver/${name}";
|
||||
|
||||
yaml = pkgs.formats.yaml { };
|
||||
|
||||
fromYAML = f:
|
||||
let
|
||||
jsonFile = pkgs.runCommand "in.json"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.remarshal ];
|
||||
} ''
|
||||
yaml2json < "${f}" > "$out"
|
||||
'';
|
||||
in
|
||||
builtins.fromJSON (builtins.readFile jsonFile);
|
||||
|
||||
mkYamlConf = name: cfg:
|
||||
if cfg != null then {
|
||||
"trafficserver/${name}.yaml".source = yaml.generate "${name}.yaml" cfg;
|
||||
} else {
|
||||
"trafficserver/${name}.yaml".text = "";
|
||||
};
|
||||
|
||||
mkRecordLines = path: value:
|
||||
if isAttrs value then
|
||||
lib.mapAttrsToList (n: v: mkRecordLines (path ++ [ n ]) v) value
|
||||
else if isInt value then
|
||||
"CONFIG ${concatStringsSep "." path} INT ${toString value}"
|
||||
else if isFloat value then
|
||||
"CONFIG ${concatStringsSep "." path} FLOAT ${toString value}"
|
||||
else
|
||||
"CONFIG ${concatStringsSep "." path} STRING ${toString value}";
|
||||
|
||||
mkRecordsConfig = cfg: concatStringsSep "\n" (flatten (mkRecordLines [ ] cfg));
|
||||
mkPluginConfig = cfg: concatStringsSep "\n" (map (p: "${p.path} ${p.arg}") cfg);
|
||||
in
|
||||
{
|
||||
options.services.trafficserver = {
|
||||
enable = mkEnableOption "Apache Traffic Server";
|
||||
|
||||
cache = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "dest_domain=example.com suffix=js action=never-cache";
|
||||
description = ''
|
||||
Caching rules that overrule the origin's caching policy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "cache.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
hosting = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "domain=example.com volume=1";
|
||||
description = ''
|
||||
Partition the cache according to origin server or domain
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "hosting.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
ipAllow = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = fromYAML (getConfPath "ip_allow.yaml");
|
||||
defaultText = "upstream defaults";
|
||||
example = literalExample {
|
||||
ip_allow = [{
|
||||
apply = "in";
|
||||
ip_addrs = "127.0.0.1";
|
||||
action = "allow";
|
||||
methods = "ALL";
|
||||
}];
|
||||
};
|
||||
description = ''
|
||||
Control client access to Traffic Server and Traffic Server connections
|
||||
to upstream servers.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "ip_allow.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
logging = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = fromYAML (getConfPath "logging.yaml");
|
||||
defaultText = "upstream defaults";
|
||||
example = literalExample { };
|
||||
description = ''
|
||||
Configure logs.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "logging.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
parent = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
dest_domain=. method=get parent="p1.example:8080; p2.example:8080" round_robin=true
|
||||
'';
|
||||
description = ''
|
||||
Identify the parent proxies used in an cache hierarchy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "parent.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
default = [ ];
|
||||
|
||||
description = ''
|
||||
Controls run-time loadable plugins available to Traffic Server, as
|
||||
well as their configuration.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "plugin.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
|
||||
type = with types;
|
||||
listOf (submodule {
|
||||
options.path = mkOption {
|
||||
type = str;
|
||||
example = "xdebug.so";
|
||||
description = ''
|
||||
Path to plugin. The path can either be absolute, or relative to
|
||||
the plugin directory.
|
||||
'';
|
||||
};
|
||||
options.arg = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
example = "--header=ATS-My-Debug";
|
||||
description = "arguments to pass to the plugin";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
records = mkOption {
|
||||
type = with types;
|
||||
let valueType = (attrsOf (oneOf [ int float str valueType ])) // {
|
||||
description = "Traffic Server records value";
|
||||
};
|
||||
in
|
||||
valueType;
|
||||
default = { };
|
||||
example = literalExample { proxy.config.proxy_name = "my_server"; };
|
||||
description = ''
|
||||
List of configurable variables used by Traffic Server.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "records.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
remap = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "map http://from.example http://origin.example";
|
||||
description = ''
|
||||
URL remapping rules used by Traffic Server.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "remap.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
splitDns = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
dest_domain=internal.corp.example named="255.255.255.255:212 255.255.255.254" def_domain=corp.example search_list="corp.example corp1.example"
|
||||
dest_domain=!internal.corp.example named=255.255.255.253
|
||||
'';
|
||||
description = ''
|
||||
Specify the DNS server that Traffic Server should use under specific
|
||||
conditions.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "splitdns.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
sslMulticert = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "dest_ip=* ssl_cert_name=default.pem";
|
||||
description = ''
|
||||
Configure SSL server certificates to terminate the SSL sessions.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "ssl_multicert.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
sni = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = null;
|
||||
example = literalExample {
|
||||
sni = [{
|
||||
fqdn = "no-http2.example.com";
|
||||
https = "off";
|
||||
}];
|
||||
};
|
||||
description = ''
|
||||
Configure aspects of TLS connection handling for both inbound and
|
||||
outbound connections.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "sni.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
storage = mkOption {
|
||||
type = types.lines;
|
||||
default = "/var/cache/trafficserver 256M";
|
||||
example = "/dev/disk/by-id/XXXXX volume=1";
|
||||
description = ''
|
||||
List all the storage that make up the Traffic Server cache.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "storage.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
strategies = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = null;
|
||||
description = ''
|
||||
Specify the next hop proxies used in an cache hierarchy and the
|
||||
algorithms used to select the next proxy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "strategies.yaml"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
volume = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = "";
|
||||
example = "volume=1 scheme=http size=20%";
|
||||
description = ''
|
||||
Manage cache space more efficiently and restrict disk usage by
|
||||
creating cache volumes of different sizes.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "volume.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.etc = {
|
||||
"trafficserver/cache.config".text = cfg.cache;
|
||||
"trafficserver/hosting.config".text = cfg.hosting;
|
||||
"trafficserver/parent.config".text = cfg.parent;
|
||||
"trafficserver/plugin.config".text = mkPluginConfig cfg.plugins;
|
||||
"trafficserver/records.config".text = mkRecordsConfig cfg.records;
|
||||
"trafficserver/remap.config".text = cfg.remap;
|
||||
"trafficserver/splitdns.config".text = cfg.splitDns;
|
||||
"trafficserver/ssl_multicert.config".text = cfg.sslMulticert;
|
||||
"trafficserver/storage.config".text = cfg.storage;
|
||||
"trafficserver/volume.config".text = cfg.volume;
|
||||
} // (mkYamlConf "ip_allow" cfg.ipAllow)
|
||||
// (mkYamlConf "logging" cfg.logging)
|
||||
// (mkYamlConf "sni" cfg.sni)
|
||||
// (mkYamlConf "strategies" cfg.strategies);
|
||||
|
||||
environment.systemPackages = [ pkgs.trafficserver ];
|
||||
systemd.packages = [ pkgs.trafficserver ];
|
||||
|
||||
# Traffic Server does privilege handling independently of systemd, and
|
||||
# therefore should be started as root
|
||||
systemd.services.trafficserver = {
|
||||
enable = true;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# These directories can't be created by systemd because:
|
||||
#
|
||||
# 1. Traffic Servers starts as root and switches to an unprivileged user
|
||||
# afterwards. The runtime directories defined below are assumed to be
|
||||
# owned by that user.
|
||||
# 2. The bin/trafficserver script assumes these directories exist.
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '/run/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/cache/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/lib/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/log/trafficserver' - ${user} ${group} - -"
|
||||
];
|
||||
|
||||
services.trafficserver = {
|
||||
records.proxy.config.admin.user_id = user;
|
||||
records.proxy.config.body_factory.template_sets_dir =
|
||||
"${pkgs.trafficserver}/etc/trafficserver/body_factory";
|
||||
};
|
||||
|
||||
users.users.trafficserver = {
|
||||
description = "Apache Traffic Server";
|
||||
isSystemUser = true;
|
||||
inherit group;
|
||||
};
|
||||
users.groups.trafficserver = { };
|
||||
};
|
||||
}
|
|
@ -151,7 +151,6 @@ in
|
|||
services.upower.enable = config.powerManagement.enable;
|
||||
services.gnome3.glib-networking.enable = true;
|
||||
services.gvfs.enable = true;
|
||||
services.gvfs.package = pkgs.xfce.gvfs;
|
||||
services.tumbler.enable = true;
|
||||
services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
|
||||
services.xserver.libinput.enable = mkDefault true; # used in xfce4-settings-manager
|
||||
|
|
|
@ -666,6 +666,7 @@ in
|
|||
# The default max inotify watches is 8192.
|
||||
# Nowadays most apps require a good number of inotify watches,
|
||||
# the value below is used by default on several other distros.
|
||||
boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288;
|
||||
boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288;
|
||||
|
||||
systemd.defaultUnit = mkIf cfg.autorun "graphical.target";
|
||||
|
|
|
@ -16,6 +16,16 @@ let
|
|||
|
||||
userData=/etc/ec2-metadata/user-data
|
||||
|
||||
# Check if user-data looks like a shell script and execute it with the
|
||||
# runtime shell if it does. Otherwise treat it as a nixos configuration
|
||||
# expression
|
||||
if IFS= LC_ALL=C read -rN2 shebang < $userData && [ "$shebang" = '#!' ]; then
|
||||
# NB: we cannot chmod the $userData file, this is why we execute it via
|
||||
# `pkgs.runtimeShell`. This means we have only limited support for shell
|
||||
# scripts compatible with the `pkgs.runtimeShell`.
|
||||
exec ${pkgs.runtimeShell} $userData
|
||||
fi
|
||||
|
||||
if [ -s "$userData" ]; then
|
||||
# If the user-data looks like it could be a nix expression,
|
||||
# copy it over. Also, look for a magic three-hash comment and set
|
||||
|
|
|
@ -56,6 +56,8 @@ in {
|
|||
systemd = {
|
||||
packages = [ config.boot.kernelPackages.hyperv-daemons.lib ];
|
||||
|
||||
services.hv-vss.unitConfig.ConditionPathExists = [ "/dev/vmbus/hv_vss" ];
|
||||
|
||||
targets.hyperv-daemons = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
|
|
@ -35,6 +35,9 @@ let
|
|||
''
|
||||
#! ${pkgs.runtimeShell} -e
|
||||
|
||||
# Exit early if we're asked to shut down.
|
||||
trap "exit 0" SIGRTMIN+3
|
||||
|
||||
# Initialise the container side of the veth pair.
|
||||
if [ -n "$HOST_ADDRESS" ] || [ -n "$HOST_ADDRESS6" ] ||
|
||||
[ -n "$LOCAL_ADDRESS" ] || [ -n "$LOCAL_ADDRESS6" ] ||
|
||||
|
@ -60,8 +63,12 @@ let
|
|||
|
||||
${concatStringsSep "\n" (mapAttrsToList renderExtraVeth cfg.extraVeths)}
|
||||
|
||||
# Start the regular stage 1 script.
|
||||
exec "$1"
|
||||
# Start the regular stage 2 script.
|
||||
# We source instead of exec to not lose an early stop signal, which is
|
||||
# also the only _reliable_ shutdown signal we have since early stop
|
||||
# does not execute ExecStop* commands.
|
||||
set +e
|
||||
. "$1"
|
||||
''
|
||||
);
|
||||
|
||||
|
@ -127,12 +134,16 @@ let
|
|||
''}
|
||||
|
||||
# Run systemd-nspawn without startup notification (we'll
|
||||
# wait for the container systemd to signal readiness).
|
||||
# wait for the container systemd to signal readiness)
|
||||
# Kill signal handling means systemd-nspawn will pass a system-halt signal
|
||||
# to the container systemd when it receives SIGTERM for container shutdown;
|
||||
# containerInit and stage2 have to handle this as well.
|
||||
exec ${config.systemd.package}/bin/systemd-nspawn \
|
||||
--keep-unit \
|
||||
-M "$INSTANCE" -D "$root" $extraFlags \
|
||||
$EXTRA_NSPAWN_FLAGS \
|
||||
--notify-ready=yes \
|
||||
--kill-signal=SIGRTMIN+3 \
|
||||
--bind-ro=/nix/store \
|
||||
--bind-ro=/nix/var/nix/db \
|
||||
--bind-ro=/nix/var/nix/daemon-socket \
|
||||
|
@ -259,13 +270,10 @@ let
|
|||
Slice = "machine.slice";
|
||||
Delegate = true;
|
||||
|
||||
# Hack: we don't want to kill systemd-nspawn, since we call
|
||||
# "machinectl poweroff" in preStop to shut down the
|
||||
# container cleanly. But systemd requires sending a signal
|
||||
# (at least if we want remaining processes to be killed
|
||||
# after the timeout). So send an ignored signal.
|
||||
# We rely on systemd-nspawn turning a SIGTERM to itself into a shutdown
|
||||
# signal (SIGRTMIN+3) for the inner container.
|
||||
KillMode = "mixed";
|
||||
KillSignal = "WINCH";
|
||||
KillSignal = "TERM";
|
||||
|
||||
DevicePolicy = "closed";
|
||||
DeviceAllow = map (d: "${d.node} ${d.modifier}") cfg.allowedDevices;
|
||||
|
@ -747,8 +755,6 @@ in
|
|||
|
||||
postStart = postStartScript dummyConfig;
|
||||
|
||||
preStop = "machinectl poweroff $INSTANCE";
|
||||
|
||||
restartIfChanged = false;
|
||||
|
||||
serviceConfig = serviceDirectives dummyConfig;
|
||||
|
|
21
third_party/nixpkgs/nixos/release.nix
vendored
21
third_party/nixpkgs/nixos/release.nix
vendored
|
@ -138,7 +138,7 @@ in rec {
|
|||
# Build the initial ramdisk so Hydra can keep track of its size over time.
|
||||
initialRamdisk = buildFromConfig ({ ... }: { }) (config: config.system.build.initialRamdisk);
|
||||
|
||||
netboot = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system: makeNetboot {
|
||||
netboot = forMatchingSystems supportedSystems (system: makeNetboot {
|
||||
module = ./modules/installer/netboot/netboot-minimal.nix;
|
||||
inherit system;
|
||||
});
|
||||
|
@ -224,6 +224,25 @@ in rec {
|
|||
);
|
||||
|
||||
|
||||
# Test job for https://github.com/NixOS/nixpkgs/issues/121354 to test
|
||||
# automatic sizing without blocking the channel.
|
||||
amazonImageAutomaticSize = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||
|
||||
with import ./.. { inherit system; };
|
||||
|
||||
hydraJob ((import lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ configuration
|
||||
versionModule
|
||||
./maintainers/scripts/ec2/amazon-image.nix
|
||||
({ ... }: { amazonImage.sizeMB = "auto"; })
|
||||
];
|
||||
}).config.system.build.amazonImage)
|
||||
|
||||
);
|
||||
|
||||
|
||||
# Ensure that all packages used by the minimal NixOS config end up in the channel.
|
||||
dummy = forAllSystems (system: pkgs.runCommand "dummy"
|
||||
{ toplevel = (import lib/eval-config.nix {
|
||||
|
|
32
third_party/nixpkgs/nixos/tests/airsonic.nix
vendored
Normal file
32
third_party/nixpkgs/nixos/tests/airsonic.nix
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "airsonic";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ sumnerevans ];
|
||||
};
|
||||
|
||||
machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.airsonic = {
|
||||
enable = true;
|
||||
maxMemory = 800;
|
||||
};
|
||||
|
||||
# Airsonic is a Java application, and unfortunately requires a significant
|
||||
# amount of memory.
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def airsonic_is_up(_) -> bool:
|
||||
return machine.succeed("curl --fail http://localhost:4040/login")
|
||||
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("airsonic.service")
|
||||
machine.wait_for_open_port(4040)
|
||||
|
||||
with machine.nested("Waiting for UI to work"):
|
||||
retry(airsonic_is_up)
|
||||
'';
|
||||
})
|
|
@ -24,6 +24,8 @@ in
|
|||
_3proxy = handleTest ./3proxy.nix {};
|
||||
acme = handleTest ./acme.nix {};
|
||||
agda = handleTest ./agda.nix {};
|
||||
airsonic = handleTest ./airsonic.nix {};
|
||||
amazon-init-shell = handleTest ./amazon-init-shell.nix {};
|
||||
ammonite = handleTest ./ammonite.nix {};
|
||||
atd = handleTest ./atd.nix {};
|
||||
avahi = handleTest ./avahi.nix {};
|
||||
|
@ -47,7 +49,7 @@ in
|
|||
buildkite-agents = handleTest ./buildkite-agents.nix {};
|
||||
caddy = handleTest ./caddy.nix {};
|
||||
cadvisor = handleTestOn ["x86_64-linux"] ./cadvisor.nix {};
|
||||
cage = handleTest ./cage.nix {};
|
||||
cage = handleTestOn ["x86_64-linux"] ./cage.nix {};
|
||||
cagebreak = handleTest ./cagebreak.nix {};
|
||||
calibre-web = handleTest ./calibre-web.nix {};
|
||||
cassandra_2_1 = handleTest ./cassandra.nix { testPackage = pkgs.cassandra_2_1; };
|
||||
|
@ -413,6 +415,7 @@ in
|
|||
# traefik test relies on docker-containers
|
||||
trac = handleTest ./trac.nix {};
|
||||
traefik = handleTestOn ["x86_64-linux"] ./traefik.nix {};
|
||||
trafficserver = handleTest ./trafficserver.nix {};
|
||||
transmission = handleTest ./transmission.nix {};
|
||||
trezord = handleTest ./trezord.nix {};
|
||||
trickster = handleTest ./trickster.nix {};
|
||||
|
|
40
third_party/nixpkgs/nixos/tests/amazon-init-shell.nix
vendored
Normal file
40
third_party/nixpkgs/nixos/tests/amazon-init-shell.nix
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
# This test verifies that the amazon-init service can treat the `user-data` ec2
|
||||
# metadata file as a shell script. If amazon-init detects that `user-data` is a
|
||||
# script (based on the presence of the shebang #! line) it executes it and
|
||||
# exits.
|
||||
# Note that other tests verify that amazon-init can treat user-data as a nixos
|
||||
# configuration expression.
|
||||
|
||||
{ system ? builtins.currentSystem,
|
||||
config ? {},
|
||||
pkgs ? import ../.. { inherit system config; }
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
with pkgs.lib;
|
||||
|
||||
makeTest {
|
||||
name = "amazon-init";
|
||||
meta = with maintainers; {
|
||||
maintainers = [ urbas ];
|
||||
};
|
||||
machine = { ... }:
|
||||
{
|
||||
imports = [ ../modules/profiles/headless.nix ../modules/virtualisation/amazon-init.nix ];
|
||||
services.openssh.enable = true;
|
||||
networking.hostName = "";
|
||||
environment.etc."ec2-metadata/user-data" = {
|
||||
text = ''
|
||||
#!/usr/bin/bash
|
||||
|
||||
echo successful > /tmp/evidence
|
||||
'';
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
# To wait until amazon-init terminates its run
|
||||
unnamed.wait_for_unit("amazon-init.service")
|
||||
|
||||
unnamed.succeed("grep -q successful /tmp/evidence")
|
||||
'';
|
||||
}
|
18
third_party/nixpkgs/nixos/tests/cage.nix
vendored
18
third_party/nixpkgs/nixos/tests/cage.nix
vendored
|
@ -3,7 +3,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
|
|||
{
|
||||
name = "cage";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ matthewbauer flokli ];
|
||||
maintainers = [ matthewbauer ];
|
||||
};
|
||||
|
||||
machine = { ... }:
|
||||
|
@ -13,19 +13,15 @@ import ./make-test-python.nix ({ pkgs, ...} :
|
|||
services.cage = {
|
||||
enable = true;
|
||||
user = "alice";
|
||||
program = "${pkgs.xterm}/bin/xterm -cm -pc"; # disable color and bold to make OCR easier
|
||||
# Disable color and bold and use a larger font to make OCR easier:
|
||||
program = "${pkgs.xterm}/bin/xterm -cm -pc -fa Monospace -fs 24";
|
||||
};
|
||||
|
||||
# this needs a fairly recent kernel, otherwise:
|
||||
# [backend/drm/util.c:215] Unable to add DRM framebuffer: No such file or directory
|
||||
# [backend/drm/legacy.c:15] Virtual-1: Failed to set CRTC: No such file or directory
|
||||
# [backend/drm/util.c:215] Unable to add DRM framebuffer: No such file or directory
|
||||
# [backend/drm/legacy.c:15] Virtual-1: Failed to set CRTC: No such file or directory
|
||||
# [backend/drm/drm.c:618] Failed to initialize renderer on connector 'Virtual-1': initial page-flip failed
|
||||
# [backend/drm/drm.c:701] Failed to initialize renderer for plane
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
virtualisation.memorySize = 1024;
|
||||
# Need to switch to a different VGA card / GPU driver because Cage segfaults with the default one (std):
|
||||
# machine # [ 14.355893] .cage-wrapped[736]: segfault at 20 ip 00007f035fa0d8c7 sp 00007ffce9e4a2f0 error 4 in libwlroots.so.8[7f035fa07000+5a000]
|
||||
# machine # [ 14.358108] Code: 4f a8 ff ff eb aa 0f 1f 44 00 00 c3 0f 1f 80 00 00 00 00 41 54 49 89 f4 55 31 ed 53 48 89 fb 48 8d 7f 18 48 8d 83 b8 00 00 00 <80> 7f 08 00 75 0d 48 83 3f 00 0f 85 91 00 00 00 48 89 fd 48 83 c7
|
||||
virtualisation.qemu.options = [ "-vga virtio" ];
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
|
|
@ -111,6 +111,26 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
|||
machine.succeed(f"nixos-container stop {id1}")
|
||||
machine.succeed(f"nixos-container start {id1}")
|
||||
|
||||
# clear serial backlog for next tests
|
||||
machine.succeed("logger eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d")
|
||||
machine.wait_for_console_text(
|
||||
"eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d"
|
||||
)
|
||||
|
||||
with subtest("Stop a container early"):
|
||||
machine.succeed(f"nixos-container stop {id1}")
|
||||
machine.succeed(f"nixos-container start {id1} &")
|
||||
machine.wait_for_console_text("Stage 2")
|
||||
machine.succeed(f"nixos-container stop {id1}")
|
||||
machine.wait_for_console_text(f"Container {id1} exited successfully")
|
||||
machine.succeed(f"nixos-container start {id1}")
|
||||
|
||||
with subtest("Stop a container without machined (regression test for #109695)"):
|
||||
machine.systemctl("stop systemd-machined")
|
||||
machine.succeed(f"nixos-container stop {id1}")
|
||||
machine.wait_for_console_text(f"Container {id1} has been shut down")
|
||||
machine.succeed(f"nixos-container start {id1}")
|
||||
|
||||
with subtest("tmpfiles are present"):
|
||||
machine.log("creating container tmpfiles")
|
||||
machine.succeed(
|
||||
|
|
10
third_party/nixpkgs/nixos/tests/custom-ca.nix
vendored
10
third_party/nixpkgs/nixos/tests/custom-ca.nix
vendored
|
@ -92,13 +92,19 @@ in
|
|||
{ onlySSL = true;
|
||||
sslCertificate = "${example-good-cert}/server.crt";
|
||||
sslCertificateKey = "${example-good-cert}/server.key";
|
||||
locations."/".extraConfig = "return 200 'It works!';";
|
||||
locations."/".extraConfig = ''
|
||||
add_header Content-Type text/plain;
|
||||
return 200 'It works!';
|
||||
'';
|
||||
};
|
||||
services.nginx.virtualHosts."bad.example.com" =
|
||||
{ onlySSL = true;
|
||||
sslCertificate = "${example-bad-cert}/server.crt";
|
||||
sslCertificateKey = "${example-bad-cert}/server.key";
|
||||
locations."/".extraConfig = "return 200 'It does not work!';";
|
||||
locations."/".extraConfig = ''
|
||||
add_header Content-Type text/plain;
|
||||
return 200 'It does not work!';
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
|
|
|
@ -18,6 +18,11 @@ in {
|
|||
|
||||
environment.systemPackages = [ pkgs.git ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
# type path mode user group age arg
|
||||
" d /git 0755 root root - -"
|
||||
];
|
||||
|
||||
services.gitDaemon = {
|
||||
enable = true;
|
||||
basePath = "/git";
|
||||
|
@ -35,7 +40,6 @@ in {
|
|||
|
||||
with subtest("create project.git"):
|
||||
server.succeed(
|
||||
"mkdir /git",
|
||||
"git init --bare /git/project.git",
|
||||
"touch /git/project.git/git-daemon-export-ok",
|
||||
)
|
||||
|
|
6
third_party/nixpkgs/nixos/tests/gitlab.nix
vendored
6
third_party/nixpkgs/nixos/tests/gitlab.nix
vendored
|
@ -57,9 +57,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; {
|
|||
};
|
||||
};
|
||||
secrets = {
|
||||
secretFile = pkgs.writeText "secret" "r8X9keSKynU7p4aKlh4GO1Bo77g5a7vj";
|
||||
otpFile = pkgs.writeText "otpsecret" "Zu5hGx3YvQx40DvI8WoZJQpX2paSDOlG";
|
||||
dbFile = pkgs.writeText "dbsecret" "lsGltKWTejOf6JxCVa7nLDenzkO9wPLR";
|
||||
secretFile = pkgs.writeText "secret" "Aig5zaic";
|
||||
otpFile = pkgs.writeText "otpsecret" "Riew9mue";
|
||||
dbFile = pkgs.writeText "dbsecret" "we2quaeZ";
|
||||
jwsFile = pkgs.runCommand "oidcKeyBase" {} "${pkgs.openssl}/bin/openssl genrsa 2048 > $out";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
configDir = "/var/lib/foobar";
|
||||
|
@ -6,9 +6,7 @@ let
|
|||
mqttPassword = "secret";
|
||||
in {
|
||||
name = "home-assistant";
|
||||
meta = with pkgs.lib; {
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
meta.maintainers = lib.teams.home-assistant.members;
|
||||
|
||||
nodes.hass = { pkgs, ... }: {
|
||||
environment.systemPackages = with pkgs; [ mosquitto ];
|
||||
|
@ -47,6 +45,10 @@ in {
|
|||
payload_on = "let_there_be_light";
|
||||
payload_off = "off";
|
||||
}];
|
||||
emulated_hue = {
|
||||
host_ip = "127.0.0.1";
|
||||
listen_port = 80;
|
||||
};
|
||||
logger = {
|
||||
default = "info";
|
||||
logs."homeassistant.components.mqtt" = "debug";
|
||||
|
@ -82,6 +84,9 @@ in {
|
|||
hass.succeed(
|
||||
"mosquitto_pub -V mqttv5 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -m let_there_be_light"
|
||||
)
|
||||
with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
|
||||
hass.wait_for_open_port(80)
|
||||
hass.succeed("curl --fail http://localhost:80/description.xml")
|
||||
with subtest("Print log to ease debugging"):
|
||||
output_log = hass.succeed("cat ${configDir}/home-assistant.log")
|
||||
print("\n### home-assistant.log ###\n")
|
||||
|
@ -93,5 +98,8 @@ in {
|
|||
# example line: 2020-06-20 10:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on home-assistant/test: b'let_there_be_light'
|
||||
with subtest("Check we received the mosquitto message"):
|
||||
assert "let_there_be_light" in output_log
|
||||
|
||||
with subtest("Check systemd unit hardening"):
|
||||
hass.log(hass.succeed("systemd-analyze security home-assistant.service"))
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -2,4 +2,14 @@
|
|||
|
||||
makeInstalledTest {
|
||||
tested = pkgs.pipewire;
|
||||
testConfig = {
|
||||
hardware.pulseaudio.enable = false;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
15
third_party/nixpkgs/nixos/tests/installer.nix
vendored
15
third_party/nixpkgs/nixos/tests/installer.nix
vendored
|
@ -75,7 +75,7 @@ let
|
|||
else ''
|
||||
def assemble_qemu_flags():
|
||||
flags = "-cpu max"
|
||||
${if system == "x86_64-linux"
|
||||
${if (system == "x86_64-linux" || system == "i686-linux")
|
||||
then ''flags += " -m 1024"''
|
||||
else ''flags += " -m 768 -enable-kvm -machine virt,gic-version=host"''
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ let
|
|||
# the same during and after installation.
|
||||
virtualisation.emptyDiskImages = [ 512 ];
|
||||
virtualisation.bootDevice =
|
||||
if grubVersion == 1 then "/dev/sdb" else "/dev/vdb";
|
||||
if grubVersion == 1 then "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive2" else "/dev/vdb";
|
||||
virtualisation.qemu.diskInterface =
|
||||
if grubVersion == 1 then "scsi" else "virtio";
|
||||
|
||||
|
@ -695,22 +695,23 @@ in {
|
|||
};
|
||||
|
||||
# Test a basic install using GRUB 1.
|
||||
grub1 = makeInstallerTest "grub1" {
|
||||
grub1 = makeInstallerTest "grub1" rec {
|
||||
createPartitions = ''
|
||||
machine.succeed(
|
||||
"flock /dev/sda parted --script /dev/sda -- mklabel msdos"
|
||||
"flock ${grubDevice} parted --script ${grubDevice} -- mklabel msdos"
|
||||
+ " mkpart primary linux-swap 1M 1024M"
|
||||
+ " mkpart primary ext2 1024M -1s",
|
||||
"udevadm settle",
|
||||
"mkswap /dev/sda1 -L swap",
|
||||
"mkswap ${grubDevice}-part1 -L swap",
|
||||
"swapon -L swap",
|
||||
"mkfs.ext3 -L nixos /dev/sda2",
|
||||
"mkfs.ext3 -L nixos ${grubDevice}-part2",
|
||||
"mount LABEL=nixos /mnt",
|
||||
"mkdir -p /mnt/tmp",
|
||||
)
|
||||
'';
|
||||
grubVersion = 1;
|
||||
grubDevice = "/dev/sda";
|
||||
# /dev/sda is not stable, even when the SCSI disk number is.
|
||||
grubDevice = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive1";
|
||||
};
|
||||
|
||||
# Test using labels to identify volumes in grub
|
||||
|
|
146
third_party/nixpkgs/nixos/tests/jellyfin.nix
vendored
146
third_party/nixpkgs/nixos/tests/jellyfin.nix
vendored
|
@ -1,4 +1,4 @@
|
|||
import ./make-test-python.nix ({ lib, ...}:
|
||||
import ./make-test-python.nix ({ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
name = "jellyfin";
|
||||
|
@ -6,11 +6,151 @@ import ./make-test-python.nix ({ lib, ...}:
|
|||
|
||||
machine =
|
||||
{ ... }:
|
||||
{ services.jellyfin.enable = true; };
|
||||
{
|
||||
services.jellyfin.enable = true;
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
};
|
||||
|
||||
# Documentation of the Jellyfin API: https://api.jellyfin.org/
|
||||
# Beware, this link can be resource intensive
|
||||
testScript =
|
||||
let
|
||||
payloads = {
|
||||
auth = pkgs.writeText "auth.json" (builtins.toJSON {
|
||||
Username = "jellyfin";
|
||||
});
|
||||
empty = pkgs.writeText "empty.json" (builtins.toJSON { });
|
||||
};
|
||||
in
|
||||
''
|
||||
import json
|
||||
import time
|
||||
from urllib.parse import urlencode
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("jellyfin.service")
|
||||
machine.wait_for_open_port(8096)
|
||||
machine.succeed("curl --fail http://localhost:8096/")
|
||||
|
||||
machine.wait_until_succeeds("curl --fail http://localhost:8096/health | grep Healthy")
|
||||
|
||||
auth_header = 'MediaBrowser Client="NixOS Integration Tests", DeviceId="1337", Device="Apple II", Version="20.09"'
|
||||
|
||||
|
||||
def api_get(path):
|
||||
return f"curl --fail 'http://localhost:8096{path}' -H 'X-Emby-Authorization:{auth_header}'"
|
||||
|
||||
|
||||
def api_post(path, json_file=None):
|
||||
if json_file:
|
||||
return f"curl --fail -X post 'http://localhost:8096{path}' -d '@{json_file}' -H Content-Type:application/json -H 'X-Emby-Authorization:{auth_header}'"
|
||||
else:
|
||||
return f"curl --fail -X post 'http://localhost:8096{path}' -H 'X-Emby-Authorization:{auth_header}'"
|
||||
|
||||
|
||||
with machine.nested("Wizard completes"):
|
||||
machine.wait_until_succeeds(api_get("/Startup/Configuration"))
|
||||
machine.succeed(api_get("/Startup/FirstUser"))
|
||||
machine.succeed(api_post("/Startup/Complete"))
|
||||
|
||||
with machine.nested("Can login"):
|
||||
auth_result = machine.succeed(
|
||||
api_post(
|
||||
"/Users/AuthenticateByName",
|
||||
"${payloads.auth}",
|
||||
)
|
||||
)
|
||||
auth_result = json.loads(auth_result)
|
||||
auth_token = auth_result["AccessToken"]
|
||||
auth_header += f", Token={auth_token}"
|
||||
|
||||
sessions_result = machine.succeed(api_get("/Sessions"))
|
||||
sessions_result = json.loads(sessions_result)
|
||||
|
||||
this_session = [
|
||||
session for session in sessions_result if session["DeviceId"] == "1337"
|
||||
]
|
||||
if len(this_session) != 1:
|
||||
raise Exception("Session not created")
|
||||
|
||||
me = machine.succeed(api_get("/Users/Me"))
|
||||
me = json.loads(me)["Id"]
|
||||
|
||||
with machine.nested("Can add library"):
|
||||
tempdir = machine.succeed("mktemp -d -p /var/lib/jellyfin").strip()
|
||||
machine.succeed(f"chmod 755 '{tempdir}'")
|
||||
|
||||
# Generate a dummy video that we can test later
|
||||
videofile = f"{tempdir}/Big Buck Bunny (2008) [1080p].mkv"
|
||||
machine.succeed(f"ffmpeg -f lavfi -i testsrc2=duration=5 '{videofile}'")
|
||||
|
||||
add_folder_query = urlencode(
|
||||
{
|
||||
"name": "My Library",
|
||||
"collectionType": "Movies",
|
||||
"paths": tempdir,
|
||||
"refreshLibrary": "true",
|
||||
}
|
||||
)
|
||||
|
||||
machine.succeed(
|
||||
api_post(
|
||||
f"/Library/VirtualFolders?{add_folder_query}",
|
||||
"${payloads.empty}",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def is_refreshed(_):
|
||||
folders = machine.succeed(api_get(f"/Library/VirtualFolders"))
|
||||
folders = json.loads(folders)
|
||||
print(folders)
|
||||
return all(folder["RefreshStatus"] == "Idle" for folder in folders)
|
||||
|
||||
|
||||
retry(is_refreshed)
|
||||
|
||||
with machine.nested("Can identify videos"):
|
||||
items = []
|
||||
|
||||
# For some reason, having the folder refreshed doesn't mean the
|
||||
# movie was scanned
|
||||
def has_movie(_):
|
||||
global items
|
||||
|
||||
items = machine.succeed(
|
||||
api_get(f"/Users/{me}/Items?IncludeItemTypes=Movie&Recursive=true")
|
||||
)
|
||||
items = json.loads(items)["Items"]
|
||||
|
||||
return len(items) == 1
|
||||
|
||||
retry(has_movie)
|
||||
|
||||
video = items[0]["Id"]
|
||||
|
||||
item_info = machine.succeed(api_get(f"/Users/{me}/Items/{video}"))
|
||||
item_info = json.loads(item_info)
|
||||
|
||||
if item_info["Name"] != "Big Buck Bunny":
|
||||
raise Exception("Jellyfin failed to properly identify file")
|
||||
|
||||
with machine.nested("Can read videos"):
|
||||
media_source_id = item_info["MediaSources"][0]["Id"]
|
||||
|
||||
machine.succeed(
|
||||
"ffmpeg"
|
||||
+ f" -headers 'X-Emby-Authorization:{auth_header}'"
|
||||
+ f" -i http://localhost:8096/Videos/{video}/master.m3u8?mediaSourceId={media_source_id}"
|
||||
+ f" /tmp/test.mkv"
|
||||
)
|
||||
|
||||
duration = machine.succeed(
|
||||
"ffprobe /tmp/test.mkv"
|
||||
+ " -show_entries format=duration"
|
||||
+ " -of compact=print_section=0:nokey=1"
|
||||
)
|
||||
|
||||
if duration.strip() != "5.000000":
|
||||
raise Exception("Downloaded video has wrong duration")
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
port = 1888;
|
||||
|
@ -30,6 +30,9 @@ in {
|
|||
];
|
||||
};
|
||||
};
|
||||
|
||||
# disable private /tmp for this test
|
||||
systemd.services.mosquitto.serviceConfig.PrivateTmp = lib.mkForce false;
|
||||
};
|
||||
|
||||
client1 = client;
|
||||
|
|
|
@ -69,6 +69,9 @@ in {
|
|||
imports = [ ../modules/profiles/installation-device.nix
|
||||
../modules/profiles/base.nix ];
|
||||
virtualisation.memorySize = 1300;
|
||||
# To add the secondary disk:
|
||||
virtualisation.qemu.options = [ "-drive index=2,file=${debianImage}/disk-image.qcow2,read-only,if=virtio" ];
|
||||
|
||||
# The test cannot access the network, so any packages
|
||||
# nixos-rebuild needs must be included in the VM.
|
||||
system.extraDependencies = with pkgs;
|
||||
|
@ -95,11 +98,6 @@ in {
|
|||
});
|
||||
|
||||
testScript = ''
|
||||
# hack to add the secondary disk
|
||||
os.environ[
|
||||
"QEMU_OPTS"
|
||||
] = "-drive index=2,file=${debianImage}/disk-image.qcow2,read-only,if=virtio"
|
||||
|
||||
machine.start()
|
||||
machine.succeed("udevadm settle")
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
|
10
third_party/nixpkgs/nixos/tests/pinnwand.nix
vendored
10
third_party/nixpkgs/nixos/tests/pinnwand.nix
vendored
|
@ -61,7 +61,7 @@ in
|
|||
client.wait_until_succeeds("ping -c1 server")
|
||||
|
||||
# make sure pinnwand is listening
|
||||
server.wait_until_succeeds("ss -lnp | grep ${toString port}")
|
||||
server.wait_for_open_port(${toString port})
|
||||
|
||||
# send the contents of /etc/machine-id
|
||||
response = client.succeed("steck paste /etc/machine-id")
|
||||
|
@ -75,6 +75,12 @@ in
|
|||
if line.startswith("Removal link:"):
|
||||
removal_link = line.split(":", 1)[1]
|
||||
|
||||
|
||||
# start the reaper, it shouldn't do anything meaningful here
|
||||
server.systemctl("start pinnwand-reaper.service")
|
||||
server.wait_until_fails("systemctl is-active -q pinnwand-reaper.service")
|
||||
server.log(server.execute("journalctl -u pinnwand-reaper -e --no-pager")[1])
|
||||
|
||||
# check whether paste matches what we sent
|
||||
client.succeed(f"curl {raw_url} > /tmp/machine-id")
|
||||
client.succeed("diff /tmp/machine-id /etc/machine-id")
|
||||
|
@ -82,5 +88,7 @@ in
|
|||
# remove paste and check that it's not available any more
|
||||
client.succeed(f"curl {removal_link}")
|
||||
client.fail(f"curl --fail {raw_url}")
|
||||
|
||||
server.log(server.succeed("systemd-analyze security pinnwand"))
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -192,7 +192,8 @@ let
|
|||
"plugin":"testplugin",
|
||||
"time":DATE
|
||||
}]
|
||||
''; in ''
|
||||
''; in
|
||||
''
|
||||
wait_for_unit("prometheus-collectd-exporter.service")
|
||||
wait_for_open_port(9103)
|
||||
succeed(
|
||||
|
@ -258,7 +259,8 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
fritzbox = { # TODO add proper test case
|
||||
fritzbox = {
|
||||
# TODO add proper test case
|
||||
exporterConfig = {
|
||||
enable = true;
|
||||
};
|
||||
|
@ -520,9 +522,11 @@ let
|
|||
url = "http://localhost";
|
||||
};
|
||||
metricProvider = {
|
||||
systemd.services.nc-pwfile = let
|
||||
systemd.services.nc-pwfile =
|
||||
let
|
||||
passfile = (pkgs.writeText "pwfile" "snakeoilpw");
|
||||
in {
|
||||
in
|
||||
{
|
||||
requiredBy = [ "prometheus-nextcloud-exporter.service" ];
|
||||
before = [ "prometheus-nextcloud-exporter.service" ];
|
||||
serviceConfig.ExecStart = ''
|
||||
|
@ -828,7 +832,8 @@ let
|
|||
};
|
||||
metricProvider = {
|
||||
# Mock rtl_433 binary to return a dummy metric stream.
|
||||
nixpkgs.overlays = [ (self: super: {
|
||||
nixpkgs.overlays = [
|
||||
(self: super: {
|
||||
rtl_433 = self.runCommand "rtl_433" { } ''
|
||||
mkdir -p "$out/bin"
|
||||
cat <<EOF > "$out/bin/rtl_433"
|
||||
|
@ -840,7 +845,8 @@ let
|
|||
EOF
|
||||
chmod +x "$out/bin/rtl_433"
|
||||
'';
|
||||
}) ];
|
||||
})
|
||||
];
|
||||
};
|
||||
exporterTest = ''
|
||||
wait_for_unit("prometheus-rtl_433-exporter.service")
|
||||
|
@ -1004,6 +1010,29 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
unbound = {
|
||||
exporterConfig = {
|
||||
enable = true;
|
||||
fetchType = "uds";
|
||||
controlInterface = "/run/unbound/unbound.ctl";
|
||||
};
|
||||
metricProvider = {
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
localControlSocketPath = "/run/unbound/unbound.ctl";
|
||||
};
|
||||
systemd.services.prometheus-unbound-exporter.serviceConfig = {
|
||||
SupplementaryGroups = [ "unbound" ];
|
||||
};
|
||||
};
|
||||
exporterTest = ''
|
||||
wait_for_unit("unbound.service")
|
||||
wait_for_unit("prometheus-unbound-exporter.service")
|
||||
wait_for_open_port(9167)
|
||||
succeed("curl -sSf localhost:9167/metrics | grep -q 'unbound_up 1'")
|
||||
'';
|
||||
};
|
||||
|
||||
varnish = {
|
||||
exporterConfig = {
|
||||
enable = true;
|
||||
|
@ -1033,7 +1062,8 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
wireguard = let snakeoil = import ./wireguard/snakeoil-keys.nix; in {
|
||||
wireguard = let snakeoil = import ./wireguard/snakeoil-keys.nix; in
|
||||
{
|
||||
exporterConfig.enable = true;
|
||||
metricProvider = {
|
||||
networking.wireguard.interfaces.wg0 = {
|
||||
|
@ -1060,10 +1090,13 @@ let
|
|||
};
|
||||
};
|
||||
in
|
||||
mapAttrs (exporter: testConfig: (makeTest (let
|
||||
mapAttrs
|
||||
(exporter: testConfig: (makeTest (
|
||||
let
|
||||
nodeName = testConfig.nodeName or exporter;
|
||||
|
||||
in {
|
||||
in
|
||||
{
|
||||
name = "prometheus-${exporter}-exporter";
|
||||
|
||||
nodes.${nodeName} = mkMerge [{
|
||||
|
@ -1083,4 +1116,6 @@ in {
|
|||
meta = with maintainers; {
|
||||
maintainers = [ willibutz elseym ];
|
||||
};
|
||||
}))) exporterTests
|
||||
}
|
||||
)))
|
||||
exporterTests
|
||||
|
|
5
third_party/nixpkgs/nixos/tests/rspamd.nix
vendored
5
third_party/nixpkgs/nixos/tests/rspamd.nix
vendored
|
@ -25,6 +25,7 @@ let
|
|||
machine = {
|
||||
services.rspamd.enable = true;
|
||||
networking.enableIPv6 = enableIPv6;
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
@ -68,6 +69,7 @@ in
|
|||
group = "rspamd";
|
||||
}];
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
|
@ -116,6 +118,7 @@ in
|
|||
'';
|
||||
};
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
|
@ -221,6 +224,7 @@ in
|
|||
rspamd_logger.infox(rspamd_config, 'Work dammit!!!')
|
||||
'';
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
|
@ -287,6 +291,7 @@ in
|
|||
postfix.enable = true;
|
||||
workers.rspamd_proxy.type = "rspamd_proxy";
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
|
|
176
third_party/nixpkgs/nixos/tests/trafficserver.nix
vendored
Normal file
176
third_party/nixpkgs/nixos/tests/trafficserver.nix
vendored
Normal file
|
@ -0,0 +1,176 @@
|
|||
# verifies:
|
||||
# 1. Traffic Server is able to start
|
||||
# 2. Traffic Server spawns traffic_crashlog upon startup
|
||||
# 3. Traffic Server proxies HTTP requests according to URL remapping rules
|
||||
# in 'services.trafficserver.remap'
|
||||
# 4. Traffic Server applies per-map settings specified with the conf_remap
|
||||
# plugin
|
||||
# 5. Traffic Server caches HTTP responses
|
||||
# 6. Traffic Server processes HTTP PUSH requests
|
||||
# 7. Traffic Server can load the healthchecks plugin
|
||||
# 8. Traffic Server logs HTTP traffic as configured
|
||||
#
|
||||
# uses:
|
||||
# - bin/traffic_manager
|
||||
# - bin/traffic_server
|
||||
# - bin/traffic_crashlog
|
||||
# - bin/traffic_cache_tool
|
||||
# - bin/traffic_ctl
|
||||
# - bin/traffic_logcat
|
||||
# - bin/traffic_logstats
|
||||
# - bin/tspush
|
||||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "trafficserver";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ midchildan ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
ats = { pkgs, lib, config, ... }: let
|
||||
user = config.users.users.trafficserver.name;
|
||||
group = config.users.groups.trafficserver.name;
|
||||
healthchecks = pkgs.writeText "healthchecks.conf" ''
|
||||
/status /tmp/ats.status text/plain 200 500
|
||||
'';
|
||||
in {
|
||||
services.trafficserver.enable = true;
|
||||
|
||||
services.trafficserver.records = {
|
||||
proxy.config.http.server_ports = "80 80:ipv6";
|
||||
proxy.config.hostdb.host_file.path = "/etc/hosts";
|
||||
proxy.config.log.max_space_mb_headroom = 0;
|
||||
proxy.config.http.push_method_enabled = 1;
|
||||
|
||||
# check that cache storage is usable before accepting traffic
|
||||
proxy.config.http.wait_for_cache = 2;
|
||||
};
|
||||
|
||||
services.trafficserver.plugins = [
|
||||
{ path = "healthchecks.so"; arg = toString healthchecks; }
|
||||
{ path = "xdebug.so"; }
|
||||
];
|
||||
|
||||
services.trafficserver.remap = ''
|
||||
map http://httpbin.test http://httpbin
|
||||
map http://pristine-host-hdr.test http://httpbin \
|
||||
@plugin=conf_remap.so \
|
||||
@pparam=proxy.config.url_remap.pristine_host_hdr=1
|
||||
map http://ats/tspush http://httpbin/cache \
|
||||
@plugin=conf_remap.so \
|
||||
@pparam=proxy.config.http.cache.required_headers=0
|
||||
'';
|
||||
|
||||
services.trafficserver.storage = ''
|
||||
/dev/vdb volume=1
|
||||
'';
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
virtualisation.emptyDiskImages = [ 256 ];
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="vdb", OWNER="${user}", GROUP="${group}"
|
||||
'';
|
||||
};
|
||||
|
||||
httpbin = { pkgs, lib, ... }: let
|
||||
python = pkgs.python3.withPackages
|
||||
(ps: with ps; [ httpbin gunicorn gevent ]);
|
||||
in {
|
||||
systemd.services.httpbin = {
|
||||
enable = true;
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${python}/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
client = { pkgs, lib, ... }: {
|
||||
environment.systemPackages = with pkgs; [ curl ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }: let
|
||||
sampleFile = pkgs.writeText "sample.txt" ''
|
||||
It's the season of White Album.
|
||||
'';
|
||||
in ''
|
||||
import json
|
||||
import re
|
||||
|
||||
ats.wait_for_unit("trafficserver")
|
||||
ats.wait_for_open_port(80)
|
||||
httpbin.wait_for_unit("httpbin")
|
||||
httpbin.wait_for_open_port(80)
|
||||
|
||||
with subtest("Traffic Server is running"):
|
||||
out = ats.succeed("traffic_ctl server status")
|
||||
assert out.strip() == "Proxy -- on"
|
||||
|
||||
with subtest("traffic_crashlog is running"):
|
||||
ats.succeed("pgrep -f traffic_crashlog")
|
||||
|
||||
with subtest("basic remapping works"):
|
||||
out = client.succeed("curl -vv -H 'Host: httpbin.test' http://ats/headers")
|
||||
assert json.loads(out)["headers"]["Host"] == "httpbin"
|
||||
|
||||
with subtest("conf_remap plugin works"):
|
||||
out = client.succeed(
|
||||
"curl -vv -H 'Host: pristine-host-hdr.test' http://ats/headers"
|
||||
)
|
||||
assert json.loads(out)["headers"]["Host"] == "pristine-host-hdr.test"
|
||||
|
||||
with subtest("caching works"):
|
||||
out = client.succeed(
|
||||
"curl -vv -D - -H 'Host: httpbin.test' -H 'X-Debug: X-Cache' http://ats/cache/60 -o /dev/null"
|
||||
)
|
||||
assert "X-Cache: miss" in out
|
||||
|
||||
out = client.succeed(
|
||||
"curl -vv -D - -H 'Host: httpbin.test' -H 'X-Debug: X-Cache' http://ats/cache/60 -o /dev/null"
|
||||
)
|
||||
assert "X-Cache: hit-fresh" in out
|
||||
|
||||
with subtest("pushing to cache works"):
|
||||
url = "http://ats/tspush"
|
||||
|
||||
ats.succeed(f"echo {url} > /tmp/urls.txt")
|
||||
out = ats.succeed(
|
||||
f"tspush -f '${sampleFile}' -u {url}"
|
||||
)
|
||||
assert "HTTP/1.0 201 Created" in out, "cache push failed"
|
||||
|
||||
out = ats.succeed(
|
||||
"traffic_cache_tool --spans /etc/trafficserver/storage.config find --input /tmp/urls.txt"
|
||||
)
|
||||
assert "Span: /dev/vdb" in out, "cache not stored on disk"
|
||||
|
||||
out = client.succeed(f"curl {url}").strip()
|
||||
expected = (
|
||||
open("${sampleFile}").read().strip()
|
||||
)
|
||||
assert out == expected, "cache content mismatch"
|
||||
|
||||
with subtest("healthcheck plugin works"):
|
||||
out = client.succeed("curl -vv http://ats/status -o /dev/null -w '%{http_code}'")
|
||||
assert out.strip() == "500"
|
||||
|
||||
ats.succeed("touch /tmp/ats.status")
|
||||
|
||||
out = client.succeed("curl -vv http://ats/status -o /dev/null -w '%{http_code}'")
|
||||
assert out.strip() == "200"
|
||||
|
||||
with subtest("logging works"):
|
||||
access_log_path = "/var/log/trafficserver/squid.blog"
|
||||
ats.wait_for_file(access_log_path)
|
||||
|
||||
out = ats.succeed(f"traffic_logcat {access_log_path}").split("\n")[0]
|
||||
expected = "^\S+ \S+ \S+ TCP_MISS/200 \S+ GET http://httpbin/headers - DIRECT/httpbin application/json$"
|
||||
assert re.fullmatch(expected, out) is not None, "no matching logs"
|
||||
|
||||
out = json.loads(ats.succeed(f"traffic_logstats -jf {access_log_path}"))
|
||||
assert out["total"]["error.total"]["req"] == "0", "unexpected log stat"
|
||||
'';
|
||||
})
|
52
third_party/nixpkgs/nixos/tests/unbound.nix
vendored
52
third_party/nixpkgs/nixos/tests/unbound.nix
vendored
|
@ -61,13 +61,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
|||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
interfaces = [ "192.168.0.1" "fd21::1" "::1" "127.0.0.1" ];
|
||||
allowedAccess = [ "192.168.0.0/24" "fd21::/64" "::1" "127.0.0.0/8" ];
|
||||
extraConfig = ''
|
||||
server:
|
||||
local-data: "example.local. IN A 1.2.3.4"
|
||||
local-data: "example.local. IN AAAA abcd::eeff"
|
||||
'';
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "192.168.0.1" "fd21::1" "::1" "127.0.0.1" ];
|
||||
access-control = [ "192.168.0.0/24 allow" "fd21::/64 allow" "::1 allow" "127.0.0.0/8 allow" ];
|
||||
local-data = [
|
||||
''"example.local. IN A 1.2.3.4"''
|
||||
''"example.local. IN AAAA abcd::eeff"''
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -90,19 +93,25 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
|||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
allowedAccess = [ "192.168.0.0/24" "fd21::/64" "::1" "127.0.0.0/8" ];
|
||||
interfaces = [ "::1" "127.0.0.1" "192.168.0.2" "fd21::2"
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "::1" "127.0.0.1" "192.168.0.2" "fd21::2"
|
||||
"192.168.0.2@853" "fd21::2@853" "::1@853" "127.0.0.1@853"
|
||||
"192.168.0.2@443" "fd21::2@443" "::1@443" "127.0.0.1@443" ];
|
||||
forwardAddresses = [
|
||||
access-control = [ "192.168.0.0/24 allow" "fd21::/64 allow" "::1 allow" "127.0.0.0/8 allow" ];
|
||||
tls-service-pem = "${cert}/cert.pem";
|
||||
tls-service-key = "${cert}/key.pem";
|
||||
};
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = [
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv6.addresses).address
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv4.addresses).address
|
||||
];
|
||||
extraConfig = ''
|
||||
server:
|
||||
tls-service-pem: ${cert}/cert.pem
|
||||
tls-service-key: ${cert}/key.pem
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -122,12 +131,14 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
|||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
allowedAccess = [ "::1" "127.0.0.0/8" ];
|
||||
interfaces = [ "::1" "127.0.0.1" ];
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "::1" "127.0.0.1" ];
|
||||
access-control = [ "::1 allow" "127.0.0.0/8 allow" ];
|
||||
};
|
||||
include = "/etc/unbound/extra*.conf";
|
||||
};
|
||||
localControlSocketPath = "/run/unbound/unbound.ctl";
|
||||
extraConfig = ''
|
||||
include: "/etc/unbound/extra*.conf"
|
||||
'';
|
||||
};
|
||||
|
||||
users.users = {
|
||||
|
@ -143,6 +154,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
|||
unauthorizeduser = { isSystemUser = true; };
|
||||
};
|
||||
|
||||
# Used for testing configuration reloading
|
||||
environment.etc = {
|
||||
"unbound-extra1.conf".text = ''
|
||||
forward-zone:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
machine = { pkgs, ... }:
|
||||
|
@ -6,6 +6,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
|||
services.zigbee2mqtt = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
systemd.services.zigbee2mqtt.serviceConfig.DevicePolicy = lib.mkForce "auto";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
|
@ -14,6 +16,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
|||
machine.succeed(
|
||||
"journalctl -eu zigbee2mqtt | grep \"Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/ttyACM0'\""
|
||||
)
|
||||
|
||||
machine.log(machine.succeed("systemd-analyze security zigbee2mqtt.service"))
|
||||
'';
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
, qca-qt5, qjson, qtquickcontrols2, qtscript, qtwebengine
|
||||
, karchive, kcmutils, kconfig, kdnssd, kguiaddons, kinit, kirigami2, knewstuff, knotifyconfig, ktexteditor, kwindowsystem
|
||||
, fftw, phonon, plasma-framework, threadweaver
|
||||
, curl, ffmpeg_3, gdk-pixbuf, libaio, liblastfm, libmtp, loudmouth, lzo, lz4, mysql57, pcre, snappy, taglib, taglib_extras
|
||||
, curl, ffmpeg, gdk-pixbuf, libaio, liblastfm, libmtp, loudmouth, lzo, lz4, mysql57, pcre, snappy, taglib, taglib_extras
|
||||
}:
|
||||
|
||||
mkDerivation rec {
|
||||
|
@ -23,7 +23,7 @@ mkDerivation rec {
|
|||
qca-qt5 qjson qtquickcontrols2 qtscript qtwebengine
|
||||
karchive kcmutils kconfig kdnssd kguiaddons kinit kirigami2 knewstuff knotifyconfig ktexteditor kwindowsystem
|
||||
phonon plasma-framework threadweaver
|
||||
curl fftw ffmpeg_3 gdk-pixbuf libaio liblastfm libmtp loudmouth lz4 lzo mysql57.server mysql57.server.static
|
||||
curl fftw ffmpeg gdk-pixbuf libaio liblastfm libmtp loudmouth lz4 lzo mysql57.server mysql57.server.static
|
||||
pcre snappy taglib taglib_extras
|
||||
];
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "BSlizr";
|
||||
version = "1.2.12";
|
||||
version = "1.2.14";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "sjaehn";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-vPkcgG+pAfjsPRMyxdMRUxWGch+RG+pdaAcekP5pKEA=";
|
||||
sha256 = "sha256-dut3I68tJWQH+X6acKROqb5HywufeBQ4/HkXFKsA3hY=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
|
63
third_party/nixpkgs/pkgs/applications/audio/bucklespring/default.nix
vendored
Normal file
63
third_party/nixpkgs/pkgs/applications/audio/bucklespring/default.nix
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
{ lib
|
||||
, stdenv
|
||||
, fetchFromGitHub
|
||||
|
||||
, legacy ? false
|
||||
, libinput
|
||||
|
||||
, pkg-config
|
||||
, makeWrapper
|
||||
|
||||
, openal
|
||||
, alure
|
||||
, libXtst
|
||||
, libX11
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) optionals;
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "bucklespring";
|
||||
version = "1.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "zevv";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "114dib4npb7r1z2zd1fwsx71xbf9r6psxqd7n7590cwz1w3r51mz";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkg-config makeWrapper ];
|
||||
|
||||
buildInputs = [ openal alure ]
|
||||
++ optionals (legacy) [ libXtst libX11 ]
|
||||
++ optionals (!legacy) [ libinput ];
|
||||
|
||||
makeFlags = optionals (!legacy) [ "libinput=1" ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/wav
|
||||
cp -r $src/wav $out/share/.
|
||||
install -D ./buckle.desktop $out/share/applications/buckle.desktop
|
||||
install -D ./buckle $out/bin/buckle
|
||||
wrapProgram $out/bin/buckle --add-flags "-p $out/share/wav"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Nostalgia bucklespring keyboard sound";
|
||||
longDescription = ''
|
||||
When built with libinput (wayland or bare console),
|
||||
users need to be in the input group to use this:
|
||||
<code>users.users.alice.extraGroups = [ "input" ];</code>
|
||||
'';
|
||||
homepage = "https://github.com/zevv/bucklespring";
|
||||
license = licenses.gpl2Only;
|
||||
platforms = platforms.unix;
|
||||
maintainers = [ maintainers.evils ];
|
||||
};
|
||||
}
|
|
@ -1,22 +1,42 @@
|
|||
{ mkDerivation, lib, fetchFromGitHub, cmake, pkg-config
|
||||
, qtbase, qtsvg, qttools, perl
|
||||
{ mkDerivation
|
||||
, lib
|
||||
, fetchFromGitHub
|
||||
, cmake
|
||||
, pkg-config
|
||||
, qtbase
|
||||
, qtsvg
|
||||
, qttools
|
||||
, perl
|
||||
|
||||
# Cantata doesn't build with cdparanoia enabled so we disable that
|
||||
# default for now until I (or someone else) figure it out.
|
||||
, withCdda ? false, cdparanoia
|
||||
, withCddb ? false, libcddb
|
||||
, withLame ? false, lame
|
||||
, withMusicbrainz ? false, libmusicbrainz5
|
||||
, withCdda ? false
|
||||
, cdparanoia
|
||||
, withCddb ? false
|
||||
, libcddb
|
||||
, withLame ? false
|
||||
, lame
|
||||
, withMusicbrainz ? false
|
||||
, libmusicbrainz5
|
||||
|
||||
, withTaglib ? true, taglib, taglib_extras
|
||||
, withHttpStream ? true, qtmultimedia
|
||||
, withReplaygain ? true, ffmpeg_3, speex, mpg123
|
||||
, withMtp ? true, libmtp
|
||||
, withTaglib ? true
|
||||
, taglib
|
||||
, taglib_extras
|
||||
, withHttpStream ? true
|
||||
, qtmultimedia
|
||||
, withReplaygain ? true
|
||||
, ffmpeg
|
||||
, speex
|
||||
, mpg123
|
||||
, withMtp ? true
|
||||
, libmtp
|
||||
, withOnlineServices ? true
|
||||
, withDevices ? true, udisks2
|
||||
, withDevices ? true
|
||||
, udisks2
|
||||
, withDynamic ? true
|
||||
, withHttpServer ? true
|
||||
, withLibVlc ? false, libvlc
|
||||
, withLibVlc ? false
|
||||
, libvlc
|
||||
, withStreams ? true
|
||||
}:
|
||||
|
||||
|
@ -31,17 +51,20 @@ assert withReplaygain -> withTaglib;
|
|||
assert withLibVlc -> withHttpStream;
|
||||
|
||||
let
|
||||
version = "2.4.2";
|
||||
pname = "cantata";
|
||||
fstat = x: fn: "-DENABLE_" + fn + "=" + (if x then "ON" else "OFF");
|
||||
fstats = x: map (fstat x);
|
||||
fstat = x: fn:
|
||||
"-DENABLE_${fn}=${if x then "ON" else "OFF"}";
|
||||
|
||||
fstats = x:
|
||||
map (fstat x);
|
||||
|
||||
withUdisks = (withTaglib && withDevices);
|
||||
|
||||
perl' = perl.withPackages (ppkgs: [ ppkgs.URI ]);
|
||||
perl' = perl.withPackages (ppkgs: with ppkgs; [ URI ]);
|
||||
|
||||
in mkDerivation {
|
||||
name = "${pname}-${version}";
|
||||
in
|
||||
mkDerivation rec {
|
||||
pname = "cantata";
|
||||
version = "2.4.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "CDrummond";
|
||||
|
@ -63,7 +86,7 @@ in mkDerivation {
|
|||
|
||||
buildInputs = [ qtbase qtsvg perl' ]
|
||||
++ lib.optionals withTaglib [ taglib taglib_extras ]
|
||||
++ lib.optionals withReplaygain [ ffmpeg_3 speex mpg123 ]
|
||||
++ lib.optionals withReplaygain [ ffmpeg speex mpg123 ]
|
||||
++ lib.optional withHttpStream qtmultimedia
|
||||
++ lib.optional withCdda cdparanoia
|
||||
++ lib.optional withCddb libcddb
|
||||
|
@ -95,11 +118,11 @@ in mkDerivation {
|
|||
];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/cdrummond/cantata";
|
||||
description = "A graphical client for MPD";
|
||||
license = licenses.gpl3;
|
||||
homepage = "https://github.com/cdrummond/cantata";
|
||||
license = licenses.gpl3Only;
|
||||
maintainers = with maintainers; [ peterhoeg ];
|
||||
# Technically Cantata can run on Windows so if someone wants to
|
||||
# Technically, Cantata should run on Darwin/Windows so if someone wants to
|
||||
# bother figuring that one out, be my guest.
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ lib, stdenv, fetchFromGitHub, alsaLib, file, fluidsynth, ffmpeg_3, jack2,
|
||||
{ lib, stdenv, fetchFromGitHub, alsaLib, file, fluidsynth, jack2,
|
||||
liblo, libpulseaudio, libsndfile, pkg-config, python3Packages,
|
||||
which, withFrontend ? true,
|
||||
withQt ? true, qtbase ? null, wrapQtAppsHook ? null,
|
||||
|
@ -33,7 +33,7 @@ stdenv.mkDerivation rec {
|
|||
] ++ optional withFrontend pyqt5;
|
||||
|
||||
buildInputs = [
|
||||
file liblo alsaLib fluidsynth ffmpeg_3 jack2 libpulseaudio libsndfile
|
||||
file liblo alsaLib fluidsynth jack2 libpulseaudio libsndfile
|
||||
] ++ optional withQt qtbase
|
||||
++ optional withGtk2 gtk2
|
||||
++ optional withGtk3 gtk3;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
, cmake
|
||||
, docbook_xml_dtd_45
|
||||
, docbook_xsl
|
||||
, ffmpeg_3
|
||||
, ffmpeg
|
||||
, flac
|
||||
, id3lib
|
||||
, libogg
|
||||
|
@ -31,21 +31,22 @@ stdenv.mkDerivation rec {
|
|||
version = "3.8.6";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://sourceforge/project/kid3/kid3/${version}/${pname}-${version}.tar.gz";
|
||||
sha256 = "sha256-ce+MWCJzAnN+u+07f0dvn0jnbqiUlS2RbcM9nAj5bgg=";
|
||||
url = "https://download.kde.org/stable/${pname}/${version}/${pname}-${version}.tar.xz";
|
||||
hash = "sha256-R4gAWlCw8RezhYbw1XDo+wdp797IbLoM3wqHwr+ul6k=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
docbook_xml_dtd_45
|
||||
docbook_xsl
|
||||
pkg-config
|
||||
python3
|
||||
wrapQtAppsHook
|
||||
];
|
||||
buildInputs = [
|
||||
automoc4
|
||||
chromaprint
|
||||
docbook_xml_dtd_45
|
||||
docbook_xsl
|
||||
ffmpeg_3
|
||||
ffmpeg
|
||||
flac
|
||||
id3lib
|
||||
libogg
|
||||
|
@ -53,7 +54,6 @@ stdenv.mkDerivation rec {
|
|||
libxslt
|
||||
mp4v2
|
||||
phonon
|
||||
python3
|
||||
qtbase
|
||||
qtmultimedia
|
||||
qtquickcontrols
|
||||
|
@ -71,6 +71,7 @@ stdenv.mkDerivation rec {
|
|||
'';
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://kid3.kde.org/";
|
||||
description = "A simple and powerful audio tag editor";
|
||||
longDescription = ''
|
||||
If you want to easily tag multiple MP3, Ogg/Vorbis, FLAC, MPC, MP4/AAC,
|
||||
|
@ -101,7 +102,6 @@ stdenv.mkDerivation rec {
|
|||
- Edit synchronized lyrics and event timing codes, import and export
|
||||
LRC files.
|
||||
'';
|
||||
homepage = "http://kid3.sourceforge.net/";
|
||||
license = licenses.lgpl2Plus;
|
||||
maintainers = [ maintainers.AndersonTorres ];
|
||||
platforms = platforms.linux;
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "kmetronome";
|
||||
version = "1.0.1";
|
||||
version = "1.2.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://sourceforge/${pname}/${version}/${pname}-${version}.tar.bz2";
|
||||
sha256 = "0bzm6vzlm32kjrgn1nvp096b2d41ybys2sk145nhy992wg56v32s";
|
||||
sha256 = "1ln0nm24w6bj7wc8cay08j5azzznigd39cbbw3h4skg6fxd8p0s7";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config qttools ];
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,18 +4,17 @@
|
|||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "librespot";
|
||||
version = "0.1.3";
|
||||
version = "0.1.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "librespot-org";
|
||||
repo = "librespot";
|
||||
rev = "v${version}";
|
||||
sha256 = "1ixh47yvaamrpzagqsiimc3y6bi4nbym95843d23am55zkrgnmy5";
|
||||
sha256 = "153i9n3qwmmwc29f62cz8nbqrlry16iygvibm1sdnvpf0s6wk5f3";
|
||||
};
|
||||
|
||||
cargoSha256 = "1csls8kzzx28ng6w9vdwhnnav5sqp2m5fj430db5z306xh5acg3d";
|
||||
|
||||
cargoPatches = [ ./cargo-lock.patch ];
|
||||
cargoSha256 = "11d64rpq4b5rdxk5wx0hhzgc6mvs6h2br0w3kfncfklp67vn3v4v";
|
||||
|
||||
cargoBuildFlags = with lib; [
|
||||
"--no-default-features"
|
||||
|
|
|
@ -21,6 +21,8 @@ lib.makeScope newScope (self: with self; {
|
|||
|
||||
mopidy-musicbox-webclient = callPackage ./musicbox-webclient.nix { };
|
||||
|
||||
mopidy-podcast = callPackage ./podcast.nix { };
|
||||
|
||||
mopidy-scrobbler = callPackage ./scrobbler.nix { };
|
||||
|
||||
mopidy-somafm = callPackage ./somafm.nix { };
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue