Merge remote-tracking branch 'upstream/master' into mberndt123/stratis-rootfs
This commit is contained in:
commit
cb410a8c59
2191 changed files with 123232 additions and 81845 deletions
39
.github/CODEOWNERS
vendored
39
.github/CODEOWNERS
vendored
|
@ -22,19 +22,19 @@
|
|||
/.editorconfig @Mic92 @zowoq
|
||||
|
||||
# Libraries
|
||||
/lib @edolstra @nbp @infinisil
|
||||
/lib/systems @alyssais @nbp @ericson2314 @matthewbauer
|
||||
/lib/generators.nix @edolstra @nbp @Profpatsch
|
||||
/lib/cli.nix @edolstra @nbp @Profpatsch
|
||||
/lib/debug.nix @edolstra @nbp @Profpatsch
|
||||
/lib/asserts.nix @edolstra @nbp @Profpatsch
|
||||
/lib @edolstra @infinisil
|
||||
/lib/systems @alyssais @ericson2314 @matthewbauer
|
||||
/lib/generators.nix @edolstra @Profpatsch
|
||||
/lib/cli.nix @edolstra @Profpatsch
|
||||
/lib/debug.nix @edolstra @Profpatsch
|
||||
/lib/asserts.nix @edolstra @Profpatsch
|
||||
/lib/path.* @infinisil @fricklerhandwerk
|
||||
|
||||
# Nixpkgs Internals
|
||||
/default.nix @nbp
|
||||
/pkgs/top-level/default.nix @nbp @Ericson2314
|
||||
/pkgs/top-level/impure.nix @nbp @Ericson2314
|
||||
/pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
|
||||
/default.nix @Ericson2314
|
||||
/pkgs/top-level/default.nix @Ericson2314
|
||||
/pkgs/top-level/impure.nix @Ericson2314
|
||||
/pkgs/top-level/stage.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/stdenv/generic @Ericson2314 @matthewbauer
|
||||
|
@ -67,22 +67,9 @@
|
|||
/doc/using @fricklerhandwerk
|
||||
|
||||
# NixOS Internals
|
||||
/nixos/default.nix @nbp @infinisil
|
||||
/nixos/lib/from-env.nix @nbp @infinisil
|
||||
/nixos/lib/eval-config.nix @nbp @infinisil
|
||||
/nixos/doc/manual/configuration/abstractions.xml @nbp
|
||||
/nixos/doc/manual/configuration/config-file.xml @nbp
|
||||
/nixos/doc/manual/configuration/config-syntax.xml @nbp
|
||||
/nixos/doc/manual/configuration/modularity.xml @nbp
|
||||
/nixos/doc/manual/development/assertions.xml @nbp
|
||||
/nixos/doc/manual/development/meta-attributes.xml @nbp
|
||||
/nixos/doc/manual/development/option-declarations.xml @nbp
|
||||
/nixos/doc/manual/development/option-def.xml @nbp
|
||||
/nixos/doc/manual/development/option-types.xml @nbp
|
||||
/nixos/doc/manual/development/replace-modules.xml @nbp
|
||||
/nixos/doc/manual/development/writing-modules.xml @nbp
|
||||
/nixos/doc/manual/man-nixos-option.xml @nbp
|
||||
/nixos/modules/installer/tools/nixos-option.sh @nbp
|
||||
/nixos/default.nix @infinisil
|
||||
/nixos/lib/from-env.nix @infinisil
|
||||
/nixos/lib/eval-config.nix @infinisil
|
||||
/nixos/modules/system @dasJ
|
||||
/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius
|
||||
/nixos/modules/system/activation/bootspec.cue @grahamc @cole-h @raitobezarius
|
||||
|
|
|
@ -164,6 +164,26 @@ tests.fetchgit = testers.invalidateFetcherByDrvHash fetchgit {
|
|||
};
|
||||
```
|
||||
|
||||
## `runNixOSTest` {#tester-runNixOSTest}
|
||||
|
||||
A helper function that behaves exactly like the NixOS `runTest`, except it also assigns this Nixpkgs package set as the `pkgs` of the test and makes the `nixpkgs.*` options read-only.
|
||||
|
||||
If your test is part of the Nixpkgs repository, or if you need a more general entrypoint, see ["Calling a test" in the NixOS manual](https://nixos.org/manual/nixos/stable/index.html#sec-calling-nixos-tests).
|
||||
|
||||
Example:
|
||||
|
||||
```nix
|
||||
pkgs.testers.runNixOSTest ({ lib, ... }: {
|
||||
name = "hello";
|
||||
nodes.machine = { pkgs, ... }: {
|
||||
environment.systemPackages = [ pkgs.hello ];
|
||||
};
|
||||
testScript = ''
|
||||
machine.succeed("hello")
|
||||
'';
|
||||
})
|
||||
```
|
||||
|
||||
## `nixosTest` {#tester-nixosTest}
|
||||
|
||||
Run a NixOS VM network test using this evaluation of Nixpkgs.
|
||||
|
|
|
@ -27,7 +27,7 @@ package set to make it the default. This guarantees you get a consistent package
|
|||
set.
|
||||
```nix
|
||||
mypkg = let
|
||||
cudaPackages = cudaPackages_11_5.overrideScope' (final: prev {
|
||||
cudaPackages = cudaPackages_11_5.overrideScope' (final: prev: {
|
||||
cudnn = prev.cudnn_8_3_2;
|
||||
}});
|
||||
in callPackage { inherit cudaPackages; };
|
||||
|
|
65
doc/languages-frameworks/dart.section.md
Normal file
65
doc/languages-frameworks/dart.section.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Dart {#sec-language-dart}
|
||||
|
||||
## Dart applications {#ssec-dart-applications}
|
||||
|
||||
The function `buildDartApplication` builds Dart applications managed with pub.
|
||||
|
||||
It fetches its Dart dependencies automatically through `fetchDartDeps`, and (through a series of hooks) builds and installs the executables specified in the pubspec file. The hooks can be used in other derivations, if needed. The phases can also be overridden to do something different from installing binaries.
|
||||
|
||||
If you are packaging a Flutter desktop application, use [`buildFlutterApplication`](#ssec-dart-flutter) instead.
|
||||
|
||||
`vendorHash`: is the hash of the output of the dependency fetcher derivation. To obtain it, simply set it to `lib.fakeHash` (or omit it) and run the build ([more details here](#sec-source-hashes)).
|
||||
|
||||
If the upstream source is missing a `pubspec.lock` file, you'll have to vendor one and specify it using `pubspecLockFile`. If it is needed, one will be generated for you and printed when attempting to build the derivation.
|
||||
|
||||
The `dart` commands run can be overridden through `pubGetScript` and `dartCompileCommand`, you can also add flags using `dartCompileFlags` or `dartJitFlags`.
|
||||
|
||||
Dart supports multiple [outputs types](https://dart.dev/tools/dart-compile#types-of-output), you can choose between them using `dartOutputType` (defaults to `exe`). If you want to override the binaries path or the source path they come from, you can use `dartEntryPoints`. Outputs that require a runtime will automatically be wrapped with the relevant runtime (`dartaotruntime` for `aot-snapshot`, `dart run` for `jit-snapshot` and `kernel`, `node` for `js`), this can be overridden through `dartRuntimeCommand`.
|
||||
|
||||
```nix
|
||||
{ buildDartApplication, fetchFromGitHub }:
|
||||
|
||||
buildDartApplication rec {
|
||||
pname = "dart-sass";
|
||||
version = "1.62.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "sass";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-U6enz8yJcc4Wf8m54eYIAnVg/jsGi247Wy8lp1r1wg4=";
|
||||
};
|
||||
|
||||
pubspecLockFile = ./pubspec.lock;
|
||||
vendorHash = "sha256-Atm7zfnDambN/BmmUf4BG0yUz/y6xWzf0reDw3Ad41s=";
|
||||
}
|
||||
```
|
||||
|
||||
## Flutter applications {#ssec-dart-flutter}
|
||||
|
||||
The function `buildFlutterApplication` builds Flutter applications.
|
||||
|
||||
The deps.json file must always be provided when packaging in Nixpkgs. It will be generated and printed if the derivation is attempted to be built without one. Alternatively, `autoDepsList` may be set to `true` when outside of Nixpkgs, as it relies on import-from-derivation.
|
||||
|
||||
A `pubspec.lock` file must be available. See the [Dart documentation](#ssec-dart-applications) for more details.
|
||||
|
||||
```nix
|
||||
{ flutter, fetchFromGitHub }:
|
||||
|
||||
flutter.buildFlutterApplication {
|
||||
pname = "firmware-updater";
|
||||
version = "unstable-2023-04-30";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "canonical";
|
||||
repo = "firmware-updater";
|
||||
rev = "6e7dbdb64e344633ea62874b54ff3990bd3b8440";
|
||||
sha256 = "sha256-s5mwtr5MSPqLMN+k851+pFIFFPa0N1hqz97ys050tFA=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
pubspecLockFile = ./pubspec.lock;
|
||||
depsListFile = ./deps.json;
|
||||
vendorHash = "sha256-cdMO+tr6kYiN5xKXa+uTMAcFf2C75F3wVPrn21G4QPQ=";
|
||||
}
|
||||
```
|
|
@ -14,6 +14,7 @@
|
|||
<xi:include href="crystal.section.xml" />
|
||||
<xi:include href="cuda.section.xml" />
|
||||
<xi:include href="cuelang.section.xml" />
|
||||
<xi:include href="dart.section.xml" />
|
||||
<xi:include href="dhall.section.xml" />
|
||||
<xi:include href="dotnet.section.xml" />
|
||||
<xi:include href="emscripten.section.xml" />
|
||||
|
|
|
@ -118,7 +118,7 @@ ImageExifTool = buildPerlPackage {
|
|||
hash = "sha256-vOhB/FwQMC8PPvdnjDvxRpU6jAZcC6GMQfc0AH4uwKg=";
|
||||
};
|
||||
|
||||
buildInputs = lib.optional stdenv.isDarwin shortenPerlShebang;
|
||||
nativeBuildInputs = lib.optional stdenv.isDarwin shortenPerlShebang;
|
||||
postInstall = lib.optionalString stdenv.isDarwin ''
|
||||
shortenPerlShebang $out/bin/exiftool
|
||||
'';
|
||||
|
|
|
@ -535,7 +535,9 @@ directory of the `tokenizers` project's source archive, we use
|
|||
```nix
|
||||
{ fetchFromGitHub
|
||||
, buildPythonPackage
|
||||
, cargo
|
||||
, rustPlatform
|
||||
, rustc
|
||||
, setuptools-rust
|
||||
}:
|
||||
|
||||
|
@ -558,11 +560,12 @@ buildPythonPackage rec {
|
|||
|
||||
sourceRoot = "source/bindings/python";
|
||||
|
||||
nativeBuildInputs = [ setuptools-rust ] ++ (with rustPlatform; [
|
||||
cargoSetupHook
|
||||
rust.cargo
|
||||
rust.rustc
|
||||
]);
|
||||
nativeBuildInputs = [
|
||||
cargo
|
||||
rustPlatform.cargoSetupHook
|
||||
rustc
|
||||
setuptools-rust
|
||||
];
|
||||
|
||||
# ...
|
||||
}
|
||||
|
|
13
flake.nix
13
flake.nix
|
@ -57,6 +57,19 @@
|
|||
|
||||
nixosModules = {
|
||||
notDetected = ./nixos/modules/installer/scan/not-detected.nix;
|
||||
|
||||
/*
|
||||
Make the `nixpkgs.*` configuration read-only. Guarantees that `pkgs`
|
||||
is the way you initialize it.
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
imports = [ nixpkgs.nixosModules.readOnlyPkgs ];
|
||||
nixpkgs.pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||
}
|
||||
*/
|
||||
readOnlyPkgs = ./nixos/modules/misc/nixpkgs/read-only.nix;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -204,6 +204,11 @@ in mkLicense lset) ({
|
|||
free = false;
|
||||
};
|
||||
|
||||
caossl = {
|
||||
fullName = "Computer Associates Open Source Licence Version 1.0";
|
||||
url = "http://jxplorer.org/licence.html";
|
||||
};
|
||||
|
||||
cal10 = {
|
||||
fullName = "Cryptographic Autonomy License version 1.0 (CAL-1.0)";
|
||||
url = "https://opensource.org/licenses/CAL-1.0";
|
||||
|
@ -230,6 +235,12 @@ in mkLicense lset) ({
|
|||
free = false;
|
||||
};
|
||||
|
||||
cc-by-nc-nd-40 = {
|
||||
spdxId = "CC-BY-NC-ND-4.0";
|
||||
fullName = "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International";
|
||||
free = false;
|
||||
};
|
||||
|
||||
cc-by-nc-sa-20 = {
|
||||
spdxId = "CC-BY-NC-SA-2.0";
|
||||
fullName = "Creative Commons Attribution Non Commercial Share Alike 2.0";
|
||||
|
|
|
@ -261,7 +261,7 @@ rec {
|
|||
concatMap (opt:
|
||||
let
|
||||
name = showOption opt.loc;
|
||||
docOption = rec {
|
||||
docOption = {
|
||||
loc = opt.loc;
|
||||
inherit name;
|
||||
description = opt.description or null;
|
||||
|
@ -280,9 +280,9 @@ rec {
|
|||
renderOptionValue opt.example
|
||||
);
|
||||
}
|
||||
// optionalAttrs (opt ? default) {
|
||||
// optionalAttrs (opt ? defaultText || opt ? default) {
|
||||
default =
|
||||
builtins.addErrorContext "while evaluating the default value of option `${name}`" (
|
||||
builtins.addErrorContext "while evaluating the ${if opt?defaultText then "defaultText" else "default value"} of option `${name}`" (
|
||||
renderOptionValue (opt.defaultText or opt.default)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ rec {
|
|||
else if final.isFreeBSD then "fblibc"
|
||||
else if final.isNetBSD then "nblibc"
|
||||
else if final.isAvr then "avrlibc"
|
||||
else if final.isGhcjs then null
|
||||
else if final.isNone then "newlib"
|
||||
# TODO(@Ericson2314) think more about other operating systems
|
||||
else "native/impure";
|
||||
|
@ -120,7 +121,7 @@ rec {
|
|||
({
|
||||
linux-kernel = args.linux-kernel or {};
|
||||
gcc = args.gcc or {};
|
||||
rustc = args.rust or {};
|
||||
rustc = args.rustc or {};
|
||||
} // platforms.select final)
|
||||
linux-kernel gcc rustc;
|
||||
|
||||
|
@ -144,6 +145,7 @@ rec {
|
|||
else if final.isS390 && !final.isS390x then null
|
||||
else if final.isx86_64 then "x86_64"
|
||||
else if final.isx86 then "i386"
|
||||
else if final.isMips64 then "mips64${lib.optionalString final.isLittleEndian "el"}"
|
||||
else final.uname.processor;
|
||||
|
||||
# Name used by UEFI for architectures.
|
||||
|
|
|
@ -476,6 +476,14 @@ rec {
|
|||
check = x: isDerivation x && hasAttr "shellPath" x;
|
||||
};
|
||||
|
||||
pkgs = addCheck
|
||||
(unique { message = "A Nixpkgs pkgs set can not be merged with another pkgs set."; } attrs // {
|
||||
name = "pkgs";
|
||||
descriptionClass = "noun";
|
||||
description = "Nixpkgs package set";
|
||||
})
|
||||
(x: (x._type or null) == "pkgs");
|
||||
|
||||
path = mkOptionType {
|
||||
name = "path";
|
||||
descriptionClass = "noun";
|
||||
|
@ -767,9 +775,11 @@ rec {
|
|||
};
|
||||
binOp = lhs: rhs: {
|
||||
class =
|
||||
if lhs.class == null then rhs.class
|
||||
else if rhs.class == null then lhs.class
|
||||
else if lhs.class == rhs.class then lhs.class
|
||||
# `or null` was added for backwards compatibility only. `class` is
|
||||
# always set in the current version of the module system.
|
||||
if lhs.class or null == null then rhs.class or null
|
||||
else if rhs.class or null == null then lhs.class or null
|
||||
else if lhs.class or null == rhs.class then lhs.class or null
|
||||
else throw "A submoduleWith option is declared multiple times with conflicting class values \"${toString lhs.class}\" and \"${toString rhs.class}\".";
|
||||
modules = lhs.modules ++ rhs.modules;
|
||||
specialArgs =
|
||||
|
|
|
@ -579,6 +579,12 @@
|
|||
githubId = 20405311;
|
||||
name = "Aksh Gupta";
|
||||
};
|
||||
alanpearce = {
|
||||
email = "alan@alanpearce.eu";
|
||||
github = "alanpearce";
|
||||
githubId = 850317;
|
||||
name = "Alan Pearce";
|
||||
};
|
||||
alapshin = {
|
||||
email = "alapshin@fastmail.com";
|
||||
github = "alapshin";
|
||||
|
@ -990,7 +996,7 @@
|
|||
name = "Stanislas Lange";
|
||||
};
|
||||
AngryAnt = {
|
||||
name = "Emil Johansen";
|
||||
name = "Emil \"AngryAnt\" Johansen";
|
||||
email = "git@eej.dk";
|
||||
matrix = "@angryant:envs.net";
|
||||
github = "AngryAnt";
|
||||
|
@ -1520,6 +1526,12 @@
|
|||
githubId = 12958979;
|
||||
name = "Mika Naylor";
|
||||
};
|
||||
autrimpo = {
|
||||
email = "michal@koutensky.net";
|
||||
github = "autrimpo";
|
||||
githubId = 5968483;
|
||||
name = "Michal Koutenský";
|
||||
};
|
||||
autumnal = {
|
||||
name = "Sven Friedrich";
|
||||
email = "sven@autumnal.de";
|
||||
|
@ -2406,6 +2418,12 @@
|
|||
githubId = 51231053;
|
||||
name = "Daniel";
|
||||
};
|
||||
cadkin = {
|
||||
email = "cva@siliconslumber.net";
|
||||
name = "Cameron Adkins";
|
||||
github = "cadkin";
|
||||
githubId = 34077838;
|
||||
};
|
||||
cafkafk = {
|
||||
email = "christina@cafkafk.com";
|
||||
matrix = "@cafkafk:matrix.cafkafk.com";
|
||||
|
@ -3466,6 +3484,12 @@
|
|||
githubId = 1298344;
|
||||
name = "Daniel Fullmer";
|
||||
};
|
||||
daniyalsuri6 = {
|
||||
email = "daniyal.suri@gmail.com";
|
||||
github = "daniyalsuri6";
|
||||
githubId = 107034852;
|
||||
name = "Daniyal Suri";
|
||||
};
|
||||
dansbandit = {
|
||||
github = "dansbandit";
|
||||
githubId = 4530687;
|
||||
|
@ -3748,13 +3772,6 @@
|
|||
githubId = 62989;
|
||||
name = "Demyan Rogozhin";
|
||||
};
|
||||
dennajort = {
|
||||
email = "gosselinjb@gmail.com";
|
||||
matrix = "@dennajort:matrix.org";
|
||||
github = "dennajort";
|
||||
githubId = 1536838;
|
||||
name = "Jean-Baptiste Gosselin";
|
||||
};
|
||||
derchris = {
|
||||
email = "derchris@me.com";
|
||||
github = "derchrisuk";
|
||||
|
@ -4946,6 +4963,12 @@
|
|||
githubId = 25955146;
|
||||
name = "eyJhb";
|
||||
};
|
||||
f2k1de = {
|
||||
name = "f2k1de";
|
||||
email = "hi@f2k1.de";
|
||||
github = "f2k1de";
|
||||
githubId = 11199213;
|
||||
};
|
||||
f4814n = {
|
||||
email = "me@f4814n.de";
|
||||
github = "f4814";
|
||||
|
@ -6204,6 +6227,12 @@
|
|||
githubId = 982322;
|
||||
name = "Henrik Olsson";
|
||||
};
|
||||
henrirosten = {
|
||||
email = "henri.rosten@unikie.com";
|
||||
github = "henrirosten";
|
||||
githubId = 49935860;
|
||||
name = "Henri Rosten";
|
||||
};
|
||||
henrytill = {
|
||||
email = "henrytill@gmail.com";
|
||||
github = "henrytill";
|
||||
|
@ -6274,6 +6303,14 @@
|
|||
github = "higebu";
|
||||
githubId = 733288;
|
||||
};
|
||||
|
||||
hikari = {
|
||||
email = "HikariNee@protonmail.com";
|
||||
github = "HikariNee";
|
||||
githubId = 72349937;
|
||||
name = "Hikari";
|
||||
};
|
||||
|
||||
hiljusti = {
|
||||
name = "J.R. Hill";
|
||||
email = "hiljusti@so.dang.cool";
|
||||
|
@ -6286,6 +6323,7 @@
|
|||
githubId = 19825977;
|
||||
name = "Hiren Shah";
|
||||
};
|
||||
|
||||
hiro98 = {
|
||||
email = "hiro@protagon.space";
|
||||
github = "vale981";
|
||||
|
@ -6774,6 +6812,15 @@
|
|||
githubId = 54999;
|
||||
name = "Ariel Nunez";
|
||||
};
|
||||
Intuinewin = {
|
||||
email = "antoinelabarussias@gmail.com";
|
||||
github = "Intuinewin";
|
||||
githubId = 13691729;
|
||||
name = "Antoine Labarussias";
|
||||
keys = [{
|
||||
fingerprint = "5CB5 9AA0 D180 1997 2FB3 E0EC 943A 1DE9 372E BE4E";
|
||||
}];
|
||||
};
|
||||
ionutnechita = {
|
||||
email = "ionut_n2001@yahoo.com";
|
||||
github = "ionutnechita";
|
||||
|
@ -7040,7 +7087,7 @@
|
|||
};
|
||||
jayesh-bhoot = {
|
||||
name = "Jayesh Bhoot";
|
||||
email = "jayesh@bhoot.sh";
|
||||
email = "jb@jayeshbhoot.com";
|
||||
github = "jayeshbhoot";
|
||||
githubId = 1915507;
|
||||
};
|
||||
|
@ -7075,6 +7122,13 @@
|
|||
githubId = 221929;
|
||||
name = "Jean-Baptiste Giraudeau";
|
||||
};
|
||||
jbgosselin = {
|
||||
email = "gosselinjb@gmail.com";
|
||||
matrix = "@dennajort:matrix.org";
|
||||
github = "jbgosselin";
|
||||
githubId = 1536838;
|
||||
name = "Jean-Baptiste Gosselin";
|
||||
};
|
||||
jboy = {
|
||||
email = "jboy+nixos@bius.moe";
|
||||
githubId = 2187261;
|
||||
|
@ -7406,6 +7460,12 @@
|
|||
fingerprint = "B768 6CD7 451A 650D 9C54 4204 6710 CF0C 1CBD 7762";
|
||||
}];
|
||||
};
|
||||
jleightcap = {
|
||||
email = "jack@leightcap.com";
|
||||
github = "jleightcap";
|
||||
githubId = 30168080;
|
||||
name = "Jack Leightcap";
|
||||
};
|
||||
jlesquembre = {
|
||||
email = "jl@lafuente.me";
|
||||
github = "jlesquembre";
|
||||
|
@ -7887,6 +7947,12 @@
|
|||
githubId = 2469618;
|
||||
name = "Junji Hashimoto";
|
||||
};
|
||||
jurraca = {
|
||||
email = "julienu@pm.me";
|
||||
github = "jurraca";
|
||||
githubId = 5124422;
|
||||
name = "Julien Urraca";
|
||||
};
|
||||
justinas = {
|
||||
email = "justinas@justinas.org";
|
||||
github = "justinas";
|
||||
|
@ -8067,6 +8133,13 @@
|
|||
githubId = 524492;
|
||||
name = "Sergey Kazenyuk";
|
||||
};
|
||||
kbdharun = {
|
||||
email = "kbdharunkrishna@gmail.com";
|
||||
matrix = "@kbdk:matrix.org";
|
||||
github = "kbdharun";
|
||||
githubId = 26346867;
|
||||
name = "K.B.Dharun Krishna";
|
||||
};
|
||||
kcalvinalvin = {
|
||||
email = "calvin@kcalvinalvin.info";
|
||||
github = "kcalvinalvin";
|
||||
|
@ -9008,6 +9081,12 @@
|
|||
fingerprint = "74F5 E5CC 19D3 B5CB 608F 6124 68FF 81E6 A785 0F49";
|
||||
}];
|
||||
};
|
||||
lizelive = {
|
||||
email = "nixpkgs@lize.live";
|
||||
github = "lizelive";
|
||||
githubId = 40217331;
|
||||
name = "LizeLive";
|
||||
};
|
||||
lluchs = {
|
||||
email = "lukas.werling@gmail.com";
|
||||
github = "lluchs";
|
||||
|
@ -10178,6 +10257,15 @@
|
|||
github = "michaelgrahamevans";
|
||||
githubId = 5932424;
|
||||
};
|
||||
michaelpachec0 = {
|
||||
email = "michaelpacheco@protonmail.com";
|
||||
name = "Michael Pacheco";
|
||||
github = "MichaelPachec0";
|
||||
githubId = 48970112;
|
||||
keys = [ {
|
||||
fingerprint = "8D12 991F 5558 C501 70B2 779C 7811 46B0 B5F9 5F64";
|
||||
}];
|
||||
};
|
||||
michaelpj = {
|
||||
email = "michaelpj@gmail.com";
|
||||
github = "michaelpj";
|
||||
|
@ -12580,9 +12668,9 @@
|
|||
githubId = 17690377;
|
||||
};
|
||||
ppom = {
|
||||
name = "Paco Pompeani";
|
||||
email = "paco@ecomail.io";
|
||||
github = "aopom";
|
||||
name = "ppom";
|
||||
email = "ppom@ecomail.fr";
|
||||
github = "ppom0";
|
||||
githubId = 38916722;
|
||||
};
|
||||
pradeepchhetri = {
|
||||
|
@ -12938,6 +13026,12 @@
|
|||
githubId = 903072;
|
||||
name = "Raghav Sood";
|
||||
};
|
||||
ragingpastry = {
|
||||
email = "senior.crepe@gmail.com";
|
||||
github = "ragingpastry";
|
||||
githubId = 6778250;
|
||||
name = "Nick Wilburn";
|
||||
};
|
||||
raitobezarius = {
|
||||
email = "ryan@lahfa.xyz";
|
||||
matrix = "@raitobezarius:matrix.org";
|
||||
|
@ -14295,6 +14389,12 @@
|
|||
githubId = 487050;
|
||||
name = "Shea Levy";
|
||||
};
|
||||
shlok = {
|
||||
email = "sd-nix-maintainer@quant.is";
|
||||
github = "shlok";
|
||||
githubId = 3000933;
|
||||
name = "Shlok Datye";
|
||||
};
|
||||
shmish111 = {
|
||||
email = "shmish111@gmail.com";
|
||||
github = "shmish111";
|
||||
|
@ -14783,7 +14883,7 @@
|
|||
name = "Christoph Honal";
|
||||
};
|
||||
star-szr = {
|
||||
email = "nixpkgs@scottr.mailworks.org";
|
||||
email = "nixpkgs@szr.fastmail.com";
|
||||
github = "star-szr";
|
||||
githubId = 327943;
|
||||
name = "Scott Zhu Reeves";
|
||||
|
@ -15555,6 +15655,15 @@
|
|||
githubId = 57180880;
|
||||
name = "Ansh Tyagi";
|
||||
};
|
||||
therealr5 = {
|
||||
email = "rouven@rfive.de";
|
||||
github = "therealr5";
|
||||
githubId = 72568063;
|
||||
name = "Rouven Seifert";
|
||||
keys = [{
|
||||
fingerprint = "1169 87A8 DD3F 78FF 8601 BF4D B95E 8FE6 B11C 4D09";
|
||||
}];
|
||||
};
|
||||
therishidesai = {
|
||||
email = "desai.rishi1@gmail.com";
|
||||
github = "therishidesai";
|
||||
|
@ -15853,6 +15962,12 @@
|
|||
githubId = 8577941;
|
||||
name = "Kevin Rauscher";
|
||||
};
|
||||
tomaskala = {
|
||||
email = "public+nixpkgs@tomaskala.com";
|
||||
github = "tomaskala";
|
||||
githubId = 7727887;
|
||||
name = "Tomas Kala";
|
||||
};
|
||||
tomberek = {
|
||||
email = "tomberek@gmail.com";
|
||||
matrix = "@tomberek:matrix.org";
|
||||
|
|
|
@ -50,19 +50,22 @@ while (@ARGV) {
|
|||
}
|
||||
}
|
||||
|
||||
my $bucket;
|
||||
|
||||
# S3 setup.
|
||||
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "AWS_ACCESS_KEY_ID not set\n";
|
||||
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "AWS_SECRET_ACCESS_KEY not set\n";
|
||||
if (not defined $ENV{DEBUG}) {
|
||||
# S3 setup.
|
||||
my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "AWS_ACCESS_KEY_ID not set\n";
|
||||
my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "AWS_SECRET_ACCESS_KEY not set\n";
|
||||
|
||||
my $s3 = Net::Amazon::S3->new(
|
||||
{ aws_access_key_id => $aws_access_key_id,
|
||||
aws_secret_access_key => $aws_secret_access_key,
|
||||
retry => 1,
|
||||
host => "s3-eu-west-1.amazonaws.com",
|
||||
});
|
||||
my $s3 = Net::Amazon::S3->new(
|
||||
{ aws_access_key_id => $aws_access_key_id,
|
||||
aws_secret_access_key => $aws_secret_access_key,
|
||||
retry => 1,
|
||||
host => "s3-eu-west-1.amazonaws.com",
|
||||
});
|
||||
|
||||
my $bucket = $s3->bucket("nixpkgs-tarballs") or die;
|
||||
$bucket = $s3->bucket("nixpkgs-tarballs") or die;
|
||||
}
|
||||
|
||||
my $doWrite = 0;
|
||||
my $cacheFile = ($ENV{"HOME"} or die "\$HOME is not set") . "/.cache/nix/copy-tarballs";
|
||||
|
@ -159,13 +162,18 @@ elsif (defined $expr) {
|
|||
# Check every fetchurl call discovered by find-tarballs.nix.
|
||||
my $mirrored = 0;
|
||||
my $have = 0;
|
||||
foreach my $fetch (sort { $a->{url} cmp $b->{url} } @{$fetches}) {
|
||||
my $url = $fetch->{url};
|
||||
foreach my $fetch (sort { $a->{urls}->[0] cmp $b->{urls}->[0] } @{$fetches}) {
|
||||
my $urls = $fetch->{urls};
|
||||
my $algo = $fetch->{type};
|
||||
my $hash = $fetch->{hash};
|
||||
my $name = $fetch->{name};
|
||||
my $isPatch = $fetch->{isPatch};
|
||||
|
||||
if ($isPatch) {
|
||||
print STDERR "skipping $urls->[0] (support for patches is missing)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($hash =~ /^([a-z0-9]+)-([A-Za-z0-9+\/=]+)$/) {
|
||||
$algo = $1;
|
||||
$hash = `nix hash to-base16 $hash` or die;
|
||||
|
@ -180,62 +188,60 @@ elsif (defined $expr) {
|
|||
chomp $hash;
|
||||
}
|
||||
|
||||
if (defined $ENV{DEBUG}) {
|
||||
print "$url $algo $hash\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($url !~ /^http:/ && $url !~ /^https:/ && $url !~ /^ftp:/ && $url !~ /^mirror:/) {
|
||||
print STDERR "skipping $url (unsupported scheme)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($isPatch) {
|
||||
print STDERR "skipping $url (support for patches is missing)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
next if defined $exclude && $url =~ /$exclude/;
|
||||
|
||||
if (alreadyMirrored($algo, $hash)) {
|
||||
$have++;
|
||||
next;
|
||||
}
|
||||
|
||||
my $storePath = makeFixedOutputPath(0, $algo, $hash, $name);
|
||||
|
||||
print STDERR "mirroring $url ($storePath, $algo, $hash)...\n";
|
||||
for my $url (@$urls) {
|
||||
if (defined $ENV{DEBUG}) {
|
||||
print "$url $algo $hash\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
if ($url !~ /^http:/ && $url !~ /^https:/ && $url !~ /^ftp:/ && $url !~ /^mirror:/) {
|
||||
print STDERR "skipping $url (unsupported scheme)\n";
|
||||
next;
|
||||
}
|
||||
|
||||
next if defined $exclude && $url =~ /$exclude/;
|
||||
|
||||
if (alreadyMirrored($algo, $hash)) {
|
||||
$have++;
|
||||
last;
|
||||
}
|
||||
|
||||
print STDERR "mirroring $url ($storePath, $algo, $hash)...\n";
|
||||
|
||||
if ($dryRun) {
|
||||
$mirrored++;
|
||||
last;
|
||||
}
|
||||
|
||||
# Substitute the output.
|
||||
if (!isValidPath($storePath)) {
|
||||
system("nix-store", "-r", $storePath);
|
||||
}
|
||||
|
||||
# Otherwise download the file using nix-prefetch-url.
|
||||
if (!isValidPath($storePath)) {
|
||||
$ENV{QUIET} = 1;
|
||||
$ENV{PRINT_PATH} = 1;
|
||||
my $fh;
|
||||
my $pid = open($fh, "-|", "nix-prefetch-url", "--type", $algo, $url, $hash) or die;
|
||||
waitpid($pid, 0) or die;
|
||||
if ($? != 0) {
|
||||
print STDERR "failed to fetch $url: $?\n";
|
||||
next;
|
||||
}
|
||||
<$fh>; my $storePath2 = <$fh>; chomp $storePath2;
|
||||
if ($storePath ne $storePath2) {
|
||||
warn "strange: $storePath != $storePath2\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
uploadFile($storePath, $url);
|
||||
$mirrored++;
|
||||
next;
|
||||
last;
|
||||
}
|
||||
|
||||
# Substitute the output.
|
||||
if (!isValidPath($storePath)) {
|
||||
system("nix-store", "-r", $storePath);
|
||||
}
|
||||
|
||||
# Otherwise download the file using nix-prefetch-url.
|
||||
if (!isValidPath($storePath)) {
|
||||
$ENV{QUIET} = 1;
|
||||
$ENV{PRINT_PATH} = 1;
|
||||
my $fh;
|
||||
my $pid = open($fh, "-|", "nix-prefetch-url", "--type", $algo, $url, $hash) or die;
|
||||
waitpid($pid, 0) or die;
|
||||
if ($? != 0) {
|
||||
print STDERR "failed to fetch $url: $?\n";
|
||||
next;
|
||||
}
|
||||
<$fh>; my $storePath2 = <$fh>; chomp $storePath2;
|
||||
if ($storePath ne $storePath2) {
|
||||
warn "strange: $storePath != $storePath2\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
uploadFile($storePath, $url);
|
||||
$mirrored++;
|
||||
}
|
||||
|
||||
print STDERR "mirrored $mirrored files, already have $have files\n";
|
||||
|
|
|
@ -9,12 +9,12 @@ let
|
|||
|
||||
root = expr;
|
||||
|
||||
uniqueUrls = map (x: x.file) (genericClosure {
|
||||
startSet = map (file: { key = file.url; inherit file; }) urls;
|
||||
uniqueFiles = map (x: x.file) (genericClosure {
|
||||
startSet = map (file: { key = with file; (if type == null then "" else type + "+") + hash; inherit file; }) files;
|
||||
operator = const [ ];
|
||||
});
|
||||
|
||||
urls = map (drv: { url = head (drv.urls or [ drv.url ]); hash = drv.outputHash; isPatch = (drv?postFetch && drv.postFetch != ""); type = drv.outputHashAlgo; name = drv.name; }) fetchurlDependencies;
|
||||
files = map (drv: { urls = drv.urls or [ drv.url ]; hash = drv.outputHash; isPatch = (drv?postFetch && drv.postFetch != ""); type = drv.outputHashAlgo; name = drv.name; }) fetchurlDependencies;
|
||||
|
||||
fetchurlDependencies =
|
||||
filter
|
||||
|
@ -47,4 +47,4 @@ let
|
|||
|
||||
canEval = val: (builtins.tryEval val).success;
|
||||
|
||||
in uniqueUrls
|
||||
in uniqueFiles
|
||||
|
|
|
@ -85,7 +85,8 @@ echo "Updating Stackage..."
|
|||
echo "Updating Hackage hashes..."
|
||||
./maintainers/scripts/haskell/update-hackage.sh --do-commit
|
||||
echo "Regenerating Hackage packages..."
|
||||
./maintainers/scripts/haskell/regenerate-hackage-packages.sh --do-commit
|
||||
# Using fast here because after the hackage-update eval errors will likely break the transitive dependencies check.
|
||||
./maintainers/scripts/haskell/regenerate-hackage-packages.sh --fast --do-commit
|
||||
|
||||
# Push these new commits to the haskell-updates branch
|
||||
echo "Pushing commits just created to the remote haskell-updates branch..."
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash -p coreutils jq nix -I nixpkgs=.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
TMP_TEMPLATE=transitive-broken.XXXXXXX
|
||||
readonly TMP_TEMPLATE
|
||||
|
||||
tmpfile=$(mktemp "$TMP_TEMPLATE")
|
||||
|
||||
trap 'rm -f "${tmpfile}"' 0
|
||||
|
||||
config_file=pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml
|
||||
|
||||
cat > $config_file << EOF
|
||||
cat > $tmpfile << EOF
|
||||
# This file is automatically generated by
|
||||
# maintainers/scripts/haskell/regenerate-transitive-broken-packages.sh
|
||||
# It is supposed to list all haskellPackages that cannot evaluate because they
|
||||
|
@ -11,4 +20,6 @@ cat > $config_file << EOF
|
|||
dont-distribute-packages:
|
||||
EOF
|
||||
|
||||
nix-instantiate --eval --option restrict-eval true -I . --strict --json maintainers/scripts/haskell/transitive-broken-packages.nix | jq -r . | LC_ALL=C.UTF-8 sort -i >> $config_file
|
||||
nix-instantiate --eval --option restrict-eval true -I . --strict --json maintainers/scripts/haskell/transitive-broken-packages.nix | jq -r . | LC_ALL=C.UTF-8 sort -i >> $tmpfile
|
||||
|
||||
mv $tmpfile $config_file
|
||||
|
|
|
@ -151,6 +151,8 @@ with lib.maintainers; {
|
|||
|
||||
cuda = {
|
||||
members = [
|
||||
connorbaker
|
||||
samuela
|
||||
SomeoneSerge
|
||||
];
|
||||
scope = "Maintain CUDA-enabled packages";
|
||||
|
@ -521,6 +523,7 @@ with lib.maintainers; {
|
|||
|
||||
mate = {
|
||||
members = [
|
||||
bobby285271
|
||||
j03
|
||||
romildo
|
||||
];
|
||||
|
@ -827,6 +830,7 @@ with lib.maintainers; {
|
|||
|
||||
xfce = {
|
||||
members = [
|
||||
bobby285271
|
||||
romildo
|
||||
muscaln
|
||||
];
|
||||
|
|
|
@ -99,6 +99,10 @@ merging is handled.
|
|||
problems.
|
||||
:::
|
||||
|
||||
`types.pkgs`
|
||||
|
||||
: A type for the top level Nixpkgs package set.
|
||||
|
||||
### Numeric types {#sec-option-types-numeric}
|
||||
|
||||
`types.int`
|
||||
|
|
|
@ -4,7 +4,7 @@ This manual describes how to install, use and extend NixOS, a Linux distribution
|
|||
|
||||
Additional information regarding the Nix package manager and the Nixpkgs project can be found in respectively the [Nix manual](https://nixos.org/nix/manual) and the [Nixpkgs manual](https://nixos.org/nixpkgs/manual).
|
||||
|
||||
If you encounter problems, please report them on the [`Discourse`](https://discourse.nixos.org), the [Matrix room](https://matrix.to/#nix:nixos.org), or on the [`#nixos` channel on Libera.Chat](irc://irc.libera.chat/#nixos). Alternatively, consider [contributing to this manual](#chap-contributing). Bugs should be reported in [NixOS’ GitHub issue tracker](https://github.com/NixOS/nixpkgs/issues).
|
||||
If you encounter problems, please report them on the [`Discourse`](https://discourse.nixos.org), the [Matrix room](https://matrix.to/#/%23nix:nixos.org), or on the [`#nixos` channel on Libera.Chat](irc://irc.libera.chat/#nixos). Alternatively, consider [contributing to this manual](#chap-contributing). Bugs should be reported in [NixOS’ GitHub issue tracker](https://github.com/NixOS/nixpkgs/issues).
|
||||
|
||||
::: {.note}
|
||||
Commands prefixed with `#` have to be run as root, either requiring to login as root user or temporarily switching to it using `sudo` for example.
|
||||
|
|
|
@ -24,6 +24,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- KDE Plasma has been updated to v5.27, see [the release notes](https://kde.org/announcements/plasma/5/5.27.0/) for what is changed.
|
||||
|
||||
- Python implements [PEP 668](https://peps.python.org/pep-0668/), providing better feedback to users that try to run `pip install` system-wide.
|
||||
|
||||
- `nixos-rebuild` now supports an extra `--specialisation` option that can be used to change specialisation for `switch` and `test` commands.
|
||||
|
||||
- `libxcrypt`, the library providing the `crypt(3)` password hashing function, is now built without support for algorithms not flagged [`strong`](https://github.com/besser82/libxcrypt/blob/v4.4.33/lib/hashes.conf#L48). This affects the availability of password hashing algorithms used for system login (`login(1)`, `passwd(1)`), but also Apache2 Basic-Auth, Samba, OpenLDAP, Dovecot, and [many other packages](https://github.com/search?q=repo%3ANixOS%2Fnixpkgs%20libxcrypt&type=code).
|
||||
|
@ -36,6 +38,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [Akkoma](https://akkoma.social), an ActivityPub microblogging server. Available as [services.akkoma](options.html#opt-services.akkoma.enable).
|
||||
|
||||
- [Pixelfed](https://pixelfed.org/), an Instagram-like ActivityPub server. Available as [services.pixelfed](options.html#opt-services.pixelfed.enable).
|
||||
|
||||
- [blesh](https://github.com/akinomyoga/ble.sh), a line editor written in pure bash. Available as [programs.bash.blesh](#opt-programs.bash.blesh.enable).
|
||||
|
||||
- [webhook](https://github.com/adnanh/webhook), a lightweight webhook server. Available as [services.webhook](#opt-services.webhook.enable).
|
||||
|
@ -56,8 +60,12 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [gemstash](https://github.com/rubygems/gemstash), a RubyGems.org cache and private gem server. Available as [services.gemstash](#opt-services.gemstash.enable).
|
||||
|
||||
- [gitea-actions-runner](https://gitea.com/gitea/act_runner), a CI runner for Gitea/Forgejo Actions. Available as [services.gitea-actions-runner](#opt-services.gitea-actions-runner.instances).
|
||||
|
||||
- [gmediarender](https://github.com/hzeller/gmrender-resurrect), a simple, headless UPnP/DLNA renderer. Available as [services.gmediarender](options.html#opt-services.gmediarender.enable).
|
||||
|
||||
- [harmonia](https://github.com/nix-community/harmonia/), Nix binary cache implemented in rust using libnix-store. Available as [services.harmonia](options.html#opt-services.harmonia.enable).
|
||||
|
||||
- [hyprland](https://github.com/hyprwm/hyprland), a dynamic tiling Wayland compositor that doesn't sacrifice on its looks. Available as [programs.hyprland](#opt-programs.hyprland.enable).
|
||||
|
||||
- [minipro](https://gitlab.com/DavidGriffith/minipro/), an open source program for controlling the MiniPRO TL866xx series of chip programmers. Available as [programs.minipro](options.html#opt-programs.minipro.enable).
|
||||
|
@ -88,6 +96,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [networkd-dispatcher](https://gitlab.com/craftyguy/networkd-dispatcher), a dispatcher service for systemd-networkd connection status changes. Available as [services.networkd-dispatcher](#opt-services.networkd-dispatcher.enable).
|
||||
|
||||
- [gonic](https://github.com/sentriz/gonic), a Subsonic music streaming server. Available as [services.gonic](#opt-services.gonic.enable).
|
||||
|
||||
- [mmsd](https://gitlab.com/kop316/mmsd), a lower level daemon that transmits and recieves MMSes. Available as [services.mmsd](#opt-services.mmsd.enable).
|
||||
|
||||
- [QDMR](https://dm3mat.darc.de/qdmr/), a GUI application and command line tool for programming DMR radios [programs.qdmr](#opt-programs.qdmr.enable)
|
||||
|
@ -98,8 +108,12 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [vault-agent](https://developer.hashicorp.com/vault/docs/agent), a template rendering and API auth proxy for HashiCorp Vault, similar to `consul-template`. Available as [services.vault-agent](#opt-services.vault-agent.instances).
|
||||
|
||||
- [trippy](https://github.com/fujiapple852/trippy), a network diagnostic tool. Available as [programs.trippy](#opt-programs.trippy.enable).
|
||||
|
||||
- [v2rayA](https://v2raya.org), a Linux web GUI client of Project V which supports V2Ray, Xray, SS, SSR, Trojan and Pingtunnel. Available as [services.v2raya](options.html#opt-services.v2raya.enable).
|
||||
|
||||
- [rshim](https://github.com/Mellanox/rshim-user-space), the user-space rshim driver for the BlueField SoC. Available as [services.rshim](options.html#opt-services.rshim.enable).
|
||||
|
||||
- [wstunnel](https://github.com/erebe/wstunnel), a proxy tunnelling arbitrary TCP or UDP traffic through a WebSocket connection. Instances may be configured via [services.wstunnel](options.html#opt-services.wstunnel.enable).
|
||||
|
||||
- [ulogd](https://www.netfilter.org/projects/ulogd/index.html), a userspace logging daemon for netfilter/iptables related logging. Available as [services.ulogd](options.html#opt-services.ulogd.enable).
|
||||
|
@ -110,8 +124,14 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [stargazer](https://sr.ht/~zethra/stargazer/), a fast and easy to use Gemini server. Available as [services.stargazer](#opt-services.stargazer.enable).
|
||||
|
||||
- [sniffnet](https://github.com/GyulyVGC/sniffnet), an application to monitor your network traffic. Available as [programs.sniffnet](#opt-programs.sniffnet.enable).
|
||||
|
||||
- [photoprism](https://photoprism.app/), a AI-Powered Photos App for the Decentralized Web. Available as [services.photoprism](options.html#opt-services.photoprism.enable).
|
||||
|
||||
- [alice-lg](github.com/alice-lg/alice-lg), a looking-glass for BGP sessions. Available as [services.alice-lg](#opt-services.alice-lg.enable).
|
||||
|
||||
- [birdwatcher](github.com/alice-lg/birdwatcher), a small HTTP server meant to provide an API defined by Barry O'Donovan's birds-eye to the BIRD internet routing daemon. Available as [services.birdwatcher](#opt-services.birdwatcher.enable).
|
||||
|
||||
- [peroxide](https://github.com/ljanyst/peroxide), a fork of the official [ProtonMail bridge](https://github.com/ProtonMail/proton-bridge) that aims to be similar to [Hydroxide](https://github.com/emersion/hydroxide). Available as [services.peroxide](#opt-services.peroxide.enable).
|
||||
|
||||
- [autosuspend](https://github.com/languitar/autosuspend), a python daemon that suspends a system if certain conditions are met, or not met.
|
||||
|
@ -138,6 +158,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [ivpn](https://www.ivpn.net/), a secure, private VPN with fast WireGuard connections. Available as [services.ivpn](#opt-services.ivpn.enable).
|
||||
|
||||
- [openvscode-server](https://github.com/gitpod-io/openvscode-server), run VS Code on a remote machine with access through a modern web browser from any device, anywhere. Available as [services.openvscode-server](#opt-services.openvscode-server.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-23.05-incompatibilities}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
@ -154,6 +176,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- The `ssh` client tool now disables the `~C` escape sequence by default. This can be re-enabled by setting `EnableEscapeCommandline yes`
|
||||
|
||||
- Many `services.syncthing` options have been moved to `services.syncthing.settings`, as part of [RFC 42](https://github.com/NixOS/rfcs/pull/42)'s implementation, see [#226088](https://github.com/NixOS/nixpkgs/pull/226088).
|
||||
|
||||
- The `ssh` module does not read `/etc/ssh/ssh_known_hosts2` anymore since this location is [deprecated since 2001](https://marc.info/?l=openssh-unix-dev&m=100508718416162&w=2).
|
||||
|
||||
- The openssh module does not read `~/.ssh/authorized_keys2` anymore since this location is [deprecated since 2001](https://marc.info/?l=openssh-unix-dev&m=100508718416162&w=2).
|
||||
|
@ -162,6 +186,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- `git-bug` has been updated to at least version 0.8.0, which includes backwards incompatible changes. The `git-bug-migration` package can be used to upgrade existing repositories.
|
||||
|
||||
- `graylog` has been updated to version 5, which can not be upgraded directly from the previously packaged version 3.3. If you had installed the previously packaged version 3.3, please follow the [upgrade path](https://go2docs.graylog.org/5-0/upgrading_graylog/upgrade_path.htm) from 3.3 to 4.0 to 4.3 to 5.0.
|
||||
|
||||
- `nushell` has been updated to at least version 0.77.0, which includes potential breaking changes in aliases. The old aliases are now available as `old-alias` but it is recommended you migrate to the new format. See [Reworked aliases](https://www.nushell.sh/blog/2023-03-14-nushell_0_77.html#reworked-aliases-breaking-changes-kubouch).
|
||||
|
||||
- `keepassx` and `keepassx2` have been removed, due to upstream [stopping development](https://www.keepassx.org/index.html%3Fp=636.html). Consider [KeePassXC](https://keepassxc.org) as a maintained alternative.
|
||||
|
@ -177,6 +203,26 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- `services.sourcehut.dispatch` and the corresponding package (`sourcehut.dispatchsrht`) have been removed due to [upstream deprecation](https://sourcehut.org/blog/2022-08-01-dispatch-deprecation-plans/).
|
||||
|
||||
- The attributes used by `services.snapper.configs.<name>` have changed. Migrate from this:
|
||||
|
||||
```nix
|
||||
services.snapper.configs.example = {
|
||||
subvolume = "/example";
|
||||
extraConfig = ''
|
||||
ALLOW_USERS="alice"
|
||||
'';
|
||||
};
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
```nix
|
||||
services.snapper.configs.example = {
|
||||
SUBVOLUME = "/example";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
};
|
||||
```
|
||||
|
||||
- The [services.snapserver.openFirewall](#opt-services.snapserver.openFirewall) module option default value has been changed from `true` to `false`. You will need to explicitly set this option to `true`, or configure your firewall.
|
||||
|
||||
- The [services.tmate-ssh-server.openFirewall](#opt-services.tmate-ssh-server.openFirewall) module option default value has been changed from `true` to `false`. You will need to explicitly set this option to `true`, or configure your firewall.
|
||||
|
@ -225,7 +271,6 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [`services.nextcloud.database.createLocally`](#opt-services.nextcloud.database.createLocally) now uses socket authentication and is no longer compatible with password authentication.
|
||||
- If you want the module to manage the database for you, unset [`services.nextcloud.config.dbpassFile`](#opt-services.nextcloud.config.dbpassFile) (and [`services.nextcloud.config.dbhost`](#opt-services.nextcloud.config.dbhost), if it's set).
|
||||
- If your database is external, simply set [`services.nextcloud.database.createLocally`](#opt-services.nextcloud.database.createLocally) to `false`.
|
||||
- If you want to use password authentication **and** create the database locally, you will have to use [`services.mysql`](#opt-services.mysql.enable) to set it up.
|
||||
|
||||
- `protonmail-bridge` package has been updated to major version 3.
|
||||
|
@ -259,6 +304,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [services.xserver.videoDrivers](options.html#opt-services.xserver.videoDrivers) now defaults to the `modesetting` driver over device-specific ones. The `radeon`, `amdgpu` and `nouveau` drivers are still available, but effectively unmaintained and not recommended for use.
|
||||
|
||||
- [services.xserver.libinput.enable](options.html#opt-services.xserver.libinput.enable) is now set by default, enabling the more actively maintained and consistently behaved input device driver.
|
||||
|
||||
- To enable the HTTP3 (QUIC) protocol for a nginx virtual host, set the `quic` attribute on it to true, e.g. `services.nginx.virtualHosts.<name>.quic = true;`.
|
||||
|
||||
- In `services.fail2ban`, `bantime-increment.<name>` options now default to `null` (except `bantime-increment.enable`) and are used to set the corresponding option in `jail.local` only if not `null`. Also, enforce that `bantime-increment.formula` and `bantime-increment.multipliers` are not both specified.
|
||||
|
@ -288,6 +335,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- The `zplug` package changes its output path from `$out` to `$out/share/zplug`. Users should update their dependency on `${pkgs.zplug}/init.zsh` to `${pkgs.zplug}/share/zplug/init.zsh`.
|
||||
|
||||
- The `pict-rs` package was updated from an 0.3 alpha release to 0.3 stable, and related environment variables now require two underscores instead of one.
|
||||
|
||||
## Other Notable Changes {#sec-release-23.05-notable-changes}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
@ -334,13 +383,15 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- `services.maddy` got several updates:
|
||||
- Configuration of users and their credentials using `services.maddy.ensureCredentials`.
|
||||
- Configuration of TLS key and certificate files using `services.maddy.tls`.
|
||||
- TLS configuration is now possible via `services.maddy.tls` with two loaders present: ACME and file based.
|
||||
|
||||
- The `dnsmasq` service now takes configuration via the
|
||||
`services.dnsmasq.settings` attribute set. The option
|
||||
`services.dnsmasq.extraConfig` will be deprecated when NixOS 22.11 reaches
|
||||
end of life.
|
||||
|
||||
- `kube3d` has now been renamed to `k3d` since the 3d editor that originally took that name has been dropped from nixpkgs. `kube3d` will continue to work as an alias for now.
|
||||
|
||||
- The `dokuwiki` service is now configured via `services.dokuwiki.sites.<name>.settings` attribute set; `extraConfig` has been removed.
|
||||
The `{aclUse,superUser,disableActions}` attributes have been renamed accordingly. `pluginsConfig` now only accepts an attribute set of booleans.
|
||||
Passing plain PHP is no longer possible.
|
||||
|
@ -367,6 +418,28 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- `nextcloud` has an option to enable SSE-C in S3.
|
||||
|
||||
- NixOS swap partitions with random encryption can now control the sector size, cipher, and key size used to setup the plain encryption device over the
|
||||
underlying block device rather than allowing them to be determined by `cryptsetup(8)`. One can use these features like so:
|
||||
|
||||
```nix
|
||||
{
|
||||
swapDevices = [
|
||||
{
|
||||
device = "/dev/disk/by-partlabel/swapspace";
|
||||
|
||||
randomEncryption = {
|
||||
enable = true;
|
||||
cipher = "aes-xts-plain64";
|
||||
keySize = 512;
|
||||
sectorSize = 4096;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- New option `security.pam.zfs` to enable unlocking and mounting of encrypted ZFS home dataset at login.
|
||||
|
||||
- `services.peertube` now requires you to specify the secret file `secrets.secretsFile`. It can be generated by running `openssl rand -hex 32`.
|
||||
Before upgrading, read the release notes for PeerTube:
|
||||
- [Release v5.0.0](https://github.com/Chocobozzz/PeerTube/releases/tag/v5.0.0)
|
||||
|
@ -385,6 +458,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
}
|
||||
```
|
||||
|
||||
- `services.netdata` offers a `deadlineBeforeStopSec` option which enable users who have netdata instance that takes time to initialize to not have systemd kill them for no reason.
|
||||
|
||||
- `services.dhcpcd` service now don't solicit or accept IPv6 Router Advertisements on interfaces that use static IPv6 addresses.
|
||||
If network uses both IPv6 Unique local addresses (ULA) and global IPv6 address auto-configuration with SLAAC, must add the parameter `networking.dhcpcd.IPv6rs = true;`.
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ let pkgs_ = pkgs;
|
|||
in
|
||||
|
||||
let
|
||||
inherit (lib) optional;
|
||||
|
||||
evalModulesMinimal = (import ./default.nix {
|
||||
inherit lib;
|
||||
# Implicit use of feature is noted in implementation.
|
||||
|
@ -47,15 +49,19 @@ let
|
|||
pkgsModule = rec {
|
||||
_file = ./eval-config.nix;
|
||||
key = _file;
|
||||
config = {
|
||||
# Explicit `nixpkgs.system` or `nixpkgs.localSystem` should override
|
||||
# this. Since the latter defaults to the former, the former should
|
||||
# default to the argument. That way this new default could propagate all
|
||||
# they way through, but has the last priority behind everything else.
|
||||
nixpkgs.system = lib.mkIf (system != null) (lib.mkDefault system);
|
||||
|
||||
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
|
||||
};
|
||||
config = lib.mkMerge (
|
||||
(optional (system != null) {
|
||||
# Explicit `nixpkgs.system` or `nixpkgs.localSystem` should override
|
||||
# this. Since the latter defaults to the former, the former should
|
||||
# default to the argument. That way this new default could propagate all
|
||||
# they way through, but has the last priority behind everything else.
|
||||
nixpkgs.system = lib.mkDefault system;
|
||||
})
|
||||
++
|
||||
(optional (pkgs_ != null) {
|
||||
_module.args.pkgs = lib.mkForce pkgs_;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
withWarnings = x:
|
||||
|
|
|
@ -511,7 +511,7 @@ let format' = format; in let
|
|||
${if format == "raw" then ''
|
||||
mv $diskImage $out/${filename}
|
||||
'' else ''
|
||||
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${format} ${compress} $diskImage $out/${filename}
|
||||
${pkgs.qemu-utils}/bin/qemu-img convert -f raw -O ${format} ${compress} $diskImage $out/${filename}
|
||||
''}
|
||||
diskImage=$out/${filename}
|
||||
'';
|
||||
|
|
|
@ -261,8 +261,8 @@ let
|
|||
mv $bootDiskImage $out/${bootFilename}
|
||||
mv $rootDiskImage $out/${rootFilename}
|
||||
'' else ''
|
||||
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $bootDiskImage $out/${bootFilename}
|
||||
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $rootDiskImage $out/${rootFilename}
|
||||
${pkgs.qemu_kvm}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $bootDiskImage $out/${bootFilename}
|
||||
${pkgs.qemu_kvm}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $rootDiskImage $out/${rootFilename}
|
||||
''}
|
||||
bootDiskImage=$out/${bootFilename}
|
||||
rootDiskImage=$out/${rootFilename}
|
||||
|
|
|
@ -244,7 +244,7 @@ let
|
|||
${if formatOpt == "raw" then ''
|
||||
mv $rootDiskImage $out/${rootFilename}
|
||||
'' else ''
|
||||
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $rootDiskImage $out/${rootFilename}
|
||||
${pkgs.qemu_kvm}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $rootDiskImage $out/${rootFilename}
|
||||
''}
|
||||
rootDiskImage=$out/${rootFilename}
|
||||
set -x
|
||||
|
|
|
@ -7,6 +7,7 @@ import io
|
|||
import os
|
||||
import queue
|
||||
import re
|
||||
import select
|
||||
import shlex
|
||||
import shutil
|
||||
import socket
|
||||
|
@ -99,7 +100,7 @@ def _perform_ocr_on_screenshot(
|
|||
+ "-blur 1x65535"
|
||||
)
|
||||
|
||||
tess_args = f"-c debug_file=/dev/null --psm 11"
|
||||
tess_args = "-c debug_file=/dev/null --psm 11"
|
||||
|
||||
cmd = f"convert {magick_args} '{screenshot_path}' 'tiff:{screenshot_path}.tiff'"
|
||||
ret = subprocess.run(cmd, shell=True, capture_output=True)
|
||||
|
@ -154,6 +155,7 @@ class StartCommand:
|
|||
# qemu options
|
||||
qemu_opts = (
|
||||
" -device virtio-serial"
|
||||
# Note: virtconsole will map to /dev/hvc0 in Linux guests
|
||||
" -device virtconsole,chardev=shell"
|
||||
" -device virtio-rng-pci"
|
||||
" -serial stdio"
|
||||
|
@ -524,8 +526,10 @@ class Machine:
|
|||
if timeout is not None:
|
||||
timeout_str = f"timeout {timeout}"
|
||||
|
||||
# While sh is bash on NixOS, this is not the case for every distro.
|
||||
# We explicitely call bash here to allow for the driver to boot other distros as well.
|
||||
out_command = (
|
||||
f"{timeout_str} sh -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n"
|
||||
f"{timeout_str} bash -c {shlex.quote(command)} | (base64 --wrap 0; echo)\n"
|
||||
)
|
||||
|
||||
assert self.shell
|
||||
|
@ -719,6 +723,15 @@ class Machine:
|
|||
self.wait_for_unit(jobname)
|
||||
|
||||
def connect(self) -> None:
|
||||
def shell_ready(timeout_secs: int) -> bool:
|
||||
"""We sent some data from the backdoor service running on the guest
|
||||
to indicate that the backdoor shell is ready.
|
||||
As soon as we read some data from the socket here, we assume that
|
||||
our root shell is operational.
|
||||
"""
|
||||
(ready, _, _) = select.select([self.shell], [], [], timeout_secs)
|
||||
return bool(ready)
|
||||
|
||||
if self.connected:
|
||||
return
|
||||
|
||||
|
@ -728,8 +741,11 @@ class Machine:
|
|||
assert self.shell
|
||||
|
||||
tic = time.time()
|
||||
self.shell.recv(1024)
|
||||
# TODO: Timeout
|
||||
# TODO: do we want to bail after a set number of attempts?
|
||||
while not shell_ready(timeout_secs=30):
|
||||
self.log("Guest root shell did not produce any data yet...")
|
||||
|
||||
self.log(self.shell.recv(1024).decode())
|
||||
toc = time.time()
|
||||
|
||||
self.log("connected to guest root shell")
|
||||
|
@ -950,7 +966,7 @@ class Machine:
|
|||
Prepares the machine to be reconnected which is useful if the
|
||||
machine was started with `allow_reboot = True`
|
||||
"""
|
||||
self.send_key(f"ctrl-alt-delete")
|
||||
self.send_key("ctrl-alt-delete")
|
||||
self.connected = False
|
||||
|
||||
def wait_for_x(self) -> None:
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
testModuleArgs@{ config, lib, hostPkgs, nodes, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption mkForce optional types mapAttrs mkDefault mdDoc;
|
||||
|
||||
system = hostPkgs.stdenv.hostPlatform.system;
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
literalMD
|
||||
mapAttrs
|
||||
mdDoc
|
||||
mkDefault
|
||||
mkIf
|
||||
mkOption mkForce
|
||||
optional
|
||||
optionalAttrs
|
||||
types
|
||||
;
|
||||
|
||||
baseOS =
|
||||
import ../eval-config.nix {
|
||||
inherit system;
|
||||
system = null; # use modularly defined system
|
||||
inherit (config.node) specialArgs;
|
||||
modules = [ config.defaults ];
|
||||
baseModules = (import ../../modules/module-list.nix) ++
|
||||
|
@ -17,11 +26,17 @@ let
|
|||
({ config, ... }:
|
||||
{
|
||||
virtualisation.qemu.package = testModuleArgs.config.qemu.package;
|
||||
|
||||
})
|
||||
(optionalAttrs (!config.node.pkgsReadOnly) {
|
||||
key = "nodes.nix-pkgs";
|
||||
config = {
|
||||
# Ensure we do not use aliases. Ideally this is only set
|
||||
# when the test framework is used by Nixpkgs NixOS tests.
|
||||
nixpkgs.config.allowAliases = false;
|
||||
})
|
||||
# TODO: switch to nixpkgs.hostPlatform and make sure containers-imperative test still evaluates.
|
||||
nixpkgs.system = hostPkgs.stdenv.hostPlatform.system;
|
||||
};
|
||||
})
|
||||
testModuleArgs.config.extraBaseModules
|
||||
];
|
||||
};
|
||||
|
@ -68,6 +83,30 @@ in
|
|||
default = { };
|
||||
};
|
||||
|
||||
node.pkgs = mkOption {
|
||||
description = mdDoc ''
|
||||
The Nixpkgs to use for the nodes.
|
||||
|
||||
Setting this will make the `nixpkgs.*` options read-only, to avoid mistakenly testing with a Nixpkgs configuration that diverges from regular use.
|
||||
'';
|
||||
type = types.nullOr types.pkgs;
|
||||
default = null;
|
||||
defaultText = literalMD ''
|
||||
`null`, so construct `pkgs` according to the `nixpkgs.*` options as usual.
|
||||
'';
|
||||
};
|
||||
|
||||
node.pkgsReadOnly = mkOption {
|
||||
description = mdDoc ''
|
||||
Whether to make the `nixpkgs.*` options read-only. This is only relevant when [`node.pkgs`](#test-opt-node.pkgs) is set.
|
||||
|
||||
Set this to `false` when any of the [`nodes`](#test-opt-nodes) needs to configure any of the `nixpkgs.*` options. This will slow down evaluation of your test a bit.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = config.node.pkgs != null;
|
||||
defaultText = literalExpression ''node.pkgs != null'';
|
||||
};
|
||||
|
||||
node.specialArgs = mkOption {
|
||||
type = types.lazyAttrsOf types.raw;
|
||||
default = { };
|
||||
|
@ -100,5 +139,11 @@ in
|
|||
config.nodes;
|
||||
|
||||
passthru.nodes = config.nodesCompat;
|
||||
|
||||
defaults = mkIf config.node.pkgsReadOnly {
|
||||
nixpkgs.pkgs = config.node.pkgs;
|
||||
imports = [ ../../modules/misc/nixpkgs/read-only.nix ];
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports =
|
||||
[ ../../../modules/virtualisation/cloudstack-config.nix ];
|
||||
|
|
|
@ -102,8 +102,8 @@ in {
|
|||
${pkgs.jq}/bin/jq -n \
|
||||
--arg system_label ${lib.escapeShellArg config.system.nixos.label} \
|
||||
--arg system ${lib.escapeShellArg pkgs.stdenv.hostPlatform.system} \
|
||||
--arg root_logical_bytes "$(${pkgs.qemu}/bin/qemu-img info --output json "$rootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg boot_logical_bytes "$(${pkgs.qemu}/bin/qemu-img info --output json "$bootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg root_logical_bytes "$(${pkgs.qemu_kvm}/bin/qemu-img info --output json "$rootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg boot_logical_bytes "$(${pkgs.qemu_kvm}/bin/qemu-img info --output json "$bootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg boot_mode "${amiBootMode}" \
|
||||
--arg root "$rootDisk" \
|
||||
--arg boot "$bootDisk" \
|
||||
|
@ -142,7 +142,7 @@ in {
|
|||
${pkgs.jq}/bin/jq -n \
|
||||
--arg system_label ${lib.escapeShellArg config.system.nixos.label} \
|
||||
--arg system ${lib.escapeShellArg pkgs.stdenv.hostPlatform.system} \
|
||||
--arg logical_bytes "$(${pkgs.qemu}/bin/qemu-img info --output json "$diskImage" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg logical_bytes "$(${pkgs.qemu_kvm}/bin/qemu-img info --output json "$diskImage" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg boot_mode "${amiBootMode}" \
|
||||
--arg file "$diskImage" \
|
||||
'{}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the default lxd configuration.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
imports = [
|
||||
../../../modules/virtualisation/lxc-container.nix
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
# WARNING: THIS CONFIGURATION IS AUTOGENERATED AND WILL BE OVERWRITTEN AUTOMATICALLY
|
||||
|
||||
{
|
||||
|
|
|
@ -85,7 +85,7 @@ in
|
|||
${pkgs.jq}/bin/jq -n \
|
||||
--arg system_label ${lib.escapeShellArg config.system.nixos.label} \
|
||||
--arg system ${lib.escapeShellArg pkgs.stdenv.hostPlatform.system} \
|
||||
--arg root_logical_bytes "$(${pkgs.qemu}/bin/qemu-img info --output json "$rootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg root_logical_bytes "$(${pkgs.qemu_kvm}/bin/qemu-img info --output json "$rootDisk" | ${pkgs.jq}/bin/jq '."virtual-size"')" \
|
||||
--arg boot_mode "${imageBootMode}" \
|
||||
--arg root "$rootDisk" \
|
||||
'{}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
# GNU GRUB, where available.
|
||||
boot.loader.grub.enable = !pkgs.stdenv.isAarch32;
|
||||
boot.loader.grub.version = 2;
|
||||
|
||||
# GNU lsh.
|
||||
services.openssh.enable = false;
|
||||
|
|
|
@ -30,7 +30,7 @@ let
|
|||
|
||||
systemPlatform = platformMap.${pkgs.stdenv.hostPlatform.system} or (throw "scudo not supported on ${pkgs.stdenv.hostPlatform.system}");
|
||||
in {
|
||||
libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-${systemPlatform}.so";
|
||||
libPath = "${pkgs.llvmPackages_14.compiler-rt}/lib/linux/libclang_rt.scudo-${systemPlatform}.so";
|
||||
description = ''
|
||||
A user-mode allocator based on LLVM Sanitizer’s CombinedAllocator,
|
||||
which aims at providing additional mitigations against heap based
|
||||
|
|
|
@ -47,7 +47,7 @@ with lib;
|
|||
libva = super.libva-minimal;
|
||||
limesuite = super.limesuite.override { withGui = false; };
|
||||
mc = super.mc.override { x11Support = false; };
|
||||
mpv-unwrapped = super.mpv-unwrapped.override { sdl2Support = false; x11Support = false; };
|
||||
mpv-unwrapped = super.mpv-unwrapped.override { sdl2Support = false; x11Support = false; waylandSupport = false; };
|
||||
msmtp = super.msmtp.override { withKeyring = false; };
|
||||
neofetch = super.neofetch.override { x11Support = false; };
|
||||
networkmanager-fortisslvpn = super.networkmanager-fortisslvpn.override { withGnome = false; };
|
||||
|
@ -59,6 +59,7 @@ with lib;
|
|||
networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
|
||||
pango = super.pango.override { x11Support = false; };
|
||||
pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; };
|
||||
pipewire = super.pipewire.override { x11Support = false; };
|
||||
qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; };
|
||||
qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; });
|
||||
qt5 = super.qt5.overrideScope (const (super': {
|
||||
|
|
|
@ -38,6 +38,34 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
keySize = mkOption {
|
||||
default = null;
|
||||
example = "512";
|
||||
type = types.nullOr types.int;
|
||||
description = lib.mdDoc ''
|
||||
Set the encryption key size for the plain device.
|
||||
|
||||
If not specified, the amount of data to read from `source` will be
|
||||
determined by cryptsetup.
|
||||
|
||||
See `cryptsetup-open(8)` for details.
|
||||
'';
|
||||
};
|
||||
|
||||
sectorSize = mkOption {
|
||||
default = null;
|
||||
example = "4096";
|
||||
type = types.nullOr types.int;
|
||||
description = lib.mdDoc ''
|
||||
Set the sector size for the plain encrypted device type.
|
||||
|
||||
If not specified, the default sector size is determined from the
|
||||
underlying block device.
|
||||
|
||||
See `cryptsetup-open(8)` for details.
|
||||
'';
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
default = "/dev/urandom";
|
||||
example = "/dev/random";
|
||||
|
@ -157,11 +185,11 @@ let
|
|||
|
||||
};
|
||||
|
||||
config = rec {
|
||||
config = {
|
||||
device = mkIf options.label.isDefined
|
||||
"/dev/disk/by-label/${config.label}";
|
||||
deviceName = lib.replaceStrings ["\\"] [""] (escapeSystemdPath config.device);
|
||||
realDevice = if config.randomEncryption.enable then "/dev/mapper/${deviceName}" else config.device;
|
||||
realDevice = if config.randomEncryption.enable then "/dev/mapper/${config.deviceName}" else config.device;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -247,7 +275,11 @@ in
|
|||
''}
|
||||
${optionalString sw.randomEncryption.enable ''
|
||||
cryptsetup plainOpen -c ${sw.randomEncryption.cipher} -d ${sw.randomEncryption.source} \
|
||||
${optionalString sw.randomEncryption.allowDiscards "--allow-discards"} ${sw.device} ${sw.deviceName}
|
||||
${concatStringsSep " \\\n" (flatten [
|
||||
(optional (sw.randomEncryption.sectorSize != null) "--sector-size=${toString sw.randomEncryption.sectorSize}")
|
||||
(optional (sw.randomEncryption.keySize != null) "--key-size=${toString sw.randomEncryption.keySize}")
|
||||
(optional sw.randomEncryption.allowDiscards "--allow-discards")
|
||||
])} ${sw.device} ${sw.deviceName}
|
||||
mkswap ${sw.realDevice}
|
||||
''}
|
||||
'';
|
||||
|
|
|
@ -473,7 +473,7 @@ in
|
|||
};
|
||||
|
||||
isoImage.squashfsCompression = mkOption {
|
||||
default = with pkgs.stdenv.targetPlatform; "xz -Xdict-size 100% "
|
||||
default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% "
|
||||
+ lib.optionalString isx86 "-Xbcj x86"
|
||||
# Untested but should also reduce size for these platforms
|
||||
+ lib.optionalString isAarch "-Xbcj arm"
|
||||
|
@ -483,6 +483,7 @@ in
|
|||
Compression settings to use for the squashfs nix store.
|
||||
'';
|
||||
example = "zstd -Xcompression-level 6";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
isoImage.edition = mkOption {
|
||||
|
@ -693,8 +694,6 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
boot.loader.grub.version = 2;
|
||||
|
||||
# Don't build the GRUB menu builder script, since we don't need it
|
||||
# here and it causes a cyclic dependency.
|
||||
boot.loader.grub.enable = false;
|
||||
|
|
|
@ -8,6 +8,20 @@ with lib;
|
|||
{
|
||||
options = {
|
||||
|
||||
netboot.squashfsCompression = mkOption {
|
||||
default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% "
|
||||
+ lib.optionalString isx86 "-Xbcj x86"
|
||||
# Untested but should also reduce size for these platforms
|
||||
+ lib.optionalString isAarch "-Xbcj arm"
|
||||
+ lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc"
|
||||
+ lib.optionalString (isSparc) "-Xbcj sparc";
|
||||
description = lib.mdDoc ''
|
||||
Compression settings to use for the squashfs nix store.
|
||||
'';
|
||||
example = "zstd -Xcompression-level 6";
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
netboot.storeContents = mkOption {
|
||||
example = literalExpression "[ pkgs.stdenv ]";
|
||||
description = lib.mdDoc ''
|
||||
|
@ -77,6 +91,7 @@ with lib;
|
|||
# Create the squashfs image that contains the Nix store.
|
||||
system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
|
||||
storeContents = config.netboot.storeContents;
|
||||
comp = config.netboot.squashfsCompression;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -668,7 +668,6 @@ EOF
|
|||
$bootLoaderConfig = <<EOF;
|
||||
# Use the GRUB 2 boot loader.
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
# boot.loader.grub.efiSupport = true;
|
||||
# boot.loader.grub.efiInstallAsRemovable = true;
|
||||
# boot.loader.efi.efiSysMountPoint = "/boot/efi";
|
||||
|
|
|
@ -49,10 +49,10 @@ let
|
|||
merge = lib.mergeOneOption;
|
||||
};
|
||||
|
||||
pkgsType = mkOptionType {
|
||||
name = "nixpkgs";
|
||||
pkgsType = types.pkgs // {
|
||||
# This type is only used by itself, so let's elaborate the description a bit
|
||||
# for the purpose of documentation.
|
||||
description = "An evaluation of Nixpkgs; the top level attribute set of packages";
|
||||
check = builtins.isAttrs;
|
||||
};
|
||||
|
||||
# Whether `pkgs` was constructed by this module - not if nixpkgs.pkgs or
|
||||
|
|
74
nixos/modules/misc/nixpkgs/read-only.nix
Normal file
74
nixos/modules/misc/nixpkgs/read-only.nix
Normal file
|
@ -0,0 +1,74 @@
|
|||
# A replacement for the traditional nixpkgs module, such that none of the modules
|
||||
# can add their own configuration. This ensures that the Nixpkgs configuration is
|
||||
# exactly as the user intends.
|
||||
# This may also be used as a performance optimization when evaluating multiple
|
||||
# configurations at once, with a shared `pkgs`.
|
||||
|
||||
# This is a separate module, because merging this logic into the nixpkgs module
|
||||
# is too burdensome, considering that it is already burdened with legacy.
|
||||
# Moving this logic into a module does not lose any composition benefits, because
|
||||
# its purpose is not something that composes anyway.
|
||||
|
||||
{ lib, config, ... }:
|
||||
|
||||
let
|
||||
cfg = config.nixpkgs;
|
||||
inherit (lib) mkOption types;
|
||||
|
||||
in
|
||||
{
|
||||
disabledModules = [
|
||||
../nixpkgs.nix
|
||||
];
|
||||
options = {
|
||||
nixpkgs = {
|
||||
pkgs = mkOption {
|
||||
type = lib.types.pkgs;
|
||||
description = lib.mdDoc ''The pkgs module argument.'';
|
||||
};
|
||||
config = mkOption {
|
||||
internal = true;
|
||||
type = types.unique { message = "nixpkgs.config is set to read-only"; } types.anything;
|
||||
description = lib.mdDoc ''
|
||||
The Nixpkgs `config` that `pkgs` was initialized with.
|
||||
'';
|
||||
};
|
||||
overlays = mkOption {
|
||||
internal = true;
|
||||
type = types.unique { message = "nixpkgs.overlays is set to read-only"; } types.anything;
|
||||
description = lib.mdDoc ''
|
||||
The Nixpkgs overlays that `pkgs` was initialized with.
|
||||
'';
|
||||
};
|
||||
hostPlatform = mkOption {
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
description = lib.mdDoc ''
|
||||
The platform of the machine that is running the NixOS configuration.
|
||||
'';
|
||||
};
|
||||
buildPlatform = mkOption {
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
description = lib.mdDoc ''
|
||||
The platform of the machine that built the NixOS configuration.
|
||||
'';
|
||||
};
|
||||
# NOTE: do not add the legacy options such as localSystem here. Let's keep
|
||||
# this module simple and let module authors upgrade their code instead.
|
||||
};
|
||||
};
|
||||
config = {
|
||||
_module.args.pkgs =
|
||||
# find mistaken definitions
|
||||
builtins.seq cfg.config
|
||||
builtins.seq cfg.overlays
|
||||
builtins.seq cfg.hostPlatform
|
||||
builtins.seq cfg.buildPlatform
|
||||
cfg.pkgs;
|
||||
nixpkgs.config = cfg.pkgs.config;
|
||||
nixpkgs.overlays = cfg.pkgs.overlays;
|
||||
nixpkgs.hostPlatform = cfg.pkgs.stdenv.hostPlatform;
|
||||
nixpkgs.buildPlatform = cfg.pkgs.stdenv.buildPlatform;
|
||||
};
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
# [nixpkgs]$ nix-build -A nixosTests.nixpkgs --show-trace
|
||||
|
||||
{ evalMinimalConfig, pkgs, lib, stdenv }:
|
||||
let
|
||||
eval = mod: evalMinimalConfig {
|
||||
|
@ -27,6 +29,47 @@ let
|
|||
let
|
||||
uncheckedEval = lib.evalModules { modules = [ ../nixpkgs.nix module ]; };
|
||||
in map (ass: ass.message) (lib.filter (ass: !ass.assertion) uncheckedEval.config.assertions);
|
||||
|
||||
readOnlyUndefined = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
};
|
||||
|
||||
readOnlyBad = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = { };
|
||||
};
|
||||
|
||||
readOnly = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = pkgs;
|
||||
};
|
||||
|
||||
readOnlyBadConfig = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = pkgs;
|
||||
nixpkgs.config.allowUnfree = true; # do in pkgs instead!
|
||||
};
|
||||
|
||||
readOnlyBadOverlays = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = pkgs;
|
||||
nixpkgs.overlays = [ (_: _: {}) ]; # do in pkgs instead!
|
||||
};
|
||||
|
||||
readOnlyBadHostPlatform = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = pkgs;
|
||||
nixpkgs.hostPlatform = "foo-linux"; # do in pkgs instead!
|
||||
};
|
||||
|
||||
readOnlyBadBuildPlatform = evalMinimalConfig {
|
||||
imports = [ ./read-only.nix ];
|
||||
nixpkgs.pkgs = pkgs;
|
||||
nixpkgs.buildPlatform = "foo-linux"; # do in pkgs instead!
|
||||
};
|
||||
|
||||
throws = x: ! (builtins.tryEval x).success;
|
||||
|
||||
in
|
||||
lib.recurseIntoAttrs {
|
||||
invokeNixpkgsSimple =
|
||||
|
@ -65,5 +108,21 @@ lib.recurseIntoAttrs {
|
|||
nixpkgs.pkgs = pkgs;
|
||||
} == [];
|
||||
|
||||
|
||||
# Tests for the read-only.nix module
|
||||
assert readOnly._module.args.pkgs.stdenv.hostPlatform.system == pkgs.stdenv.hostPlatform.system;
|
||||
assert throws readOnlyBad._module.args.pkgs.stdenv;
|
||||
assert throws readOnlyUndefined._module.args.pkgs.stdenv;
|
||||
assert throws readOnlyBadConfig._module.args.pkgs.stdenv;
|
||||
assert throws readOnlyBadOverlays._module.args.pkgs.stdenv;
|
||||
assert throws readOnlyBadHostPlatform._module.args.pkgs.stdenv;
|
||||
assert throws readOnlyBadBuildPlatform._module.args.pkgs.stdenv;
|
||||
# read-only.nix does not provide legacy options, for the sake of simplicity
|
||||
# If you're bothered by this, upgrade your configs to use the new *Platform
|
||||
# options.
|
||||
assert !readOnly.options.nixpkgs?system;
|
||||
assert !readOnly.options.nixpkgs?localSystem;
|
||||
assert !readOnly.options.nixpkgs?crossSystem;
|
||||
|
||||
pkgs.emptyFile;
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
./programs/cnping.nix
|
||||
./programs/command-not-found/command-not-found.nix
|
||||
./programs/criu.nix
|
||||
./programs/darling.nix
|
||||
./programs/dconf.nix
|
||||
./programs/digitalbitbox/default.nix
|
||||
./programs/dmrconfig.nix
|
||||
|
@ -234,6 +235,7 @@
|
|||
./programs/singularity.nix
|
||||
./programs/skim.nix
|
||||
./programs/slock.nix
|
||||
./programs/sniffnet.nix
|
||||
./programs/spacefm.nix
|
||||
./programs/ssh.nix
|
||||
./programs/starship.nix
|
||||
|
@ -247,6 +249,7 @@
|
|||
./programs/thunar.nix
|
||||
./programs/tmux.nix
|
||||
./programs/traceroute.nix
|
||||
./programs/trippy.nix
|
||||
./programs/tsm-client.nix
|
||||
./programs/turbovnc.nix
|
||||
./programs/udevil.nix
|
||||
|
@ -306,6 +309,7 @@
|
|||
./services/audio/alsa.nix
|
||||
./services/audio/botamusique.nix
|
||||
./services/audio/gmediarender.nix
|
||||
./services/audio/gonic.nix
|
||||
./services/audio/hqplayerd.nix
|
||||
./services/audio/icecast.nix
|
||||
./services/audio/jack.nix
|
||||
|
@ -371,6 +375,7 @@
|
|||
./services/continuous-integration/buildbot/master.nix
|
||||
./services/continuous-integration/buildbot/worker.nix
|
||||
./services/continuous-integration/buildkite-agents.nix
|
||||
./services/continuous-integration/gitea-actions-runner.nix
|
||||
./services/continuous-integration/github-runner.nix
|
||||
./services/continuous-integration/github-runners.nix
|
||||
./services/continuous-integration/gitlab-runner.nix
|
||||
|
@ -684,6 +689,7 @@
|
|||
./services/misc/ripple-data-api.nix
|
||||
./services/misc/rippled.nix
|
||||
./services/misc/rmfakecloud.nix
|
||||
./services/misc/rshim.nix
|
||||
./services/misc/safeeyes.nix
|
||||
./services/misc/sdrplay.nix
|
||||
./services/misc/serviio.nix
|
||||
|
@ -801,6 +807,7 @@
|
|||
./services/network-filesystems/yandex-disk.nix
|
||||
./services/networking/3proxy.nix
|
||||
./services/networking/adguardhome.nix
|
||||
./services/networking/alice-lg.nix
|
||||
./services/networking/amuled.nix
|
||||
./services/networking/antennas.nix
|
||||
./services/networking/aria2.nix
|
||||
|
@ -815,6 +822,7 @@
|
|||
./services/networking/bind.nix
|
||||
./services/networking/bird-lg.nix
|
||||
./services/networking/bird.nix
|
||||
./services/networking/birdwatcher.nix
|
||||
./services/networking/bitcoind.nix
|
||||
./services/networking/bitlbee.nix
|
||||
./services/networking/blockbook-frontend.nix
|
||||
|
@ -873,6 +881,7 @@
|
|||
./services/networking/gobgpd.nix
|
||||
./services/networking/gvpe.nix
|
||||
./services/networking/hans.nix
|
||||
./services/networking/harmonia.nix
|
||||
./services/networking/haproxy.nix
|
||||
./services/networking/headscale.nix
|
||||
./services/networking/hostapd.nix
|
||||
|
@ -1173,6 +1182,7 @@
|
|||
./services/web-apps/gerrit.nix
|
||||
./services/web-apps/gotify-server.nix
|
||||
./services/web-apps/grocy.nix
|
||||
./services/web-apps/pixelfed.nix
|
||||
./services/web-apps/healthchecks.nix
|
||||
./services/web-apps/hedgedoc.nix
|
||||
./services/web-apps/hledger-web.nix
|
||||
|
@ -1189,6 +1199,7 @@
|
|||
./services/web-apps/komga.nix
|
||||
./services/web-apps/lemmy.nix
|
||||
./services/web-apps/limesurvey.nix
|
||||
./services/web-apps/mainsail.nix
|
||||
./services/web-apps/mastodon.nix
|
||||
./services/web-apps/matomo.nix
|
||||
./services/web-apps/mattermost.nix
|
||||
|
@ -1203,6 +1214,7 @@
|
|||
./services/web-apps/nifi.nix
|
||||
./services/web-apps/node-red.nix
|
||||
./services/web-apps/onlyoffice.nix
|
||||
./services/web-apps/openvscode-server.nix
|
||||
./services/web-apps/openwebrx.nix
|
||||
./services/web-apps/outline.nix
|
||||
./services/web-apps/peering-manager.nix
|
||||
|
@ -1368,6 +1380,7 @@
|
|||
./tasks/filesystems/cifs.nix
|
||||
./tasks/filesystems/ecryptfs.nix
|
||||
./tasks/filesystems/envfs.nix
|
||||
./tasks/filesystems/erofs.nix
|
||||
./tasks/filesystems/exfat.nix
|
||||
./tasks/filesystems/ext.nix
|
||||
./tasks/filesystems/f2fs.nix
|
||||
|
|
21
nixos/modules/programs/darling.nix
Normal file
21
nixos/modules/programs/darling.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.darling;
|
||||
in {
|
||||
options = {
|
||||
programs.darling = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "Darling, a Darwin/macOS compatibility layer for Linux");
|
||||
package = lib.mkPackageOptionMD pkgs "darling" {};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
security.wrappers.darling = {
|
||||
source = lib.getExe cfg.package;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
setuid = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -26,7 +26,7 @@ in
|
|||
source ${pkgs.fzf}/share/fzf/key-bindings.zsh
|
||||
'');
|
||||
|
||||
programs.zsh.ohMyZsh.plugins = optional (cfg.keybindings || cfg.fuzzyCompletion) [ "fzf" ];
|
||||
programs.zsh.ohMyZsh.plugins = lib.mkIf (cfg.keybindings || cfg.fuzzyCompletion) [ "fzf" ];
|
||||
};
|
||||
meta.maintainers = with maintainers; [ laalsaas ];
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ in {
|
|||
Miriway, a Mir based Wayland compositor. You can manually launch Miriway by
|
||||
executing "exec miriway" on a TTY, or launch it from a display manager. Copy
|
||||
/etc/xdg/xdg-miriway/miriway-shell.config to ~/.config/miriway-shell.config
|
||||
to modify the default configuration. See <https://github.com/Miriway/Miriway>,
|
||||
to modify the system-wide configuration on a per-user basis. See <https://github.com/Miriway/Miriway>,
|
||||
and "miriway --help" for more information'');
|
||||
|
||||
config = lib.mkOption {
|
||||
|
@ -19,6 +19,15 @@ in {
|
|||
ctrl-alt=t:miriway-terminal # Default "terminal emulator finder"
|
||||
|
||||
shell-component=dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY
|
||||
|
||||
meta=Left:@dock-left
|
||||
meta=Right:@dock-right
|
||||
meta=Space:@toggle-maximized
|
||||
meta=Home:@workspace-begin
|
||||
meta=End:@workspace-end
|
||||
meta=Page_Up:@workspace-up
|
||||
meta=Page_Down:@workspace-down
|
||||
ctrl-alt=BackSpace:@exit
|
||||
'';
|
||||
example = ''
|
||||
idle-timeout=300
|
||||
|
@ -31,6 +40,15 @@ in {
|
|||
shell-component=wbg Pictures/wallpaper
|
||||
|
||||
shell-meta=a:synapse
|
||||
|
||||
meta=Left:@dock-left
|
||||
meta=Right:@dock-right
|
||||
meta=Space:@toggle-maximized
|
||||
meta=Home:@workspace-begin
|
||||
meta=End:@workspace-end
|
||||
meta=Page_Up:@workspace-up
|
||||
meta=Page_Down:@workspace-down
|
||||
ctrl-alt=BackSpace:@exit
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
Miriway's config. This will be installed system-wide.
|
||||
|
|
|
@ -138,7 +138,8 @@ in
|
|||
};
|
||||
|
||||
source = mkOption {
|
||||
type = types.path;
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
description = lib.mdDoc "Path of the source file.";
|
||||
};
|
||||
|
||||
|
@ -160,9 +161,11 @@ in
|
|||
environment.etc = listToAttrs (attrValues (mapAttrs
|
||||
(name: value: {
|
||||
name = "xdg/nvim/${name}";
|
||||
value = value // {
|
||||
target = "xdg/nvim/${value.target}";
|
||||
};
|
||||
value = removeAttrs
|
||||
(value // {
|
||||
target = "xdg/nvim/${value.target}";
|
||||
})
|
||||
(optionals (isNull value.source) [ "source" ]);
|
||||
})
|
||||
cfg.runtime));
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ let
|
|||
# This should be made configurable.
|
||||
#CHFN_RESTRICT frwh
|
||||
|
||||
# The default crypt() method, keep in sync with the PAM default
|
||||
ENCRYPT_METHOD YESCRYPT
|
||||
'';
|
||||
|
||||
mkSetuidRoot = source:
|
||||
|
|
24
nixos/modules/programs/sniffnet.nix
Normal file
24
nixos/modules/programs/sniffnet.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.sniffnet;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
programs.sniffnet = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "sniffnet");
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
security.wrappers.sniffnet = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
capabilities = "cap_net_raw,cap_net_admin=eip";
|
||||
source = "${pkgs.sniffnet}/bin/sniffnet";
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ figsoda ];
|
||||
}
|
24
nixos/modules/programs/trippy.nix
Normal file
24
nixos/modules/programs/trippy.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.programs.trippy;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
programs.trippy = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "trippy");
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
security.wrappers.trip = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
capabilities = "cap_net_raw+p";
|
||||
source = lib.getExe pkgs.trippy;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ figsoda ];
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
{ lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkAliasOptionModuleMD
|
||||
mkRemovedOptionModule;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
/*
|
||||
|
|
|
@ -323,7 +323,7 @@ let
|
|||
}
|
||||
fi
|
||||
'');
|
||||
} // optionalAttrs (data.listenHTTP != null && toInt (elemAt (splitString ":" data.listenHTTP) 1) < 1024) {
|
||||
} // optionalAttrs (data.listenHTTP != null && toInt (last (splitString ":" data.listenHTTP)) < 1024) {
|
||||
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
|
||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ in
|
|||
# some may even be completely useless.
|
||||
config.security.apparmor.includes = {
|
||||
# This one is included by <tunables/global>
|
||||
# which is usualy included before any profile.
|
||||
# which is usually included before any profile.
|
||||
"abstractions/tunables/alias" = ''
|
||||
alias /bin -> /run/current-system/sw/bin,
|
||||
alias /lib/modules -> /run/current-system/kernel/lib/modules,
|
||||
|
|
|
@ -446,6 +446,15 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
zfs = mkOption {
|
||||
default = config.security.pam.zfs.enable;
|
||||
defaultText = literalExpression "config.security.pam.zfs.enable";
|
||||
type = types.bool;
|
||||
description = lib.mdDoc ''
|
||||
Enable unlocking and mounting of encrypted ZFS home dataset at login.
|
||||
'';
|
||||
};
|
||||
|
||||
text = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
description = lib.mdDoc "Contents of the PAM service file.";
|
||||
|
@ -556,7 +565,8 @@ let
|
|||
|| cfg.googleAuthenticator.enable
|
||||
|| cfg.gnupg.enable
|
||||
|| cfg.failDelay.enable
|
||||
|| cfg.duoSecurity.enable))
|
||||
|| cfg.duoSecurity.enable
|
||||
|| cfg.zfs))
|
||||
(
|
||||
optionalString config.services.homed.enable ''
|
||||
auth optional ${config.systemd.package}/lib/security/pam_systemd_home.so
|
||||
|
@ -570,6 +580,9 @@ let
|
|||
optionalString config.security.pam.enableFscrypt ''
|
||||
auth optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so
|
||||
'' +
|
||||
optionalString cfg.zfs ''
|
||||
auth optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes}
|
||||
'' +
|
||||
optionalString cfg.pamMount ''
|
||||
auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive
|
||||
'' +
|
||||
|
@ -628,6 +641,9 @@ let
|
|||
optionalString config.security.pam.enableFscrypt ''
|
||||
password optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so
|
||||
'' +
|
||||
optionalString cfg.zfs ''
|
||||
password optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes}
|
||||
'' +
|
||||
optionalString cfg.pamMount ''
|
||||
password optional ${pkgs.pam_mount}/lib/security/pam_mount.so
|
||||
'' +
|
||||
|
@ -638,7 +654,7 @@ let
|
|||
password sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf
|
||||
'' +
|
||||
optionalString config.services.sssd.enable ''
|
||||
password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok
|
||||
password sufficient ${pkgs.sssd}/lib/security/pam_sss.so
|
||||
'' +
|
||||
optionalString config.security.pam.krb5.enable ''
|
||||
password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
|
||||
|
@ -685,6 +701,10 @@ let
|
|||
session [success=1 default=ignore] pam_succeed_if.so service = systemd-user
|
||||
session optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so
|
||||
'' +
|
||||
optionalString cfg.zfs ''
|
||||
session [success=1 default=ignore] pam_succeed_if.so service = systemd-user
|
||||
session optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} ${optionalString config.security.pam.zfs.noUnmount "nounmount"}
|
||||
'' +
|
||||
optionalString cfg.pamMount ''
|
||||
session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive
|
||||
'' +
|
||||
|
@ -1202,6 +1222,34 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
security.pam.zfs = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = lib.mdDoc ''
|
||||
Enable unlocking and mounting of encrypted ZFS home dataset at login.
|
||||
'';
|
||||
};
|
||||
|
||||
homes = mkOption {
|
||||
example = "rpool/home";
|
||||
default = "rpool/home";
|
||||
type = types.str;
|
||||
description = lib.mdDoc ''
|
||||
Prefix of home datasets. This value will be concatenated with
|
||||
`"/" + <username>` in order to determine the home dataset to unlock.
|
||||
'';
|
||||
};
|
||||
|
||||
noUnmount = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = lib.mdDoc ''
|
||||
Do not unmount home dataset on logout.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.enableEcryptfs = mkEnableOption (lib.mdDoc "eCryptfs PAM module (mounting ecryptfs home directory on login)");
|
||||
security.pam.enableFscrypt = mkEnableOption (lib.mdDoc ''
|
||||
Enables fscrypt to automatically unlock directories with the user's login password.
|
||||
|
@ -1238,6 +1286,12 @@ in
|
|||
Only one of users.motd and users.motdFile can be set.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = config.security.pam.zfs.enable -> (config.boot.zfs.enabled || config.boot.zfs.enableUnstable);
|
||||
message = ''
|
||||
`security.pam.zfs.enable` requires enabling ZFS (`boot.zfs.enabled` or `boot.zfs.enableUnstable`).
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages =
|
||||
|
@ -1378,7 +1432,10 @@ in
|
|||
mr ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so,
|
||||
'' +
|
||||
optionalString config.virtualisation.lxc.lxcfs.enable ''
|
||||
mr ${pkgs.lxc}/lib/security/pam_cgfs.so
|
||||
mr ${pkgs.lxc}/lib/security/pam_cgfs.so,
|
||||
'' +
|
||||
optionalString (isEnabled (cfg: cfg.zfs)) ''
|
||||
mr ${config.boot.zfs.package}/lib/security/pam_zfs_key.so,
|
||||
'' +
|
||||
optionalString config.services.homed.enable ''
|
||||
mr ${config.systemd.package}/lib/security/pam_systemd_home.so
|
||||
|
|
|
@ -3,7 +3,7 @@ let
|
|||
cfg = config.security.tpm2;
|
||||
|
||||
# This snippet is taken from tpm2-tss/dist/tpm-udev.rules, but modified to allow custom user/groups
|
||||
# The idea is that the tssUser is allowed to acess the TPM and kernel TPM resource manager, while
|
||||
# The idea is that the tssUser is allowed to access the TPM and kernel TPM resource manager, while
|
||||
# the tssGroup is only allowed to access the kernel resource manager
|
||||
# Therefore, if either of the two are null, the respective part isn't generated
|
||||
udevRules = tssUser: tssGroup: ''
|
||||
|
|
|
@ -283,7 +283,7 @@ in
|
|||
'';
|
||||
|
||||
###### wrappers consistency checks
|
||||
system.extraDependencies = lib.singleton (pkgs.runCommandLocal
|
||||
system.checks = lib.singleton (pkgs.runCommandLocal
|
||||
"ensure-all-wrappers-paths-exist" { }
|
||||
''
|
||||
# make sure we produce output
|
||||
|
|
89
nixos/modules/services/audio/gonic.nix
Normal file
89
nixos/modules/services/audio/gonic.nix
Normal file
|
@ -0,0 +1,89 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.gonic;
|
||||
settingsFormat = pkgs.formats.keyValue {
|
||||
mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
|
||||
listsAsDuplicateKeys = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.gonic = {
|
||||
|
||||
enable = mkEnableOption (lib.mdDoc "Gonic music server");
|
||||
|
||||
settings = mkOption rec {
|
||||
type = settingsFormat.type;
|
||||
apply = recursiveUpdate default;
|
||||
default = {
|
||||
listen-addr = "127.0.0.1:4747";
|
||||
cache-path = "/var/cache/gonic";
|
||||
tls-cert = null;
|
||||
tls-key = null;
|
||||
};
|
||||
example = {
|
||||
music-path = [ "/mnt/music" ];
|
||||
podcast-path = "/mnt/podcasts";
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
Configuration for Gonic, see <https://github.com/sentriz/gonic#configuration-options> for supported values.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.gonic = {
|
||||
description = "Gonic Media Server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
let
|
||||
# these values are null by default but should not appear in the final config
|
||||
filteredSettings = filterAttrs (n: v: !((n == "tls-cert" || n == "tls-key") && v == null)) cfg.settings;
|
||||
in
|
||||
"${pkgs.gonic}/bin/gonic -config-path ${settingsFormat.generate "gonic" filteredSettings}";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "gonic";
|
||||
CacheDirectory = "gonic";
|
||||
WorkingDirectory = "/var/lib/gonic";
|
||||
RuntimeDirectory = "gonic";
|
||||
RootDirectory = "/run/gonic";
|
||||
ReadWritePaths = "";
|
||||
BindReadOnlyPaths = [
|
||||
# gonic can access scrobbling services
|
||||
"-/etc/ssl/certs/ca-certificates.crt"
|
||||
builtins.storeDir
|
||||
cfg.settings.podcast-path
|
||||
] ++ cfg.settings.music-path
|
||||
++ lib.optional (cfg.settings.tls-cert != null) cfg.settings.tls-cert
|
||||
++ lib.optional (cfg.settings.tls-key != null) cfg.settings.tls-key;
|
||||
CapabilityBoundingSet = "";
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [ "@system-service" "~@privileged" ];
|
||||
RestrictRealtime = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
UMask = "0066";
|
||||
ProtectHostname = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = [ maintainers.autrimpo ];
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
let
|
||||
|
||||
inherit (lib) concatMapStringsSep concatStringsSep isInt isList literalExpression;
|
||||
inherit (lib) mapAttrs mapAttrsToList mkDefault mkEnableOption mkIf mkOption optional types;
|
||||
inherit (lib) mapAttrs mapAttrsToList mkDefault mkEnableOption mkIf mkOption mkRenamedOptionModule optional types;
|
||||
|
||||
cfg = config.services.automysqlbackup;
|
||||
pkg = pkgs.automysqlbackup;
|
||||
|
@ -26,6 +26,10 @@ let
|
|||
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "automysqlbackup" "config" ] [ "services" "automysqlbackup" "settings" ])
|
||||
];
|
||||
|
||||
# interface
|
||||
options = {
|
||||
services.automysqlbackup = {
|
||||
|
@ -40,7 +44,7 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
|
||||
default = {};
|
||||
description = lib.mdDoc ''
|
||||
|
@ -112,7 +116,18 @@ in
|
|||
|
||||
services.mysql.ensureUsers = optional (config.services.mysql.enable && cfg.config.mysql_dump_host == "localhost") {
|
||||
name = user;
|
||||
ensurePermissions = { "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT"; };
|
||||
ensurePermissions = {
|
||||
"*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT";
|
||||
|
||||
# https://forums.mysql.com/read.php?10,668311,668315#msg-668315
|
||||
"function sys.extract_table_from_file_name" = "execute";
|
||||
"function sys.format_path" = "execute";
|
||||
"function sys.format_statement" = "execute";
|
||||
"function sys.extract_schema_from_file_name" = "execute";
|
||||
"function sys.ps_thread_account" = "execute";
|
||||
"function sys.format_time" = "execute";
|
||||
"function sys.format_bytes" = "execute";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -109,7 +109,7 @@ let
|
|||
};
|
||||
environment = {
|
||||
BORG_REPO = cfg.repo;
|
||||
inherit (cfg) extraArgs extraInitArgs extraCreateArgs extraPruneArgs;
|
||||
inherit (cfg) extraArgs extraInitArgs extraCreateArgs extraPruneArgs extraCompactArgs;
|
||||
} // (mkPassEnv cfg) // cfg.environment;
|
||||
};
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ in
|
|||
type = types.attrsOf unitOption;
|
||||
default = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
When to run the backup. See {manpage}`systemd.timer(5)` for details.
|
||||
|
@ -152,6 +153,7 @@ in
|
|||
example = {
|
||||
OnCalendar = "00:05";
|
||||
RandomizedDelaySec = "5h";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
{ config
|
||||
, lib
|
||||
, pkgs
|
||||
, utils
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
any
|
||||
attrValues
|
||||
concatStringsSep
|
||||
escapeShellArg
|
||||
hasInfix
|
||||
hasSuffix
|
||||
optionalAttrs
|
||||
optionals
|
||||
literalExpression
|
||||
mapAttrs'
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkPackageOptionMD
|
||||
mkIf
|
||||
nameValuePair
|
||||
types
|
||||
;
|
||||
|
||||
inherit (utils)
|
||||
escapeSystemdPath
|
||||
;
|
||||
|
||||
cfg = config.services.gitea-actions-runner;
|
||||
|
||||
# Check whether any runner instance label requires a container runtime
|
||||
# Empty label strings result in the upstream defined defaultLabels, which require docker
|
||||
# https://gitea.com/gitea/act_runner/src/tag/v0.1.5/internal/app/cmd/register.go#L93-L98
|
||||
hasDockerScheme = instance:
|
||||
instance.labels == [] || any (label: hasInfix ":docker:" label) instance.labels;
|
||||
wantsContainerRuntime = any hasDockerScheme (attrValues cfg.instances);
|
||||
|
||||
hasHostScheme = instance: any (label: hasSuffix ":host" label) instance.labels;
|
||||
|
||||
# provide shorthands for whether container runtimes are enabled
|
||||
hasDocker = config.virtualisation.docker.enable;
|
||||
hasPodman = config.virtualisation.podman.enable;
|
||||
|
||||
tokenXorTokenFile = instance:
|
||||
(instance.token == null && instance.tokenFile != null) ||
|
||||
(instance.token != null && instance.tokenFile == null);
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
hexa
|
||||
];
|
||||
|
||||
options.services.gitea-actions-runner = with types; {
|
||||
package = mkPackageOptionMD pkgs "gitea-actions-runner" { };
|
||||
|
||||
instances = mkOption {
|
||||
default = {};
|
||||
description = lib.mdDoc ''
|
||||
Gitea Actions Runner instances.
|
||||
'';
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
enable = mkEnableOption (lib.mdDoc "Gitea Actions Runner instance");
|
||||
|
||||
name = mkOption {
|
||||
type = str;
|
||||
example = literalExpression "config.networking.hostName";
|
||||
description = lib.mdDoc ''
|
||||
The name identifying the runner instance towards the Gitea/Forgejo instance.
|
||||
'';
|
||||
};
|
||||
|
||||
url = mkOption {
|
||||
type = str;
|
||||
example = "https://forge.example.com";
|
||||
description = lib.mdDoc ''
|
||||
Base URL of your Gitea/Forgejo instance.
|
||||
'';
|
||||
};
|
||||
|
||||
token = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Plain token to register at the configured Gitea/Forgejo instance.
|
||||
'';
|
||||
};
|
||||
|
||||
tokenFile = mkOption {
|
||||
type = nullOr (either str path);
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Path to an environment file, containing the `TOKEN` environment
|
||||
variable, that holds a token to register at the configured
|
||||
Gitea/Forgejo instance.
|
||||
'';
|
||||
};
|
||||
|
||||
labels = mkOption {
|
||||
type = listOf str;
|
||||
example = literalExpression ''
|
||||
[
|
||||
# provide a debian base with nodejs for actions
|
||||
"debian-latest:docker://node:18-bullseye"
|
||||
# fake the ubuntu name, because node provides no ubuntu builds
|
||||
"ubuntu-latest:docker://node:18-bullseye"
|
||||
# provide native execution on the host
|
||||
#"native:host"
|
||||
]
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
Labels used to map jobs to their runtime environment. Changing these
|
||||
labels currently requires a new registration token.
|
||||
|
||||
Many common actions require bash, git and nodejs, as well as a filesystem
|
||||
that follows the filesystem hierarchy standard.
|
||||
'';
|
||||
};
|
||||
|
||||
hostPackages = mkOption {
|
||||
type = listOf package;
|
||||
default = with pkgs; [
|
||||
bash
|
||||
coreutils
|
||||
curl
|
||||
gawk
|
||||
gitMinimal
|
||||
gnused
|
||||
nodejs
|
||||
wget
|
||||
];
|
||||
defaultText = literalExpression ''
|
||||
with pkgs; [
|
||||
bash
|
||||
coreutils
|
||||
curl
|
||||
gawk
|
||||
gitMinimal
|
||||
gnused
|
||||
nodejs
|
||||
wget
|
||||
]
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
List of packages, that are available to actions, when the runner is configured
|
||||
with a host execution label.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.instances != {}) {
|
||||
assertions = [ {
|
||||
assertion = any tokenXorTokenFile (attrValues cfg.instances);
|
||||
message = "Instances of gitea-actions-runner can have `token` or `tokenFile`, not both.";
|
||||
} {
|
||||
assertion = wantsContainerRuntime -> hasDocker || hasPodman;
|
||||
message = "Label configuration on gitea-actions-runner instance requires either docker or podman.";
|
||||
} ];
|
||||
|
||||
systemd.services = let
|
||||
mkRunnerService = name: instance: let
|
||||
wantsContainerRuntime = hasDockerScheme instance;
|
||||
wantsHost = hasHostScheme instance;
|
||||
wantsDocker = wantsContainerRuntime && config.virtualisation.docker.enable;
|
||||
wantsPodman = wantsContainerRuntime && config.virtualisation.podman.enable;
|
||||
in
|
||||
nameValuePair "gitea-runner-${escapeSystemdPath name}" {
|
||||
inherit (instance) enable;
|
||||
description = "Gitea Actions Runner";
|
||||
after = [
|
||||
"network-online.target"
|
||||
] ++ optionals (wantsDocker) [
|
||||
"docker.service"
|
||||
] ++ optionals (wantsPodman) [
|
||||
"podman.service"
|
||||
];
|
||||
wantedBy = [
|
||||
"multi-user.target"
|
||||
];
|
||||
environment = optionalAttrs (instance.token != null) {
|
||||
TOKEN = "${instance.token}";
|
||||
} // optionalAttrs (wantsPodman) {
|
||||
DOCKER_HOST = "unix:///run/podman/podman.sock";
|
||||
};
|
||||
path = with pkgs; [
|
||||
coreutils
|
||||
] ++ lib.optionals wantsHost instance.hostPackages;
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
User = "gitea-runner";
|
||||
StateDirectory = "gitea-runner";
|
||||
WorkingDirectory = "-/var/lib/gitea-runner/${name}";
|
||||
ExecStartPre = pkgs.writeShellScript "gitea-register-runner-${name}" ''
|
||||
export INSTANCE_DIR="$STATE_DIRECTORY/${name}"
|
||||
mkdir -vp "$INSTANCE_DIR"
|
||||
cd "$INSTANCE_DIR"
|
||||
|
||||
# force reregistration on changed labels
|
||||
export LABELS_FILE="$INSTANCE_DIR/.labels"
|
||||
export LABELS_WANTED="$(echo ${escapeShellArg (concatStringsSep "\n" instance.labels)} | sort)"
|
||||
export LABELS_CURRENT="$(cat $LABELS_FILE 2>/dev/null || echo 0)"
|
||||
|
||||
if [ ! -e "$INSTANCE_DIR/.runner" ] || [ "$LABELS_WANTED" != "$LABELS_CURRENT" ]; then
|
||||
# remove existing registration file, so that changing the labels forces a re-registation
|
||||
rm -v "$INSTANCE_DIR/.runner" || true
|
||||
|
||||
# perform the registration
|
||||
${cfg.package}/bin/act_runner register --no-interactive \
|
||||
--instance ${escapeShellArg instance.url} \
|
||||
--token "$TOKEN" \
|
||||
--name ${escapeShellArg instance.name} \
|
||||
--labels ${escapeShellArg (concatStringsSep "," instance.labels)}
|
||||
|
||||
# and write back the configured labels
|
||||
echo "$LABELS_WANTED" > "$LABELS_FILE"
|
||||
fi
|
||||
|
||||
'';
|
||||
ExecStart = "${cfg.package}/bin/act_runner daemon";
|
||||
SupplementaryGroups = optionals (wantsDocker) [
|
||||
"docker"
|
||||
] ++ optionals (wantsPodman) [
|
||||
"podman"
|
||||
];
|
||||
} // optionalAttrs (instance.tokenFile != null) {
|
||||
EnvironmentFile = instance.tokenFile;
|
||||
};
|
||||
};
|
||||
in mapAttrs' mkRunnerService cfg.instances;
|
||||
};
|
||||
}
|
|
@ -489,7 +489,7 @@ in
|
|||
"/share/postgresql"
|
||||
];
|
||||
|
||||
system.extraDependencies = lib.optional (cfg.checkConfig && pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) configFileCheck;
|
||||
system.checks = lib.optional (cfg.checkConfig && pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) configFileCheck;
|
||||
|
||||
systemd.services.postgresql =
|
||||
{ description = "PostgreSQL Server";
|
||||
|
|
|
@ -254,7 +254,7 @@ in
|
|||
preStart = ''
|
||||
# Blindly copy the whole project here.
|
||||
chmod -R +w .
|
||||
rm -rf ./public/assets/*
|
||||
rm -rf ./public/assets/
|
||||
rm -rf ./tmp/*
|
||||
rm -rf ./log/*
|
||||
cp -r --no-preserve=owner ${cfg.package}/* .
|
||||
|
|
|
@ -245,7 +245,7 @@ in
|
|||
|
||||
rm -f www
|
||||
${optionalString cfg.web-ui.enable ''
|
||||
ln -s ${cfg.web-ui.package}/lib/dist www
|
||||
ln -s ${cfg.web-ui.package}/ www
|
||||
''}
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -76,7 +76,9 @@ in
|
|||
ExecStart = "${pkgs.keyd}/bin/keyd";
|
||||
Restart = "always";
|
||||
|
||||
DynamicUser = true;
|
||||
# TODO investigate why it doesn't work propeprly with DynamicUser
|
||||
# See issue: https://github.com/NixOS/nixpkgs/issues/226346
|
||||
# DynamicUser = true;
|
||||
SupplementaryGroups = [
|
||||
config.users.groups.input.name
|
||||
config.users.groups.uinput.name
|
||||
|
@ -96,6 +98,7 @@ in
|
|||
ProtectHostname = true;
|
||||
PrivateUsers = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
RestrictNamespaces = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
|
@ -104,7 +107,18 @@ in
|
|||
MemoryDenyWriteExecute = true;
|
||||
RestrictRealtime = true;
|
||||
LockPersonality = true;
|
||||
ProtectProc = "noaccess";
|
||||
ProtectProc = "invisible";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
RestrictAddressFamilies = [ "AF_UNIX" ];
|
||||
RestrictSUIDSGID = true;
|
||||
IPAddressDeny = [ "any" ];
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProcSubset = "pid";
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -37,8 +37,8 @@ in
|
|||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.graylog;
|
||||
defaultText = literalExpression "pkgs.graylog";
|
||||
default = if versionOlder config.system.stateVersion "23.05" then pkgs.graylog-3_3 else pkgs.graylog-5_0;
|
||||
defaultText = literalExpression (if versionOlder config.system.stateVersion "23.05" then "pkgs.graylog-3_3" else "pkgs.graylog-5_0");
|
||||
description = lib.mdDoc "Graylog package to use.";
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ in
|
|||
options.services.vector = {
|
||||
enable = mkEnableOption (lib.mdDoc "Vector");
|
||||
|
||||
package = mkPackageOptionMD pkgs "vector" { };
|
||||
|
||||
journaldAccess = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -47,7 +49,7 @@ in
|
|||
'';
|
||||
in
|
||||
{
|
||||
ExecStart = "${pkgs.vector}/bin/vector --config ${validateConfig conf}";
|
||||
ExecStart = "${getExe cfg.package} --config ${validateConfig conf}";
|
||||
DynamicUser = true;
|
||||
Restart = "no";
|
||||
StateDirectory = "vector";
|
||||
|
|
|
@ -206,7 +206,7 @@ in {
|
|||
Server configuration, see
|
||||
[https://maddy.email](https://maddy.email) for
|
||||
more information. The default configuration of this module will setup
|
||||
minimal maddy instance for mail transfer without TLS encryption.
|
||||
minimal Maddy instance for mail transfer without TLS encryption.
|
||||
|
||||
::: {.note}
|
||||
This should not be used in a production environment.
|
||||
|
@ -216,13 +216,24 @@ in {
|
|||
|
||||
tls = {
|
||||
loader = mkOption {
|
||||
type = with types; nullOr (enum [ "file" "off" ]);
|
||||
type = with types; nullOr (enum [ "off" "file" "acme" ]);
|
||||
default = "off";
|
||||
description = lib.mdDoc ''
|
||||
TLS certificates are obtained by modules called "certificate
|
||||
loaders". Currently only the file loader is supported which reads
|
||||
certificates from files specifying the options `keyPaths` and
|
||||
`certPaths`.
|
||||
loaders".
|
||||
|
||||
The `file` loader module reads certificates from files specified by
|
||||
the `certificates` option.
|
||||
|
||||
Alternatively the `acme` module can be used to automatically obtain
|
||||
certificates using the ACME protocol.
|
||||
|
||||
Module configuration is done via the `tls.extraConfig` option.
|
||||
|
||||
Secrets such as API keys or passwords should not be supplied in
|
||||
plaintext. Instead the `secrets` option can be used to read secrets
|
||||
at runtime as environment variables. Secrets can be referenced with
|
||||
`{env:VAR}`.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -261,11 +272,13 @@ in {
|
|||
extraConfig = mkOption {
|
||||
type = with types; nullOr lines;
|
||||
description = lib.mdDoc ''
|
||||
Arguments for the specific certificate loader. Note that Maddy uses
|
||||
secure defaults for the TLS configuration so there is no need to
|
||||
change anything in most cases.
|
||||
See [upstream manual](https://maddy.email/reference/tls/) for
|
||||
available options.
|
||||
Arguments for the specified certificate loader.
|
||||
|
||||
In case the `tls` loader is set, the defaults are considered secure
|
||||
and there is no need to change anything in most cases.
|
||||
For available options see [upstream manual](https://maddy.email/reference/tls/).
|
||||
|
||||
For ACME configuration, see [following page](https://maddy.email/reference/tls-acme).
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
@ -321,20 +334,41 @@ in {
|
|||
});
|
||||
};
|
||||
|
||||
secrets = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = lib.mdDoc ''
|
||||
A file containing the various secrets. Should be in the format
|
||||
expected by systemd's `EnvironmentFile` directory. Secrets can be
|
||||
referenced in the format `{env:VAR}`.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
assertions = [{
|
||||
assertion = cfg.tls.loader == "file" -> cfg.tls.certificates != [];
|
||||
message = ''
|
||||
If maddy is configured to use TLS, tls.certificates with attribute sets
|
||||
of certPath and keyPath must be provided.
|
||||
Read more about obtaining TLS certificates here:
|
||||
https://maddy.email/tutorials/setting-up/#tls-certificates
|
||||
'';
|
||||
}];
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.tls.loader == "file" -> cfg.tls.certificates != [];
|
||||
message = ''
|
||||
If Maddy is configured to use TLS, tls.certificates with attribute sets
|
||||
of certPath and keyPath must be provided.
|
||||
Read more about obtaining TLS certificates here:
|
||||
https://maddy.email/tutorials/setting-up/#tls-certificates
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = cfg.tls.loader == "acme" -> cfg.tls.extraConfig != "";
|
||||
message = ''
|
||||
If Maddy is configured to obtain TLS certificates using the ACME
|
||||
loader, extra configuration options must be supplied via
|
||||
tls.extraConfig option.
|
||||
See upstream documentation for more details:
|
||||
https://maddy.email/reference/tls-acme
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
systemd = {
|
||||
|
||||
|
@ -345,6 +379,7 @@ in {
|
|||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = [ "maddy" ];
|
||||
EnvironmentFile = lib.mkIf (cfg.secrets != null) "${cfg.secrets}";
|
||||
};
|
||||
restartTriggers = [ config.environment.etc."maddy/maddy.conf".source ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
@ -391,6 +426,12 @@ in {
|
|||
) cfg.tls.certificates)} ${optionalString (cfg.tls.extraConfig != "") ''
|
||||
{ ${cfg.tls.extraConfig} }
|
||||
''}
|
||||
'' else if (cfg.tls.loader == "acme") then ''
|
||||
tls {
|
||||
loader acme {
|
||||
${cfg.tls.extraConfig}
|
||||
}
|
||||
}
|
||||
'' else if (cfg.tls.loader == "off") then ''
|
||||
tls off
|
||||
'' else ""}
|
||||
|
|
|
@ -30,7 +30,7 @@ let
|
|||
|
||||
# these config files will be merged one after the other to build the final config
|
||||
configFiles = [
|
||||
"${pkgs.mjolnir}/share/mjolnir/config/default.yaml"
|
||||
"${pkgs.mjolnir}/libexec/mjolnir/deps/mjolnir/config/default.yaml"
|
||||
moduleConfigFile
|
||||
];
|
||||
|
||||
|
@ -200,7 +200,7 @@ in
|
|||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = ''${pkgs.mjolnir}/bin/mjolnir'';
|
||||
ExecStart = ''${pkgs.mjolnir}/bin/mjolnir --mjolnir-config ./config/default.yaml'';
|
||||
ExecStartPre = [ generateConfig ];
|
||||
WorkingDirectory = cfg.dataPath;
|
||||
StateDirectory = "mjolnir";
|
||||
|
|
|
@ -167,10 +167,11 @@ in {
|
|||
ETCD_LISTEN_CLIENT_URLS = concatStringsSep "," cfg.listenClientUrls;
|
||||
ETCD_LISTEN_PEER_URLS = concatStringsSep "," cfg.listenPeerUrls;
|
||||
ETCD_INITIAL_ADVERTISE_PEER_URLS = concatStringsSep "," cfg.initialAdvertisePeerUrls;
|
||||
ETCD_PEER_CLIENT_CERT_AUTH = toString cfg.peerClientCertAuth;
|
||||
ETCD_PEER_TRUSTED_CA_FILE = cfg.peerTrustedCaFile;
|
||||
ETCD_PEER_CERT_FILE = cfg.peerCertFile;
|
||||
ETCD_PEER_KEY_FILE = cfg.peerKeyFile;
|
||||
ETCD_CLIENT_CERT_AUTH = toString cfg.peerClientCertAuth;
|
||||
ETCD_CLIENT_CERT_AUTH = toString cfg.clientCertAuth;
|
||||
ETCD_TRUSTED_CA_FILE = cfg.trustedCaFile;
|
||||
ETCD_CERT_FILE = cfg.certFile;
|
||||
ETCD_KEY_FILE = cfg.keyFile;
|
||||
|
|
|
@ -23,6 +23,16 @@ in
|
|||
description = lib.mdDoc "The Klipper package.";
|
||||
};
|
||||
|
||||
logFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/var/lib/klipper/klipper.log";
|
||||
description = lib.mdDoc ''
|
||||
Path of the file Klipper should log to.
|
||||
If `null`, it logs to stdout, which is not recommended by upstream.
|
||||
'';
|
||||
};
|
||||
|
||||
inputTTY = mkOption {
|
||||
type = types.path;
|
||||
default = "/run/klipper/tty";
|
||||
|
@ -151,7 +161,9 @@ in
|
|||
systemd.services.klipper =
|
||||
let
|
||||
klippyArgs = "--input-tty=${cfg.inputTTY}"
|
||||
+ optionalString (cfg.apiSocket != null) " --api-server=${cfg.apiSocket}";
|
||||
+ optionalString (cfg.apiSocket != null) " --api-server=${cfg.apiSocket}"
|
||||
+ optionalString (cfg.logFile != null) " --logfile=${cfg.logFile}"
|
||||
;
|
||||
printerConfigPath =
|
||||
if cfg.mutableConfig
|
||||
then cfg.mutableConfigFolder + "/printer.cfg"
|
||||
|
@ -177,7 +189,7 @@ in
|
|||
'';
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/lib/klipper/klippy.py ${klippyArgs} ${printerConfigPath}";
|
||||
ExecStart = "${cfg.package}/bin/klippy ${klippyArgs} ${printerConfigPath}";
|
||||
RuntimeDirectory = "klipper";
|
||||
StateDirectory = "klipper";
|
||||
SupplementaryGroups = [ "dialout" ];
|
||||
|
|
|
@ -72,7 +72,7 @@ in {
|
|||
example = {
|
||||
authorization = {
|
||||
trusted_clients = [ "10.0.0.0/24" ];
|
||||
cors_domains = [ "https://app.fluidd.xyz" ];
|
||||
cors_domains = [ "https://app.fluidd.xyz" "https://my.mainsail.xyz" ];
|
||||
};
|
||||
};
|
||||
description = lib.mdDoc ''
|
||||
|
|
99
nixos/modules/services/misc/rshim.nix
Normal file
99
nixos/modules/services/misc/rshim.nix
Normal file
|
@ -0,0 +1,99 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.rshim;
|
||||
|
||||
rshimCommand = [ "${cfg.package}/bin/rshim" ]
|
||||
++ lib.optionals (cfg.backend != null) [ "--backend ${cfg.backend}" ]
|
||||
++ lib.optionals (cfg.device != null) [ "--device ${cfg.device}" ]
|
||||
++ lib.optionals (cfg.index != null) [ "--index ${builtins.toString cfg.index}" ]
|
||||
++ [ "--log-level ${builtins.toString cfg.log-level}" ]
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.rshim = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "User-space rshim driver for the BlueField SoC");
|
||||
|
||||
package = lib.mkPackageOptionMD pkgs "rshim-user-space" { };
|
||||
|
||||
backend = lib.mkOption {
|
||||
type = with lib.types; nullOr (enum [ "usb" "pcie" "pcie_lf" ]);
|
||||
description = lib.mdDoc ''
|
||||
Specify the backend to attach. If not specified, the driver will scan
|
||||
all rshim backends unless the `device` option is given with a device
|
||||
name specified.
|
||||
'';
|
||||
default = null;
|
||||
example = "pcie";
|
||||
};
|
||||
|
||||
device = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
description = lib.mdDoc ''
|
||||
Specify the device name to attach. The backend driver can be deduced
|
||||
from the device name, thus the `backend` option is not needed.
|
||||
'';
|
||||
default = null;
|
||||
example = "pcie-04:00.2";
|
||||
};
|
||||
|
||||
index = lib.mkOption {
|
||||
type = with lib.types; nullOr int;
|
||||
description = lib.mdDoc ''
|
||||
Specify the index to create device path `/dev/rshim<index>`. It's also
|
||||
used to create network interface name `tmfifo_net<index>`. This option
|
||||
is needed when multiple rshim instances are running.
|
||||
'';
|
||||
default = null;
|
||||
example = 1;
|
||||
};
|
||||
|
||||
log-level = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = lib.mdDoc ''
|
||||
Specify the log level (0:none, 1:error, 2:warning, 3:notice, 4:debug).
|
||||
'';
|
||||
default = 2;
|
||||
example = 4;
|
||||
};
|
||||
|
||||
config = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ int str ]);
|
||||
description = lib.mdDoc ''
|
||||
Structural setting for the rshim configuration file
|
||||
(`/etc/rshim.conf`). It can be used to specify the static mapping
|
||||
between rshim devices and rshim names. It can also be used to ignore
|
||||
some rshim devices.
|
||||
'';
|
||||
default = { };
|
||||
example = {
|
||||
DISPLAY_LEVEL = 0;
|
||||
rshim0 = "usb-2-1.7";
|
||||
none = "usb-1-1.4";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.etc = lib.mkIf (cfg.config != { }) {
|
||||
"rshim.conf".text = lib.generators.toKeyValue
|
||||
{ mkKeyValue = lib.generators.mkKeyValueDefault { } " "; }
|
||||
cfg.config;
|
||||
};
|
||||
|
||||
systemd.services.rshim = {
|
||||
after = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
Type = "forking";
|
||||
ExecStart = [
|
||||
(lib.concatStringsSep " \\\n" rshimCommand)
|
||||
];
|
||||
KillMode = "control-group";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ nikstur ];
|
||||
}
|
|
@ -4,6 +4,81 @@ with lib;
|
|||
|
||||
let
|
||||
cfg = config.services.snapper;
|
||||
|
||||
mkValue = v:
|
||||
if isList v then "\"${concatMapStringsSep " " (escape [ "\\" " " ]) v}\""
|
||||
else if v == true then "yes"
|
||||
else if v == false then "no"
|
||||
else if isString v then "\"${v}\""
|
||||
else builtins.toJSON v;
|
||||
|
||||
mkKeyValue = k: v: "${k}=${mkValue v}";
|
||||
|
||||
# "it's recommended to always specify the filesystem type" -- man snapper-configs
|
||||
defaultOf = k: if k == "FSTYPE" then null else configOptions.${k}.default or null;
|
||||
|
||||
safeStr = types.strMatching "[^\n\"]*" // {
|
||||
description = "string without line breaks or quotes";
|
||||
descriptionClass = "conjunction";
|
||||
};
|
||||
|
||||
configOptions = {
|
||||
SUBVOLUME = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
Path of the subvolume or mount point.
|
||||
This path is a subvolume and has to contain a subvolume named
|
||||
.snapshots.
|
||||
See also man:snapper(8) section PERMISSIONS.
|
||||
'';
|
||||
};
|
||||
|
||||
FSTYPE = mkOption {
|
||||
type = types.enum [ "btrfs" ];
|
||||
default = "btrfs";
|
||||
description = lib.mdDoc ''
|
||||
Filesystem type. Only btrfs is stable and tested.
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_GROUPS = mkOption {
|
||||
type = types.listOf safeStr;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
List of groups allowed to operate with the config.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_USERS = mkOption {
|
||||
type = types.listOf safeStr;
|
||||
default = [];
|
||||
example = [ "alice" ];
|
||||
description = lib.mdDoc ''
|
||||
List of users allowed to operate with the config. "root" is always
|
||||
implicitly included.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CLEANUP = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Defines whether the timeline cleanup algorithm should be run for the config.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CREATE = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Defines whether hourly snapshots should be created.
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -52,49 +127,23 @@ in
|
|||
example = literalExpression ''
|
||||
{
|
||||
home = {
|
||||
subvolume = "/home";
|
||||
extraConfig = '''
|
||||
ALLOW_USERS="alice"
|
||||
TIMELINE_CREATE=yes
|
||||
TIMELINE_CLEANUP=yes
|
||||
''';
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
};
|
||||
}
|
||||
'';
|
||||
|
||||
description = lib.mdDoc ''
|
||||
Subvolume configuration
|
||||
Subvolume configuration. Any option mentioned in man:snapper-configs(5)
|
||||
is valid here, even if NixOS doesn't document it.
|
||||
'';
|
||||
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
subvolume = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
Path of the subvolume or mount point.
|
||||
This path is a subvolume and has to contain a subvolume named
|
||||
.snapshots.
|
||||
See also man:snapper(8) section PERMISSIONS.
|
||||
'';
|
||||
};
|
||||
freeformType = types.attrsOf (types.oneOf [ (types.listOf safeStr) types.bool safeStr types.number ]);
|
||||
|
||||
fstype = mkOption {
|
||||
type = types.enum [ "btrfs" ];
|
||||
default = "btrfs";
|
||||
description = lib.mdDoc ''
|
||||
Filesystem type. Only btrfs is stable and tested.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = lib.mdDoc ''
|
||||
Additional configuration next to SUBVOLUME and FSTYPE.
|
||||
See man:snapper-configs(5).
|
||||
'';
|
||||
};
|
||||
};
|
||||
options = configOptions;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -117,11 +166,7 @@ in
|
|||
|
||||
}
|
||||
// (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
|
||||
text = ''
|
||||
${subvolume.extraConfig}
|
||||
FSTYPE="${subvolume.fstype}"
|
||||
SUBVOLUME="${subvolume.subvolume}"
|
||||
'';
|
||||
text = lib.generators.toKeyValue { inherit mkKeyValue; } (filterAttrs (k: v: v != defaultOf k) subvolume);
|
||||
})) cfg.configs)
|
||||
// (lib.optionalAttrs (cfg.filters != null) {
|
||||
"snapper/filters/default.txt".text = cfg.filters;
|
||||
|
@ -181,5 +226,28 @@ in
|
|||
unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
|
||||
};
|
||||
|
||||
assertions =
|
||||
concatMap
|
||||
(name:
|
||||
let
|
||||
sub = cfg.configs.${name};
|
||||
in
|
||||
[ { assertion = !(sub ? extraConfig);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.extraConfig' no longer has any effect; please remove it.
|
||||
The contents of this option should be migrated to attributes on `services.snapper.configs.${name}'.
|
||||
'';
|
||||
}
|
||||
] ++
|
||||
map
|
||||
(attr: {
|
||||
assertion = !(hasAttr attr sub);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.${attr}' has been renamed to `services.snapper.configs.${name}.${toUpper attr}'.
|
||||
'';
|
||||
})
|
||||
[ "fstype" "subvolume" ]
|
||||
)
|
||||
(attrNames cfg.configs);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ in
|
|||
agent.enabled = true;
|
||||
agent.scrape_integration = true;
|
||||
node_exporter.enabled = true;
|
||||
replace_instance_label = true;
|
||||
};
|
||||
}
|
||||
'';
|
||||
|
@ -122,7 +121,6 @@ in
|
|||
agent.enabled = mkDefault true;
|
||||
agent.scrape_integration = mkDefault true;
|
||||
node_exporter.enabled = mkDefault true;
|
||||
replace_instance_label = mkDefault true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -169,6 +169,20 @@ in {
|
|||
See: <https://learn.netdata.cloud/docs/agent/anonymous-statistics>
|
||||
'';
|
||||
};
|
||||
|
||||
deadlineBeforeStopSec = mkOption {
|
||||
type = types.int;
|
||||
default = 120;
|
||||
description = lib.mdDoc ''
|
||||
In order to detect when netdata is misbehaving, we run a concurrent task pinging netdata (wait-for-netdata-up)
|
||||
in the systemd unit.
|
||||
|
||||
If after a while, this task does not succeed, we stop the unit and mark it as failed.
|
||||
|
||||
You can control this deadline in seconds with this option, it's useful to bump it
|
||||
if you have (1) a lot of data (2) doing upgrades (3) have low IOPS/throughput.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -205,7 +219,7 @@ in {
|
|||
while [ "$(${pkgs.netdata}/bin/netdatacli ping)" != pong ]; do sleep 0.5; done
|
||||
'';
|
||||
|
||||
TimeoutStopSec = 60;
|
||||
TimeoutStopSec = cfg.deadlineBeforeStopSec;
|
||||
Restart = "on-failure";
|
||||
# User and group
|
||||
User = cfg.user;
|
||||
|
|
|
@ -6,10 +6,12 @@ let
|
|||
cfg = config.services.prometheus.alertmanager;
|
||||
mkConfigFile = pkgs.writeText "alertmanager.yml" (builtins.toJSON cfg.configuration);
|
||||
|
||||
checkedConfig = file: pkgs.runCommand "checked-config" { buildInputs = [ cfg.package ]; } ''
|
||||
ln -s ${file} $out
|
||||
amtool check-config $out
|
||||
'';
|
||||
checkedConfig = file:
|
||||
if cfg.checkConfig then
|
||||
pkgs.runCommand "checked-config" { buildInputs = [ cfg.package ]; } ''
|
||||
ln -s ${file} $out
|
||||
amtool check-config $out
|
||||
'' else file;
|
||||
|
||||
alertmanagerYml = let
|
||||
yml = if cfg.configText != null then
|
||||
|
@ -70,6 +72,20 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
checkConfig = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Check configuration with `amtool check-config`. The call to `amtool` is
|
||||
subject to sandboxing by Nix.
|
||||
|
||||
If you use credentials stored in external files
|
||||
(`environmentFile`, etc),
|
||||
they will not be visible to `amtool`
|
||||
and it will report errors, despite a correct configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
logFormat = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
|
|
@ -76,7 +76,7 @@ example:
|
|||
directory, which will be called postfix.nix and contains all exporter
|
||||
specific options and configuration:
|
||||
```
|
||||
# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||
# nixpkgs/nixos/modules/services/prometheus/exporters/postfix.nix
|
||||
{ config, lib, pkgs, options }:
|
||||
|
||||
with lib;
|
||||
|
|
|
@ -43,6 +43,8 @@ in
|
|||
services.uptime-kuma.settings = {
|
||||
DATA_DIR = "/var/lib/uptime-kuma/";
|
||||
NODE_ENV = mkDefault "production";
|
||||
HOST = mkDefault "127.0.0.1";
|
||||
PORT = mkDefault "3001";
|
||||
};
|
||||
|
||||
systemd.services.uptime-kuma = {
|
||||
|
|
|
@ -28,6 +28,12 @@ in
|
|||
description = lib.mdDoc "Group to run under when setuid is not enabled.";
|
||||
};
|
||||
|
||||
debug = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc "Enable debug mode.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = format.type;
|
||||
default = { };
|
||||
|
@ -111,7 +117,7 @@ in
|
|||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.webdav-server-rs}/bin/webdav-server -c ${cfg.configFile}";
|
||||
ExecStart = "${pkgs.webdav-server-rs}/bin/webdav-server ${lib.optionalString cfg.debug "--debug"} -c ${cfg.configFile}";
|
||||
|
||||
CapabilityBoundingSet = [
|
||||
"CAP_SETUID"
|
||||
|
|
101
nixos/modules/services/networking/alice-lg.nix
Normal file
101
nixos/modules/services/networking/alice-lg.nix
Normal file
|
@ -0,0 +1,101 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.alice-lg;
|
||||
settingsFormat = pkgs.formats.ini { };
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.alice-lg = {
|
||||
enable = mkEnableOption (lib.mdDoc "Alice Looking Glass");
|
||||
|
||||
package = mkPackageOptionMD pkgs "alice-lg" { };
|
||||
|
||||
settings = mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
description = lib.mdDoc ''
|
||||
alice-lg configuration, for configuration options see the example on [github](https://github.com/alice-lg/alice-lg/blob/main/etc/alice-lg/alice.example.conf)
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
server = {
|
||||
# configures the built-in webserver and provides global application settings
|
||||
listen_http = "127.0.0.1:7340";
|
||||
enable_prefix_lookup = true;
|
||||
asn = 9033;
|
||||
store_backend = postgres;
|
||||
routes_store_refresh_parallelism = 5;
|
||||
neighbors_store_refresh_parallelism = 10000;
|
||||
routes_store_refresh_interval = 5;
|
||||
neighbors_store_refresh_interval = 5;
|
||||
};
|
||||
postgres = {
|
||||
url = "postgres://postgres:postgres@localhost:5432/alice";
|
||||
min_connections = 2;
|
||||
max_connections = 128;
|
||||
};
|
||||
pagination = {
|
||||
routes_filtered_page_size = 250;
|
||||
routes_accepted_page_size = 250;
|
||||
routes_not_exported_page_size = 250;
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment = {
|
||||
etc."alice-lg/alice.conf".source = settingsFormat.generate "alice-lg.conf" cfg.settings;
|
||||
};
|
||||
systemd.services = {
|
||||
alice-lg = {
|
||||
wants = [ "network.target" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Alice Looking Glass";
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 15;
|
||||
ExecStart = "${cfg.package}/bin/alice-lg";
|
||||
StateDirectoryMode = "0700";
|
||||
UMask = "0007";
|
||||
CapabilityBoundingSet = "";
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
PrivateMounts = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap";
|
||||
BindReadOnlyPaths = [
|
||||
"-/etc/resolv.conf"
|
||||
"-/etc/nsswitch.conf"
|
||||
"-/etc/ssl/certs"
|
||||
"-/etc/static/ssl/certs"
|
||||
"-/etc/hosts"
|
||||
"-/etc/localtime"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
129
nixos/modules/services/networking/birdwatcher.nix
Normal file
129
nixos/modules/services/networking/birdwatcher.nix
Normal file
|
@ -0,0 +1,129 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.birdwatcher;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.birdwatcher = {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.birdwatcher;
|
||||
defaultText = literalExpression "pkgs.birdwatcher";
|
||||
description = lib.mdDoc "The Birdwatcher package to use.";
|
||||
};
|
||||
enable = mkEnableOption (lib.mdDoc "Birdwatcher");
|
||||
flags = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
example = [ "-worker-pool-size 16" "-6" ];
|
||||
description = lib.mdDoc ''
|
||||
Flags to append to the program call
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.lines;
|
||||
default = { };
|
||||
description = lib.mdDoc ''
|
||||
birdwatcher configuration, for configuration options see the example on [github](https://github.com/alice-lg/birdwatcher/blob/master/etc/birdwatcher/birdwatcher.conf)
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[server]
|
||||
allow_from = []
|
||||
allow_uncached = false
|
||||
modules_enabled = ["status",
|
||||
"protocols",
|
||||
"protocols_bgp",
|
||||
"protocols_short",
|
||||
"routes_protocol",
|
||||
"routes_peer",
|
||||
"routes_table",
|
||||
"routes_table_filtered",
|
||||
"routes_table_peer",
|
||||
"routes_filtered",
|
||||
"routes_prefixed",
|
||||
"routes_noexport",
|
||||
"routes_pipe_filtered_count",
|
||||
"routes_pipe_filtered"
|
||||
]
|
||||
|
||||
[status]
|
||||
reconfig_timestamp_source = "bird"
|
||||
reconfig_timestamp_match = "# created: (.*)"
|
||||
|
||||
filter_fields = []
|
||||
|
||||
[bird]
|
||||
listen = "0.0.0.0:29184"
|
||||
config = "/etc/bird/bird2.conf"
|
||||
birdc = "''${pkgs.bird}/bin/birdc"
|
||||
ttl = 5 # time to live (in minutes) for caching of cli output
|
||||
|
||||
[parser]
|
||||
filter_fields = []
|
||||
|
||||
[cache]
|
||||
use_redis = false # if not using redis cache, activate housekeeping to save memory!
|
||||
|
||||
[housekeeping]
|
||||
interval = 5
|
||||
force_release_memory = true
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let flagsStr = escapeShellArgs cfg.flags;
|
||||
in lib.mkIf cfg.enable {
|
||||
environment.etc."birdwatcher/birdwatcher.conf".source = pkgs.writeTextFile {
|
||||
name = "birdwatcher.conf";
|
||||
text = cfg.settings;
|
||||
};
|
||||
systemd.services = {
|
||||
birdwatcher = {
|
||||
wants = [ "network.target" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Birdwatcher";
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 15;
|
||||
ExecStart = "${cfg.package}/bin/birdwatcher";
|
||||
StateDirectoryMode = "0700";
|
||||
UMask = "0117";
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX AF_INET AF_INET6" ];
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
PrivateMounts = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap";
|
||||
BindReadOnlyPaths = [
|
||||
"-/etc/resolv.conf"
|
||||
"-/etc/nsswitch.conf"
|
||||
"-/etc/ssl/certs"
|
||||
"-/etc/static/ssl/certs"
|
||||
"-/etc/hosts"
|
||||
"-/etc/localtime"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
88
nixos/modules/services/networking/harmonia.nix
Normal file
88
nixos/modules/services/networking/harmonia.nix
Normal file
|
@ -0,0 +1,88 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.services.harmonia;
|
||||
format = pkgs.formats.toml { };
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.harmonia = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "Harmonia: Nix binary cache written in Rust");
|
||||
|
||||
signKeyPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = lib.mdDoc "Path to the signing key that will be used for signing the cache";
|
||||
};
|
||||
|
||||
package = lib.mkPackageOptionMD pkgs "harmonia" { };
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (format) type;
|
||||
default = { };
|
||||
description = lib.mdDoc ''
|
||||
Settings to merge with the default configuration.
|
||||
For the list of the default configuration, see <https://github.com/nix-community/harmonia/tree/master#configuration>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.harmonia = {
|
||||
description = "harmonia binary cache service";
|
||||
|
||||
requires = [ "nix-daemon.socket" ];
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = {
|
||||
CONFIG_FILE = format.generate "harmonia.toml" cfg.settings;
|
||||
SIGN_KEY_PATH = lib.mkIf (cfg.signKeyPath != null) "%d/sign-key";
|
||||
# Note: it's important to set this for nix-store, because it wants to use
|
||||
# $HOME in order to use a temporary cache dir. bizarre failures will occur
|
||||
# otherwise
|
||||
HOME = "/run/harmonia";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
User = "harmonia";
|
||||
Group = "harmonia";
|
||||
DynamicUser = true;
|
||||
PrivateUsers = true;
|
||||
DeviceAllow = [ "" ];
|
||||
UMask = "0066";
|
||||
RuntimeDirectory = "harmonia";
|
||||
LoadCredential = lib.mkIf (cfg.signKeyPath != null) [ "sign-key:${cfg.signKeyPath}" ];
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
CapabilityBoundingSet = "";
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
RestrictRealtime = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectProc = "invisible";
|
||||
RestrictNamespaces = true;
|
||||
SystemCallArchitectures = "native";
|
||||
PrivateNetwork = false;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
NoNewPrivileges = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
LockPersonality = true;
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
LimitNOFILE = 65536;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -365,9 +365,6 @@ in
|
|||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
"hmac-sha2-512"
|
||||
"hmac-sha2-256"
|
||||
"umac-128@openssh.com"
|
||||
];
|
||||
description = lib.mdDoc ''
|
||||
Allowed MACs
|
||||
|
|
|
@ -8,7 +8,8 @@ let
|
|||
cmdArgs =
|
||||
[ "--port" cfg.port ]
|
||||
++ optionals (cfg.salt != null) [ "--salt" cfg.salt ]
|
||||
++ optionals (cfg.certDir != null) [ "--tls" cfg.certDir ];
|
||||
++ optionals (cfg.certDir != null) [ "--tls" cfg.certDir ]
|
||||
++ cfg.extraArgs;
|
||||
|
||||
in
|
||||
{
|
||||
|
@ -33,7 +34,22 @@ in
|
|||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Salt to allow room operator passwords generated by this server
|
||||
instance to still work when the server is restarted.
|
||||
instance to still work when the server is restarted. The salt will be
|
||||
readable in the nix store and the processlist. If this is not
|
||||
intended use `saltFile` instead. Mutually exclusive with
|
||||
<option>services.syncplay.saltFile</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
saltFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Path to the file that contains the server salt. This allows room
|
||||
operator passwords generated by this server instance to still work
|
||||
when the server is restarted. `null`, the server doesn't load the
|
||||
salt from a file. Mutually exclusive with
|
||||
<option>services.syncplay.salt</option>.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -46,6 +62,14 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
Additional arguments to be passed to the service.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "nobody";
|
||||
|
@ -74,21 +98,31 @@ in
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.salt == null || cfg.saltFile == null;
|
||||
message = "services.syncplay.salt and services.syncplay.saltFile are mutually exclusive.";
|
||||
}
|
||||
];
|
||||
systemd.services.syncplay = {
|
||||
description = "Syncplay Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
LoadCredential = lib.mkIf (cfg.passwordFile != null) "password:${cfg.passwordFile}";
|
||||
LoadCredential = lib.optional (cfg.passwordFile != null) "password:${cfg.passwordFile}"
|
||||
++ lib.optional (cfg.saltFile != null) "salt:${cfg.saltFile}";
|
||||
};
|
||||
|
||||
script = ''
|
||||
${lib.optionalString (cfg.passwordFile != null) ''
|
||||
export SYNCPLAY_PASSWORD=$(cat "''${CREDENTIALS_DIRECTORY}/password")
|
||||
''}
|
||||
${lib.optionalString (cfg.saltFile != null) ''
|
||||
export SYNCPLAY_SALT=$(cat "''${CREDENTIALS_DIRECTORY}/salt")
|
||||
''}
|
||||
exec ${pkgs.syncplay-nogui}/bin/syncplay-server ${escapeShellArgs cmdArgs}
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -7,25 +7,24 @@ let
|
|||
opt = options.services.syncthing;
|
||||
defaultUser = "syncthing";
|
||||
defaultGroup = defaultUser;
|
||||
settingsFormat = pkgs.formats.json { };
|
||||
|
||||
devices = mapAttrsToList (name: device: {
|
||||
devices = mapAttrsToList (_: device: device // {
|
||||
deviceID = device.id;
|
||||
inherit (device) name addresses introducer autoAcceptFolders;
|
||||
}) cfg.devices;
|
||||
}) cfg.settings.devices;
|
||||
|
||||
folders = mapAttrsToList ( _: folder: {
|
||||
inherit (folder) path id label type;
|
||||
devices = map (device: { deviceId = cfg.devices.${device}.id; }) folder.devices;
|
||||
rescanIntervalS = folder.rescanInterval;
|
||||
fsWatcherEnabled = folder.watch;
|
||||
fsWatcherDelayS = folder.watchDelay;
|
||||
ignorePerms = folder.ignorePerms;
|
||||
ignoreDelete = folder.ignoreDelete;
|
||||
versioning = folder.versioning;
|
||||
}) (filterAttrs (
|
||||
_: folder:
|
||||
folder.enable
|
||||
) cfg.folders);
|
||||
folders = mapAttrsToList (_: folder: folder //
|
||||
throwIf (folder?rescanInterval || folder?watch || folder?watchDelay) ''
|
||||
The options services.syncthing.settings.folders.<name>.{rescanInterval,watch,watchDelay}
|
||||
were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead.
|
||||
'' {
|
||||
devices = map (device:
|
||||
if builtins.isString device then
|
||||
{ deviceId = cfg.settings.devices.${device}.id; }
|
||||
else
|
||||
device
|
||||
) folder.devices;
|
||||
}) cfg.settings.folders;
|
||||
|
||||
updateConfig = pkgs.writers.writeDash "merge-syncthing-config" ''
|
||||
set -efu
|
||||
|
@ -54,10 +53,10 @@ let
|
|||
old_cfg=$(curl ${cfg.guiAddress}/rest/config)
|
||||
|
||||
# generate the new config by merging with the NixOS config options
|
||||
new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * {
|
||||
"devices": (${builtins.toJSON devices}${optionalString (cfg.devices == {} || ! cfg.overrideDevices) " + .devices"}),
|
||||
"folders": (${builtins.toJSON folders}${optionalString (cfg.folders == {} || ! cfg.overrideFolders) " + .folders"})
|
||||
} * ${builtins.toJSON cfg.extraOptions}')
|
||||
new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c ${escapeShellArg ''. * ${builtins.toJSON cfg.settings} * {
|
||||
"devices": (${builtins.toJSON devices}${optionalString (cfg.settings.devices == {} || ! cfg.overrideDevices) " + .devices"}),
|
||||
"folders": (${builtins.toJSON folders}${optionalString (cfg.settings.folders == {} || ! cfg.overrideFolders) " + .folders"})
|
||||
}''})
|
||||
|
||||
# send the new config
|
||||
curl -X PUT -d "$new_cfg" ${cfg.guiAddress}/rest/config
|
||||
|
@ -99,287 +98,282 @@ in {
|
|||
default = true;
|
||||
description = mdDoc ''
|
||||
Whether to delete the devices which are not configured via the
|
||||
[devices](#opt-services.syncthing.devices) option.
|
||||
[devices](#opt-services.syncthing.settings.devices) option.
|
||||
If set to `false`, devices added via the web
|
||||
interface will persist and will have to be deleted manually.
|
||||
'';
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Peers/devices which Syncthing should communicate with.
|
||||
|
||||
Note that you can still add devices manually, but those changes
|
||||
will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices)
|
||||
is enabled.
|
||||
'';
|
||||
example = {
|
||||
bigbox = {
|
||||
id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
|
||||
addresses = [ "tcp://192.168.0.10:51820" ];
|
||||
};
|
||||
};
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The name of the device.
|
||||
'';
|
||||
};
|
||||
|
||||
addresses = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
The addresses used to connect to the device.
|
||||
If this is left empty, dynamic configuration is attempted.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
description = mdDoc ''
|
||||
The device ID. See <https://docs.syncthing.net/dev/device-ids.html>.
|
||||
'';
|
||||
};
|
||||
|
||||
introducer = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
Whether the device should act as an introducer and be allowed
|
||||
to add folders on this computer.
|
||||
See <https://docs.syncthing.net/users/introducer.html>.
|
||||
'';
|
||||
};
|
||||
|
||||
autoAcceptFolders = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
Automatically create or share folders that this device advertises at the default path.
|
||||
See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
overrideFolders = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = mdDoc ''
|
||||
Whether to delete the folders which are not configured via the
|
||||
[folders](#opt-services.syncthing.folders) option.
|
||||
[folders](#opt-services.syncthing.settings.folders) option.
|
||||
If set to `false`, folders added via the web
|
||||
interface will persist and will have to be deleted manually.
|
||||
'';
|
||||
};
|
||||
|
||||
folders = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Folders which should be shared by Syncthing.
|
||||
|
||||
Note that you can still add folders manually, but those changes
|
||||
will be reverted on restart if [overrideFolders](#opt-services.syncthing.overrideFolders)
|
||||
is enabled.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
"/home/user/sync" = {
|
||||
id = "syncme";
|
||||
devices = [ "bigbox" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to share this folder.
|
||||
This option is useful when you want to define all folders
|
||||
in one place, but not every machine should share all folders.
|
||||
'';
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
# TODO for release 23.05: allow relative paths again and set
|
||||
# working directory to cfg.dataDir
|
||||
type = types.str // {
|
||||
check = x: types.str.check x && (substring 0 1 x == "/" || substring 0 2 x == "~/");
|
||||
description = types.str.description + " starting with / or ~/";
|
||||
};
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The path to the folder which should be shared.
|
||||
Only absolute paths (starting with `/`) and paths relative to
|
||||
the [user](#opt-services.syncthing.user)'s home directory
|
||||
(starting with `~/`) are allowed.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The ID of the folder. Must be the same on all devices.
|
||||
'';
|
||||
};
|
||||
|
||||
label = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The label of the folder.
|
||||
'';
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
# global options
|
||||
options = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
The devices this folder should be shared with. Each device must
|
||||
be defined in the [devices](#opt-services.syncthing.devices) option.
|
||||
The options element contains all other global configuration options
|
||||
'';
|
||||
};
|
||||
|
||||
versioning = mkOption {
|
||||
default = null;
|
||||
description = mdDoc ''
|
||||
How to keep changed/deleted files with Syncthing.
|
||||
There are 4 different types of versioning with different parameters.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
versioning = {
|
||||
type = "simple";
|
||||
params.keep = "10";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "trashcan";
|
||||
params.cleanoutDays = "1000";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
fsPath = "/syncthing/backup";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "31536000";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "external";
|
||||
params.versionsPath = pkgs.writers.writeBash "backup" '''
|
||||
folderpath="$1"
|
||||
filepath="$2"
|
||||
rm -rf "$folderpath/$filepath"
|
||||
''';
|
||||
};
|
||||
}
|
||||
]
|
||||
'';
|
||||
type = with types; nullOr (submodule {
|
||||
type = types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = enum [ "external" "simple" "staggered" "trashcan" ];
|
||||
description = mdDoc ''
|
||||
The type of versioning.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
localAnnounceEnabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to send announcements to the local LAN, also use such announcements to find other devices.
|
||||
'';
|
||||
};
|
||||
fsPath = mkOption {
|
||||
default = "";
|
||||
type = either str path;
|
||||
description = mdDoc ''
|
||||
Path to the versioning folder.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
|
||||
localAnnouncePort = mkOption {
|
||||
type = types.int;
|
||||
default = 21027;
|
||||
description = lib.mdDoc ''
|
||||
The port on which to listen and send IPv4 broadcast announcements to.
|
||||
'';
|
||||
};
|
||||
params = mkOption {
|
||||
type = attrsOf (either str path);
|
||||
description = mdDoc ''
|
||||
The parameters for versioning. Structure depends on
|
||||
[versioning.type](#opt-services.syncthing.folders._name_.versioning.type).
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
|
||||
relaysEnabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
When true, relays will be connected to and potentially used for device to device connections.
|
||||
'';
|
||||
};
|
||||
|
||||
urAccepted = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
description = lib.mdDoc ''
|
||||
Whether the user has accepted to submit anonymous usage data.
|
||||
The default, 0, mean the user has not made a choice, and Syncthing will ask at some point in the future.
|
||||
"-1" means no, a number above zero means that that version of usage reporting has been accepted.
|
||||
'';
|
||||
};
|
||||
|
||||
limitBandwidthInLan = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Whether to apply bandwidth limits to devices in the same broadcast domain as the local device.
|
||||
'';
|
||||
};
|
||||
|
||||
maxFolderConcurrency = mkOption {
|
||||
type = types.int;
|
||||
default = 0;
|
||||
description = lib.mdDoc ''
|
||||
This option controls how many folders may concurrently be in I/O-intensive operations such as syncing or scanning.
|
||||
The mechanism is described in detail in a [separate chapter](https://docs.syncthing.net/advanced/option-max-concurrency.html).
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
rescanInterval = mkOption {
|
||||
type = types.int;
|
||||
default = 3600;
|
||||
description = lib.mdDoc ''
|
||||
How often the folder should be rescanned for changes.
|
||||
'';
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "sendreceive" "sendonly" "receiveonly" "receiveencrypted" ];
|
||||
default = "sendreceive";
|
||||
description = lib.mdDoc ''
|
||||
Whether to only send changes for this folder, only receive them
|
||||
or both. `receiveencrypted` can be used for untrusted devices. See
|
||||
<https://docs.syncthing.net/users/untrusted.html> for reference.
|
||||
'';
|
||||
};
|
||||
|
||||
watch = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether the folder should be watched for changes by inotify.
|
||||
'';
|
||||
};
|
||||
|
||||
watchDelay = mkOption {
|
||||
type = types.int;
|
||||
default = 10;
|
||||
description = lib.mdDoc ''
|
||||
The delay after an inotify event is triggered.
|
||||
'';
|
||||
};
|
||||
|
||||
ignorePerms = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to ignore permission changes.
|
||||
'';
|
||||
};
|
||||
|
||||
ignoreDelete = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
# device settings
|
||||
devices = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Whether to skip deleting files that are deleted by peers.
|
||||
See <https://docs.syncthing.net/advanced/folder-ignoredelete.html>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
Peers/devices which Syncthing should communicate with.
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = types.addCheck (pkgs.formats.json {}).type isAttrs;
|
||||
Note that you can still add devices manually, but those changes
|
||||
will be reverted on restart if [overrideDevices](#opt-services.syncthing.overrideDevices)
|
||||
is enabled.
|
||||
'';
|
||||
example = {
|
||||
bigbox = {
|
||||
id = "7CFNTQM-IMTJBHJ-3UWRDIU-ZGQJFR6-VCXZ3NB-XUH3KZO-N52ITXR-LAIYUAU";
|
||||
addresses = [ "tcp://192.168.0.10:51820" ];
|
||||
};
|
||||
};
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The name of the device.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
description = mdDoc ''
|
||||
The device ID. See <https://docs.syncthing.net/dev/device-ids.html>.
|
||||
'';
|
||||
};
|
||||
|
||||
autoAcceptFolders = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
Automatically create or share folders that this device advertises at the default path.
|
||||
See <https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
# folder settings
|
||||
folders = mkOption {
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Folders which should be shared by Syncthing.
|
||||
|
||||
Note that you can still add folders manually, but those changes
|
||||
will be reverted on restart if [overrideFolders](#opt-services.syncthing.overrideFolders)
|
||||
is enabled.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
"/home/user/sync" = {
|
||||
id = "syncme";
|
||||
devices = [ "bigbox" ];
|
||||
};
|
||||
}
|
||||
'';
|
||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Whether to share this folder.
|
||||
This option is useful when you want to define all folders
|
||||
in one place, but not every machine should share all folders.
|
||||
'';
|
||||
};
|
||||
|
||||
path = mkOption {
|
||||
# TODO for release 23.05: allow relative paths again and set
|
||||
# working directory to cfg.dataDir
|
||||
type = types.str // {
|
||||
check = x: types.str.check x && (substring 0 1 x == "/" || substring 0 2 x == "~/");
|
||||
description = types.str.description + " starting with / or ~/";
|
||||
};
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The path to the folder which should be shared.
|
||||
Only absolute paths (starting with `/`) and paths relative to
|
||||
the [user](#opt-services.syncthing.user)'s home directory
|
||||
(starting with `~/`) are allowed.
|
||||
'';
|
||||
};
|
||||
|
||||
id = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The ID of the folder. Must be the same on all devices.
|
||||
'';
|
||||
};
|
||||
|
||||
label = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = lib.mdDoc ''
|
||||
The label of the folder.
|
||||
'';
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = mdDoc ''
|
||||
The devices this folder should be shared with. Each device must
|
||||
be defined in the [devices](#opt-services.syncthing.settings.devices) option.
|
||||
'';
|
||||
};
|
||||
|
||||
versioning = mkOption {
|
||||
default = null;
|
||||
description = mdDoc ''
|
||||
How to keep changed/deleted files with Syncthing.
|
||||
There are 4 different types of versioning with different parameters.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
versioning = {
|
||||
type = "simple";
|
||||
params.keep = "10";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "trashcan";
|
||||
params.cleanoutDays = "1000";
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
fsPath = "/syncthing/backup";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "31536000";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
versioning = {
|
||||
type = "external";
|
||||
params.versionsPath = pkgs.writers.writeBash "backup" '''
|
||||
folderpath="$1"
|
||||
filepath="$2"
|
||||
rm -rf "$folderpath/$filepath"
|
||||
''';
|
||||
};
|
||||
}
|
||||
]
|
||||
'';
|
||||
type = with types; nullOr (submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
type = mkOption {
|
||||
type = enum [ "external" "simple" "staggered" "trashcan" ];
|
||||
description = mdDoc ''
|
||||
The type of versioning.
|
||||
See <https://docs.syncthing.net/users/versioning.html>.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
copyOwnershipFromParent = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = mdDoc ''
|
||||
On Unix systems, tries to copy file/folder ownership from the parent directory (the directory it’s located in).
|
||||
Requires running Syncthing as a privileged user, or granting it additional capabilities (e.g. CAP_CHOWN on Linux).
|
||||
'';
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
description = mdDoc ''
|
||||
Extra configuration options for Syncthing.
|
||||
|
@ -530,6 +524,10 @@ in {
|
|||
This option was removed because Syncthing now has the inotify functionality included under the name "fswatcher".
|
||||
It can be enabled on a per-folder basis through the web interface.
|
||||
'')
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "extraOptions" ] [ "services" "syncthing" "settings" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "folders" ] [ "services" "syncthing" "settings" "folders" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "devices" ] [ "services" "syncthing" "settings" "devices" ])
|
||||
(mkRenamedOptionModule [ "services" "syncthing" "options" ] [ "services" "syncthing" "settings" "options" ])
|
||||
] ++ map (o:
|
||||
mkRenamedOptionModule [ "services" "syncthing" "declarative" o ] [ "services" "syncthing" o ]
|
||||
) [ "cert" "key" "devices" "folders" "overrideDevices" "overrideFolders" "extraOptions"];
|
||||
|
@ -615,9 +613,7 @@ in {
|
|||
];
|
||||
};
|
||||
};
|
||||
syncthing-init = mkIf (
|
||||
cfg.devices != {} || cfg.folders != {} || cfg.extraOptions != {}
|
||||
) {
|
||||
syncthing-init = mkIf (cfg.settings != {}) {
|
||||
description = "Syncthing configuration updater";
|
||||
requisite = [ "syncthing.service" ];
|
||||
after = [ "syncthing.service" ];
|
||||
|
|
|
@ -170,10 +170,22 @@ let
|
|||
|
||||
# peer options
|
||||
|
||||
peerOpts = {
|
||||
peerOpts = self: {
|
||||
|
||||
options = {
|
||||
|
||||
name = mkOption {
|
||||
default =
|
||||
replaceStrings
|
||||
[ "/" "-" " " "+" "=" ]
|
||||
[ "-" "\\x2d" "\\x20" "\\x2b" "\\x3d" ]
|
||||
self.config.publicKey;
|
||||
defaultText = literalExpression "publicKey";
|
||||
example = "bernd";
|
||||
type = types.str;
|
||||
description = lib.mdDoc "Name used to derive peer unit name.";
|
||||
};
|
||||
|
||||
publicKey = mkOption {
|
||||
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
|
||||
type = types.singleLineStr;
|
||||
|
@ -313,15 +325,11 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
peerUnitServiceName = interfaceName: publicKey: dynamicRefreshEnabled:
|
||||
peerUnitServiceName = interfaceName: peerName: dynamicRefreshEnabled:
|
||||
let
|
||||
keyToUnitName = replaceStrings
|
||||
[ "/" "-" " " "+" "=" ]
|
||||
[ "-" "\\x2d" "\\x20" "\\x2b" "\\x3d" ];
|
||||
unitName = keyToUnitName publicKey;
|
||||
refreshSuffix = optionalString dynamicRefreshEnabled "-refresh";
|
||||
in
|
||||
"wireguard-${interfaceName}-peer-${unitName}${refreshSuffix}";
|
||||
"wireguard-${interfaceName}-peer-${peerName}${refreshSuffix}";
|
||||
|
||||
generatePeerUnit = { interfaceName, interfaceCfg, peer }:
|
||||
let
|
||||
|
@ -337,10 +345,11 @@ let
|
|||
# We generate a different name (a `-refresh` suffix) when `dynamicEndpointRefreshSeconds`
|
||||
# to avoid that the same service switches `Type` (`oneshot` vs `simple`),
|
||||
# with the intent to make scripting more obvious.
|
||||
serviceName = peerUnitServiceName interfaceName peer.publicKey dynamicRefreshEnabled;
|
||||
serviceName = peerUnitServiceName interfaceName peer.name dynamicRefreshEnabled;
|
||||
in nameValuePair serviceName
|
||||
{
|
||||
description = "WireGuard Peer - ${interfaceName} - ${peer.publicKey}";
|
||||
description = "WireGuard Peer - ${interfaceName} - ${peer.name}"
|
||||
+ optionalString (peer.name != peer.publicKey) " (${peer.publicKey})";
|
||||
requires = [ "wireguard-${interfaceName}.service" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "wireguard-${interfaceName}.service" "network-online.target" ];
|
||||
|
@ -418,7 +427,7 @@ let
|
|||
# the target is required to start new peer units when they are added
|
||||
generateInterfaceTarget = name: values:
|
||||
let
|
||||
mkPeerUnit = peer: (peerUnitServiceName name peer.publicKey (peer.dynamicEndpointRefreshSeconds != 0)) + ".service";
|
||||
mkPeerUnit = peer: (peerUnitServiceName name peer.name (peer.dynamicEndpointRefreshSeconds != 0)) + ".service";
|
||||
in
|
||||
nameValuePair "wireguard-${name}"
|
||||
rec {
|
||||
|
|
|
@ -90,7 +90,7 @@ in
|
|||
|
||||
};
|
||||
|
||||
config = {
|
||||
config = mkIf cfg.enable {
|
||||
services.cloud-init.settings = {
|
||||
system_info = mkDefault {
|
||||
distro = "nixos";
|
||||
|
@ -142,7 +142,6 @@ in
|
|||
"power-state-change"
|
||||
];
|
||||
};
|
||||
} // (mkIf cfg.enable {
|
||||
|
||||
environment.etc."cloud/cloud.cfg" =
|
||||
if cfg.config == "" then
|
||||
|
@ -225,5 +224,7 @@ in
|
|||
description = "Cloud-config availability";
|
||||
requires = [ "cloud-init-local.service" "cloud-init.service" ];
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
meta.maintainers = [ maintainers.zimbatm ];
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ in {
|
|||
`true`.
|
||||
|
||||
It does NOT apply to the daemon port nor the web UI port. To access those
|
||||
ports secuerly check the documentation
|
||||
ports securely check the documentation
|
||||
<https://dev.deluge-torrent.org/wiki/UserGuide/ThinClient#CreateSSHTunnel>
|
||||
or use a VPN or configure certificates for deluge.
|
||||
'';
|
||||
|
|
66
nixos/modules/services/web-apps/mainsail.nix
Normal file
66
nixos/modules/services/web-apps/mainsail.nix
Normal file
|
@ -0,0 +1,66 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.mainsail;
|
||||
moonraker = config.services.moonraker;
|
||||
in
|
||||
{
|
||||
options.services.mainsail = {
|
||||
enable = mkEnableOption (lib.mdDoc "a modern and responsive user interface for Klipper");
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = lib.mdDoc "Mainsail package to be used in the module";
|
||||
default = pkgs.mainsail;
|
||||
defaultText = literalExpression "pkgs.mainsail";
|
||||
};
|
||||
|
||||
hostName = mkOption {
|
||||
type = types.str;
|
||||
default = "localhost";
|
||||
description = lib.mdDoc "Hostname to serve mainsail on";
|
||||
};
|
||||
|
||||
nginx = mkOption {
|
||||
type = types.submodule
|
||||
(import ../web-servers/nginx/vhost-options.nix { inherit config lib; });
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
serverAliases = [ "mainsail.''${config.networking.domain}" ];
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc "Extra configuration for the nginx virtual host of mainsail.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
upstreams.mainsail-apiserver.servers."${moonraker.address}:${toString moonraker.port}" = { };
|
||||
virtualHosts."${cfg.hostName}" = mkMerge [
|
||||
cfg.nginx
|
||||
{
|
||||
root = mkForce "${cfg.package}/share/mainsail";
|
||||
locations = {
|
||||
"/" = {
|
||||
index = "index.html";
|
||||
tryFiles = "$uri $uri/ /index.html";
|
||||
};
|
||||
"/index.html".extraConfig = ''
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
'';
|
||||
"/websocket" = {
|
||||
proxyWebsockets = true;
|
||||
proxyPass = "http://mainsail-apiserver/websocket";
|
||||
};
|
||||
"~ ^/(printer|api|access|machine|server)/" = {
|
||||
proxyWebsockets = true;
|
||||
proxyPass = "http://mainsail-apiserver$request_uri";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -588,11 +588,12 @@ in {
|
|||
'';
|
||||
}
|
||||
{
|
||||
assertion = 1 == builtins.length
|
||||
(lib.mapAttrsToList
|
||||
(_: v: builtins.elem "scheduler" v.jobClasses || v.jobClasses == [ ])
|
||||
cfg.sidekiqProcesses);
|
||||
message = "There must be one and only one Sidekiq queue in services.mastodon.sidekiqProcesses with jobClass \"scheduler\".";
|
||||
assertion = 1 ==
|
||||
(lib.count (x: x)
|
||||
(lib.mapAttrsToList
|
||||
(_: v: builtins.elem "scheduler" v.jobClasses || v.jobClasses == [ ])
|
||||
cfg.sidekiqProcesses));
|
||||
message = "There must be exactly one Sidekiq queue in services.mastodon.sidekiqProcesses with jobClass \"scheduler\".";
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Matomo is a real-time web analytics application. This module configures
|
||||
php-fpm as backend for Matomo, optionally configuring an nginx vhost as well.
|
||||
|
||||
An automatic setup is not suported by Matomo, so you need to configure Matomo
|
||||
An automatic setup is not supported by Matomo, so you need to configure Matomo
|
||||
itself in the browser-based Matomo setup.
|
||||
|
||||
## Database Setup {#module-services-matomo-database-setup}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
let
|
||||
cfg = config.services.nextcloud.notify_push;
|
||||
cfgN = config.services.nextcloud;
|
||||
in
|
||||
{
|
||||
options.services.nextcloud.notify_push = {
|
||||
|
@ -25,6 +26,16 @@ in
|
|||
default = "error";
|
||||
description = lib.mdDoc "Log level";
|
||||
};
|
||||
|
||||
bendDomainToLocalhost = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Wether to add an entry to `/etc/hosts` for the configured nextcloud domain to point to `localhost` and add `localhost `to nextcloud's `trusted_proxies` config option.
|
||||
|
||||
This is useful when nextcloud's domain is not a static IP address and when the reverse proxy cannot be bypassed because the backend connection is done via unix socket.
|
||||
'';
|
||||
};
|
||||
} // (
|
||||
lib.genAttrs [
|
||||
"dbtype"
|
||||
|
@ -44,11 +55,14 @@ in
|
|||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.nextcloud-notify_push = let
|
||||
nextcloudUrl = "http${lib.optionalString config.services.nextcloud.https "s"}://${config.services.nextcloud.hostName}";
|
||||
nextcloudUrl = "http${lib.optionalString cfgN.https "s"}://${cfgN.hostName}";
|
||||
in {
|
||||
description = "Push daemon for Nextcloud clients";
|
||||
documentation = [ "https://github.com/nextcloud/notify_push" ];
|
||||
after = [ "phpfpm-nextcloud.service" ];
|
||||
after = [
|
||||
"phpfpm-nextcloud.service"
|
||||
"redis-nextcloud.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment = {
|
||||
NEXTCLOUD_URL = nextcloudUrl;
|
||||
|
@ -57,7 +71,7 @@ in
|
|||
LOG = cfg.logLevel;
|
||||
};
|
||||
postStart = ''
|
||||
${config.services.nextcloud.occ}/bin/nextcloud-occ notify_push:setup ${nextcloudUrl}/push
|
||||
${cfgN.occ}/bin/nextcloud-occ notify_push:setup ${nextcloudUrl}/push
|
||||
'';
|
||||
script = let
|
||||
dbType = if cfg.dbtype == "pgsql" then "postgresql" else cfg.dbtype;
|
||||
|
@ -76,7 +90,7 @@ in
|
|||
export DATABASE_PASSWORD="$(<"${cfg.dbpassFile}")"
|
||||
'' + ''
|
||||
export DATABASE_URL="${dbUrl}"
|
||||
${cfg.package}/bin/notify_push '${config.services.nextcloud.datadir}/config/config.php'
|
||||
${cfg.package}/bin/notify_push '${cfgN.datadir}/config/config.php'
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "nextcloud";
|
||||
|
@ -87,10 +101,23 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${config.services.nextcloud.hostName}.locations."^~ /push/" = {
|
||||
proxyPass = "http://unix:${cfg.socketPath}";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
networking.hosts = lib.mkIf cfg.bendDomainToLocalhost {
|
||||
"127.0.0.1" = [ cfgN.hostName ];
|
||||
"::1" = [ cfgN.hostName ];
|
||||
};
|
||||
|
||||
services = lib.mkMerge [
|
||||
{
|
||||
nginx.virtualHosts.${cfgN.hostName}.locations."^~ /push/" = {
|
||||
proxyPass = "http://unix:${cfg.socketPath}";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.bendDomainToLocalhost {
|
||||
nextcloud.extraOptions.trusted_proxies = [ "127.0.0.1" "::1" ];
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@ and optionally supports
|
|||
|
||||
For the database, you can set
|
||||
[`services.nextcloud.config.dbtype`](#opt-services.nextcloud.config.dbtype) to
|
||||
either `sqlite` (the default), `mysql`, or `pgsql`. For the last two, by
|
||||
default, a local database will be created and nextcloud will connect to it via
|
||||
socket; this can be disabled by setting
|
||||
either `sqlite` (the default), `mysql`, or `pgsql`. The simplest is `sqlite`,
|
||||
which will be automatically created and managed by the application. For the
|
||||
last two, you can easily create a local database by setting
|
||||
[`services.nextcloud.database.createLocally`](#opt-services.nextcloud.database.createLocally)
|
||||
to `false`.
|
||||
to `true`, Nextcloud will automatically be configured to connect to it through
|
||||
socket.
|
||||
|
||||
A very basic configuration may look like this:
|
||||
```
|
||||
|
@ -30,6 +31,7 @@ A very basic configuration may look like this:
|
|||
services.nextcloud = {
|
||||
enable = true;
|
||||
hostName = "nextcloud.tld";
|
||||
database.createLocally = true;
|
||||
config = {
|
||||
dbtype = "pgsql";
|
||||
adminpassFile = "/path/to/admin-pass-file";
|
||||
|
|
|
@ -317,7 +317,7 @@ in {
|
|||
|
||||
createLocally = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Create the database and database user locally.
|
||||
'';
|
||||
|
@ -551,6 +551,19 @@ in {
|
|||
default = true;
|
||||
};
|
||||
|
||||
configureRedis = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = config.services.nextcloud.notify_push.enable;
|
||||
defaultText = literalExpression "config.services.nextcloud.notify_push.enable";
|
||||
description = lib.mdDoc ''
|
||||
Wether to configure nextcloud to use the recommended redis settings for small instances.
|
||||
|
||||
::: {.note}
|
||||
The `notify_push` app requires redis to be configured. If this option is turned off, this must be configured manually.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
caching = {
|
||||
apcu = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -741,9 +754,8 @@ in {
|
|||
{ assertions = [
|
||||
{ assertion = cfg.database.createLocally -> cfg.config.dbpassFile == null;
|
||||
message = ''
|
||||
Using `services.nextcloud.database.createLocally` (that now defaults
|
||||
to true) with database password authentication is no longer
|
||||
supported.
|
||||
Using `services.nextcloud.database.createLocally` with database
|
||||
password authentication is no longer supported.
|
||||
|
||||
If you use an external database (or want to use password auth for any
|
||||
other reason), set `services.nextcloud.database.createLocally` to
|
||||
|
@ -1044,6 +1056,25 @@ in {
|
|||
}];
|
||||
};
|
||||
|
||||
services.redis.servers.nextcloud = lib.mkIf cfg.configureRedis {
|
||||
enable = true;
|
||||
user = "nextcloud";
|
||||
};
|
||||
|
||||
services.nextcloud = lib.mkIf cfg.configureRedis {
|
||||
caching.redis = true;
|
||||
extraOptions = {
|
||||
memcache = {
|
||||
distributed = ''\OC\Memcache\Redis'';
|
||||
locking = ''\OC\Memcache\Redis'';
|
||||
};
|
||||
redis = {
|
||||
host = config.services.redis.servers.nextcloud.unixSocket;
|
||||
port = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.enable = mkDefault true;
|
||||
|
||||
services.nginx.virtualHosts.${cfg.hostName} = {
|
||||
|
|
211
nixos/modules/services/web-apps/openvscode-server.nix
Normal file
211
nixos/modules/services/web-apps/openvscode-server.nix
Normal file
|
@ -0,0 +1,211 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.openvscode-server;
|
||||
defaultUser = "openvscode-server";
|
||||
defaultGroup = defaultUser;
|
||||
in {
|
||||
options = {
|
||||
services.openvscode-server = {
|
||||
enable = lib.mkEnableOption (lib.mdDoc "openvscode-server");
|
||||
|
||||
package = lib.mkPackageOptionMD pkgs "openvscode-server" { };
|
||||
|
||||
extraPackages = lib.mkOption {
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
Additional packages to add to the openvscode-server {env}`PATH`.
|
||||
'';
|
||||
example = lib.literalExpression "[ pkgs.go ]";
|
||||
type = lib.types.listOf lib.types.package;
|
||||
};
|
||||
|
||||
extraEnvironment = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
description = lib.mdDoc ''
|
||||
Additional environment variables to pass to openvscode-server.
|
||||
'';
|
||||
default = { };
|
||||
example = { PKG_CONFIG_PATH = "/run/current-system/sw/lib/pkgconfig"; };
|
||||
};
|
||||
|
||||
extraArguments = lib.mkOption {
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
Additional arguments to pass to openvscode-server.
|
||||
'';
|
||||
example = lib.literalExpression ''[ "--log=info" ]'';
|
||||
type = lib.types.listOf lib.types.str;
|
||||
};
|
||||
|
||||
host = lib.mkOption {
|
||||
default = "localhost";
|
||||
description = lib.mdDoc ''
|
||||
The host name or IP address the server should listen to.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
default = 3000;
|
||||
description = lib.mdDoc ''
|
||||
The port the server should listen to. If 0 is passed a random free port is picked. If a range in the format num-num is passed, a free port from the range (end inclusive) is selected.
|
||||
'';
|
||||
type = lib.types.port;
|
||||
};
|
||||
|
||||
user = lib.mkOption {
|
||||
default = defaultUser;
|
||||
example = "yourUser";
|
||||
description = lib.mdDoc ''
|
||||
The user to run openvscode-server as.
|
||||
By default, a user named `${defaultUser}` will be created.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
default = defaultGroup;
|
||||
example = "yourGroup";
|
||||
description = lib.mdDoc ''
|
||||
The group to run openvscode-server under.
|
||||
By default, a group named `${defaultGroup}` will be created.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
extraGroups = lib.mkOption {
|
||||
default = [ ];
|
||||
description = lib.mdDoc ''
|
||||
An array of additional groups for the `${defaultUser}` user.
|
||||
'';
|
||||
example = [ "docker" ];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
};
|
||||
|
||||
withoutConnectionToken = lib.mkOption {
|
||||
default = false;
|
||||
description = lib.mdDoc ''
|
||||
Run without a connection token. Only use this if the connection is secured by other means.
|
||||
'';
|
||||
example = true;
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
socketPath = lib.mkOption {
|
||||
default = null;
|
||||
example = "/run/openvscode/socket";
|
||||
description = lib.mdDoc ''
|
||||
The path to a socket file for the server to listen to.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
userDataDir = lib.mkOption {
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
serverDataDir = lib.mkOption {
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Specifies the directory that server data is kept in.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
extensionsDir = lib.mkOption {
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Set the root path for extensions.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
telemetryLevel = lib.mkOption {
|
||||
default = "off";
|
||||
example = "crash";
|
||||
description = lib.mdDoc ''
|
||||
Sets the initial telemetry level. Valid levels are: 'off', 'crash', 'error' and 'all'.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
connectionToken = lib.mkOption {
|
||||
default = null;
|
||||
example = "secret-token";
|
||||
description = lib.mdDoc ''
|
||||
A secret that must be included with all requests.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
connectionTokenFile = lib.mkOption {
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
Path to a file that contains the connection token.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.openvscode-server = {
|
||||
description = "OpenVSCode server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
path = cfg.extraPackages;
|
||||
environment = cfg.extraEnvironment;
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${lib.getExe cfg.package} \
|
||||
--accept-server-license-terms \
|
||||
--host=${cfg.host} \
|
||||
--port=${toString cfg.port} \
|
||||
'' + lib.optionalString (cfg.telemetryLevel == true) ''
|
||||
--telemetry-level=${cfg.telemetryLevel} \
|
||||
'' + lib.optionalString (cfg.withoutConnectionToken == true) ''
|
||||
--without-connection-token \
|
||||
'' + lib.optionalString (cfg.socketPath != null) ''
|
||||
--socket-path=${cfg.socketPath} \
|
||||
'' + lib.optionalString (cfg.userDataDir != null) ''
|
||||
--user-data-dir=${cfg.userDataDir} \
|
||||
'' + lib.optionalString (cfg.serverDataDir != null) ''
|
||||
--server-data-dir=${cfg.serverDataDir} \
|
||||
'' + lib.optionalString (cfg.extensionsDir != null) ''
|
||||
--extensions-dir=${cfg.extensionsDir} \
|
||||
'' + lib.optionalString (cfg.connectionToken != null) ''
|
||||
--connection-token=${cfg.connectionToken} \
|
||||
'' + lib.optionalString (cfg.connectionTokenFile != null) ''
|
||||
--connection-token-file=${cfg.connectionTokenFile} \
|
||||
'' + lib.escapeShellArgs cfg.extraArguments;
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
RuntimeDirectory = cfg.user;
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
users.users."${cfg.user}" = lib.mkMerge [
|
||||
(lib.mkIf (cfg.user == defaultUser) {
|
||||
isNormalUser = true;
|
||||
description = "openvscode-server user";
|
||||
inherit (cfg) group;
|
||||
})
|
||||
{
|
||||
packages = cfg.extraPackages;
|
||||
inherit (cfg) extraGroups;
|
||||
}
|
||||
];
|
||||
|
||||
users.groups."${defaultGroup}" = lib.mkIf (cfg.group == defaultGroup) { };
|
||||
};
|
||||
|
||||
meta.maintainers = [ lib.maintainers.drupol ];
|
||||
}
|
|
@ -429,7 +429,7 @@ in {
|
|||
|
||||
environment = env;
|
||||
|
||||
path = with pkgs; [ bashInteractive ffmpeg nodejs_16 openssl yarn python3 ];
|
||||
path = with pkgs; [ bashInteractive ffmpeg nodejs_18 openssl yarn python3 ];
|
||||
|
||||
script = ''
|
||||
#!/bin/sh
|
||||
|
@ -490,7 +490,7 @@ in {
|
|||
services.nginx = lib.mkIf cfg.configureNginx {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.localDomain}" = {
|
||||
root = "/var/lib/peertube";
|
||||
root = "/var/lib/peertube/www";
|
||||
|
||||
# Application
|
||||
locations."/" = {
|
||||
|
@ -593,7 +593,7 @@ in {
|
|||
|
||||
# Bypass PeerTube for performance reasons.
|
||||
locations."~ ^/client/(assets/images/(icons/icon-36x36\.png|icons/icon-48x48\.png|icons/icon-72x72\.png|icons/icon-96x96\.png|icons/icon-144x144\.png|icons/icon-192x192\.png|icons/icon-512x512\.png|logo\.svg|favicon\.png|default-playlist\.jpg|default-avatar-account\.png|default-avatar-account-48x48\.png|default-avatar-video-channel\.png|default-avatar-video-channel-48x48\.png))$" = {
|
||||
tryFiles = "/www/client-overrides/$1 /www/client/$1 $1";
|
||||
tryFiles = "/client-overrides/$1 /client/$1 $1";
|
||||
priority = 1310;
|
||||
};
|
||||
|
||||
|
@ -859,7 +859,7 @@ in {
|
|||
home = cfg.package;
|
||||
};
|
||||
})
|
||||
(lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package peertubeEnv peertubeCli pkgs.ffmpeg pkgs.nodejs_16 pkgs.yarn ])
|
||||
(lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package peertubeEnv peertubeCli pkgs.ffmpeg pkgs.nodejs_18 pkgs.yarn ])
|
||||
(lib.mkIf cfg.redis.enableUnixSocket {${config.services.peertube.user}.extraGroups = [ "redis-peertube" ];})
|
||||
];
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ in
|
|||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.pict-rs = {
|
||||
environment = {
|
||||
PICTRS_PATH = cfg.dataDir;
|
||||
PICTRS_ADDR = "${cfg.address}:${toString cfg.port}";
|
||||
PICTRS__PATH = cfg.dataDir;
|
||||
PICTRS__ADDR = "${cfg.address}:${toString cfg.port}";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
|
|
478
nixos/modules/services/web-apps/pixelfed.nix
Normal file
478
nixos/modules/services/web-apps/pixelfed.nix
Normal file
|
@ -0,0 +1,478 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.pixelfed;
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
pixelfed = cfg.package.override { inherit (cfg) dataDir runtimeDir; };
|
||||
# https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L185-L190
|
||||
extraPrograms = with pkgs; [ jpegoptim optipng pngquant gifsicle ffmpeg ];
|
||||
# Ensure PHP extensions: https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L135-L147
|
||||
phpPackage = cfg.phpPackage.buildEnv {
|
||||
extensions = { enabled, all }:
|
||||
enabled
|
||||
++ (with all; [ bcmath ctype curl mbstring gd intl zip redis imagick ]);
|
||||
};
|
||||
configFile =
|
||||
pkgs.writeText "pixelfed-env" (lib.generators.toKeyValue { } cfg.settings);
|
||||
# Management script
|
||||
pixelfed-manage = pkgs.writeShellScriptBin "pixelfed-manage" ''
|
||||
cd ${pixelfed}
|
||||
sudo=exec
|
||||
if [[ "$USER" != ${user} ]]; then
|
||||
sudo='exec /run/wrappers/bin/sudo -u ${user}'
|
||||
fi
|
||||
$sudo ${cfg.phpPackage}/bin/php artisan "$@"
|
||||
'';
|
||||
dbSocket = {
|
||||
"pgsql" = "/run/postgresql";
|
||||
"mysql" = "/run/mysqld/mysqld.sock";
|
||||
}.${cfg.database.type};
|
||||
dbService = {
|
||||
"pgsql" = "postgresql.service";
|
||||
"mysql" = "mysql.service";
|
||||
}.${cfg.database.type};
|
||||
redisService = "redis-pixelfed.service";
|
||||
in {
|
||||
options.services = {
|
||||
pixelfed = {
|
||||
enable = mkEnableOption (lib.mdDoc "a Pixelfed instance");
|
||||
package = mkPackageOptionMD pkgs "pixelfed" { };
|
||||
phpPackage = mkPackageOptionMD pkgs "php81" { };
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "pixelfed";
|
||||
description = lib.mdDoc ''
|
||||
User account under which pixelfed runs.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value this user will automatically be created
|
||||
on system activation, otherwise you are responsible for
|
||||
ensuring the user exists before the pixelfed application starts.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "pixelfed";
|
||||
description = lib.mdDoc ''
|
||||
Group account under which pixelfed runs.
|
||||
|
||||
::: {.note}
|
||||
If left as the default value this group will automatically be created
|
||||
on system activation, otherwise you are responsible for
|
||||
ensuring the group exists before the pixelfed application starts.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
description = lib.mdDoc ''
|
||||
FQDN for the Pixelfed instance.
|
||||
'';
|
||||
};
|
||||
|
||||
secretFile = mkOption {
|
||||
type = types.path;
|
||||
description = lib.mdDoc ''
|
||||
A secret file to be sourced for the .env settings.
|
||||
Place `APP_KEY` and other settings that should not end up in the Nix store here.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; (attrsOf (oneOf [ bool int str ]));
|
||||
description = lib.mdDoc ''
|
||||
.env settings for Pixelfed.
|
||||
Secrets should use `secretFile` option instead.
|
||||
'';
|
||||
};
|
||||
|
||||
nginx = mkOption {
|
||||
type = types.nullOr (types.submodule
|
||||
(import ../web-servers/nginx/vhost-options.nix {
|
||||
inherit config lib;
|
||||
}));
|
||||
default = null;
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
serverAliases = [
|
||||
"pics.''${config.networking.domain}"
|
||||
];
|
||||
enableACME = true;
|
||||
forceHttps = true;
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
With this option, you can customize an nginx virtual host which already has sensible defaults for Dolibarr.
|
||||
Set to {} if you do not need any customization to the virtual host.
|
||||
If enabled, then by default, the {option}`serverName` is
|
||||
`''${domain}`,
|
||||
If this is set to null (the default), no nginx virtualHost will be configured.
|
||||
'';
|
||||
};
|
||||
|
||||
redis.createLocally = mkEnableOption
|
||||
(lib.mdDoc "a local Redis database using UNIX socket authentication")
|
||||
// {
|
||||
default = true;
|
||||
};
|
||||
|
||||
database = {
|
||||
createLocally = mkEnableOption
|
||||
(lib.mdDoc "a local database using UNIX socket authentication") // {
|
||||
default = true;
|
||||
};
|
||||
automaticMigrations = mkEnableOption
|
||||
(lib.mdDoc "automatic migrations for database schema and data") // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "mysql" "pgsql" ];
|
||||
example = "pgsql";
|
||||
default = "mysql";
|
||||
description = lib.mdDoc ''
|
||||
Database engine to use.
|
||||
Note that PGSQL is not well supported: https://github.com/pixelfed/pixelfed/issues/2727
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "pixelfed";
|
||||
description = lib.mdDoc "Database name.";
|
||||
};
|
||||
};
|
||||
|
||||
maxUploadSize = mkOption {
|
||||
type = types.str;
|
||||
default = "8M";
|
||||
description = lib.mdDoc ''
|
||||
Max upload size with units.
|
||||
'';
|
||||
};
|
||||
|
||||
poolConfig = mkOption {
|
||||
type = with types; attrsOf (oneOf [ int str bool ]);
|
||||
default = { };
|
||||
|
||||
description = lib.mdDoc ''
|
||||
Options for Pixelfed's PHP-FPM pool.
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/pixelfed";
|
||||
description = lib.mdDoc ''
|
||||
State directory of the `pixelfed` user which holds
|
||||
the application's state and data.
|
||||
'';
|
||||
};
|
||||
|
||||
runtimeDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/run/pixelfed";
|
||||
description = lib.mdDoc ''
|
||||
Ruutime directory of the `pixelfed` user which holds
|
||||
the application's caches and temporary files.
|
||||
'';
|
||||
};
|
||||
|
||||
schedulerInterval = mkOption {
|
||||
type = types.str;
|
||||
default = "1d";
|
||||
description = lib.mdDoc "How often the Pixelfed cron task should run";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.users.pixelfed = mkIf (cfg.user == "pixelfed") {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
extraGroups = lib.optional cfg.redis.createLocally "redis-pixelfed";
|
||||
};
|
||||
users.groups.pixelfed = mkIf (cfg.group == "pixelfed") { };
|
||||
|
||||
services.redis.servers.pixelfed.enable = lib.mkIf cfg.redis.createLocally true;
|
||||
services.pixelfed.settings = mkMerge [
|
||||
({
|
||||
APP_ENV = mkDefault "production";
|
||||
APP_DEBUG = mkDefault false;
|
||||
# https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L312-L316
|
||||
APP_URL = mkDefault "https://${cfg.domain}";
|
||||
ADMIN_DOMAIN = mkDefault cfg.domain;
|
||||
APP_DOMAIN = mkDefault cfg.domain;
|
||||
SESSION_DOMAIN = mkDefault cfg.domain;
|
||||
SESSION_SECURE_COOKIE = mkDefault true;
|
||||
OPEN_REGISTRATION = mkDefault false;
|
||||
# ActivityPub: https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L360-L364
|
||||
ACTIVITY_PUB = mkDefault true;
|
||||
AP_REMOTE_FOLLOW = mkDefault true;
|
||||
AP_INBOX = mkDefault true;
|
||||
AP_OUTBOX = mkDefault true;
|
||||
AP_SHAREDINBOX = mkDefault true;
|
||||
# Image optimization: https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L367-L404
|
||||
PF_OPTIMIZE_IMAGES = mkDefault true;
|
||||
IMAGE_DRIVER = mkDefault "imagick";
|
||||
# Mobile APIs
|
||||
OAUTH_ENABLED = mkDefault true;
|
||||
# https://github.com/pixelfed/pixelfed/blob/dev/app/Console/Commands/Installer.php#L351
|
||||
EXP_EMC = mkDefault true;
|
||||
# Defer to systemd
|
||||
LOG_CHANNEL = mkDefault "stderr";
|
||||
# TODO: find out the correct syntax?
|
||||
# TRUST_PROXIES = mkDefault "127.0.0.1/8, ::1/128";
|
||||
})
|
||||
(mkIf (cfg.redis.createLocally) {
|
||||
BROADCAST_DRIVER = mkDefault "redis";
|
||||
CACHE_DRIVER = mkDefault "redis";
|
||||
QUEUE_DRIVER = mkDefault "redis";
|
||||
SESSION_DRIVER = mkDefault "redis";
|
||||
WEBSOCKET_REPLICATION_MODE = mkDefault "redis";
|
||||
# Suppport phpredis and predis configuration-style.
|
||||
REDIS_SCHEME = "unix";
|
||||
REDIS_HOST = config.services.redis.servers.pixelfed.unixSocket;
|
||||
REDIS_PATH = config.services.redis.servers.pixelfed.unixSocket;
|
||||
})
|
||||
(mkIf (cfg.database.createLocally) {
|
||||
DB_CONNECTION = cfg.database.type;
|
||||
DB_SOCKET = dbSocket;
|
||||
DB_DATABASE = cfg.database.name;
|
||||
DB_USERNAME = user;
|
||||
# No TCP/IP connection.
|
||||
DB_PORT = 0;
|
||||
})
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pixelfed-manage ];
|
||||
|
||||
services.mysql =
|
||||
mkIf (cfg.database.createLocally && cfg.database.type == "mysql") {
|
||||
enable = mkDefault true;
|
||||
package = mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [{
|
||||
name = user;
|
||||
ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
|
||||
}];
|
||||
};
|
||||
|
||||
services.postgresql =
|
||||
mkIf (cfg.database.createLocally && cfg.database.type == "pgsql") {
|
||||
enable = mkDefault true;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [{
|
||||
name = user;
|
||||
ensurePermissions = { };
|
||||
}];
|
||||
};
|
||||
|
||||
# Make each individual option overridable with lib.mkDefault.
|
||||
services.pixelfed.poolConfig = lib.mapAttrs' (n: v: lib.nameValuePair n (lib.mkDefault v)) {
|
||||
"pm" = "dynamic";
|
||||
"php_admin_value[error_log]" = "stderr";
|
||||
"php_admin_flag[log_errors]" = true;
|
||||
"catch_workers_output" = true;
|
||||
"pm.max_children" = "32";
|
||||
"pm.start_servers" = "2";
|
||||
"pm.min_spare_servers" = "2";
|
||||
"pm.max_spare_servers" = "4";
|
||||
"pm.max_requests" = "500";
|
||||
};
|
||||
|
||||
services.phpfpm.pools.pixelfed = {
|
||||
inherit user group;
|
||||
inherit phpPackage;
|
||||
|
||||
phpOptions = ''
|
||||
post_max_size = ${toString cfg.maxUploadSize}
|
||||
upload_max_filesize = ${toString cfg.maxUploadSize}
|
||||
max_execution_time = 600;
|
||||
'';
|
||||
|
||||
settings = {
|
||||
"listen.owner" = user;
|
||||
"listen.group" = group;
|
||||
"listen.mode" = "0660";
|
||||
"catch_workers_output" = "yes";
|
||||
} // cfg.poolConfig;
|
||||
};
|
||||
|
||||
systemd.services.phpfpm-pixelfed.after = [ "pixelfed-data-setup.service" ];
|
||||
systemd.services.phpfpm-pixelfed.requires =
|
||||
[ "pixelfed-horizon.service" "pixelfed-data-setup.service" ]
|
||||
++ lib.optional cfg.database.createLocally dbService
|
||||
++ lib.optional cfg.redis.createLocally redisService;
|
||||
# Ensure image optimizations programs are available.
|
||||
systemd.services.phpfpm-pixelfed.path = extraPrograms;
|
||||
|
||||
systemd.services.pixelfed-horizon = {
|
||||
description = "Pixelfed task queueing via Laravel Horizon framework";
|
||||
after = [ "network.target" "pixelfed-data-setup.service" ];
|
||||
requires = [ "pixelfed-data-setup.service" ]
|
||||
++ (lib.optional cfg.database.createLocally dbService)
|
||||
++ (lib.optional cfg.redis.createLocally redisService);
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# Ensure image optimizations programs are available.
|
||||
path = extraPrograms;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pixelfed-manage}/bin/pixelfed-manage horizon";
|
||||
StateDirectory =
|
||||
lib.mkIf (cfg.dataDir == "/var/lib/pixelfed") "pixelfed";
|
||||
User = user;
|
||||
Group = group;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.pixelfed-cron = {
|
||||
description = "Pixelfed periodic tasks timer";
|
||||
after = [ "pixelfed-data-setup.service" ];
|
||||
requires = [ "phpfpm-pixelfed.service" ];
|
||||
wantedBy = [ "timers.target" ];
|
||||
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.schedulerInterval;
|
||||
OnUnitActiveSec = cfg.schedulerInterval;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.pixelfed-cron = {
|
||||
description = "Pixelfed periodic tasks";
|
||||
# Ensure image optimizations programs are available.
|
||||
path = extraPrograms;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${pixelfed-manage}/bin/pixelfed-manage schedule:run";
|
||||
User = user;
|
||||
Group = group;
|
||||
StateDirectory = cfg.dataDir;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.pixelfed-data-setup = {
|
||||
description =
|
||||
"Pixelfed setup: migrations, environment file update, cache reload, data changes";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = lib.optional cfg.database.createLocally dbService;
|
||||
requires = lib.optional cfg.database.createLocally dbService;
|
||||
path = with pkgs; [ bash pixelfed-manage rsync ] ++ extraPrograms;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
Group = group;
|
||||
StateDirectory =
|
||||
lib.mkIf (cfg.dataDir == "/var/lib/pixelfed") "pixelfed";
|
||||
LoadCredential = "env-secrets:${cfg.secretFile}";
|
||||
UMask = "077";
|
||||
};
|
||||
|
||||
script = ''
|
||||
# Concatenate non-secret .env and secret .env
|
||||
rm -f ${cfg.dataDir}/.env
|
||||
cp --no-preserve=all ${configFile} ${cfg.dataDir}/.env
|
||||
echo -e '\n' >> ${cfg.dataDir}/.env
|
||||
cat "$CREDENTIALS_DIRECTORY/env-secrets" >> ${cfg.dataDir}/.env
|
||||
|
||||
# Link the static storage (package provided) to the runtime storage
|
||||
# Necessary for cities.json and static images.
|
||||
mkdir -p ${cfg.dataDir}/storage
|
||||
rsync -av --no-perms ${pixelfed}/storage-static/ ${cfg.dataDir}/storage
|
||||
chmod -R +w ${cfg.dataDir}/storage
|
||||
|
||||
# Link the app.php in the runtime folder.
|
||||
# We cannot link the cache folder only because bootstrap folder needs to be writeable.
|
||||
ln -sf ${pixelfed}/bootstrap-static/app.php ${cfg.runtimeDir}/app.php
|
||||
|
||||
# https://laravel.com/docs/10.x/filesystem#the-public-disk
|
||||
# Creating the public/storage → storage/app/public link
|
||||
# is unnecessary as it's part of the installPhase of pixelfed.
|
||||
|
||||
# Install Horizon
|
||||
# FIXME: require write access to public/ — should be done as part of install — pixelfed-manage horizon:publish
|
||||
|
||||
# Before running any PHP program, cleanup the bootstrap.
|
||||
# It's necessary if you upgrade the application otherwise you might
|
||||
# try to import non-existent modules.
|
||||
rm -rf ${cfg.runtimeDir}/bootstrap/*
|
||||
|
||||
# Perform the first migration.
|
||||
[[ ! -f ${cfg.dataDir}/.initial-migration ]] && pixelfed-manage migrate --force && touch ${cfg.dataDir}/.initial-migration
|
||||
|
||||
${lib.optionalString cfg.database.automaticMigrations ''
|
||||
# Force migrate the database.
|
||||
pixelfed-manage migrate --force
|
||||
''}
|
||||
|
||||
# Import location data
|
||||
pixelfed-manage import:cities
|
||||
|
||||
${lib.optionalString cfg.settings.ACTIVITY_PUB ''
|
||||
# ActivityPub federation bookkeeping
|
||||
[[ ! -f ${cfg.dataDir}/.instance-actor-created ]] && pixelfed-manage instance:actor && touch ${cfg.dataDir}/.instance-actor-created
|
||||
''}
|
||||
|
||||
${lib.optionalString cfg.settings.OAUTH_ENABLED ''
|
||||
# Generate Passport encryption keys
|
||||
[[ ! -f ${cfg.dataDir}/.passport-keys-generated ]] && pixelfed-manage passport:keys && touch ${cfg.dataDir}/.passport-keys-generated
|
||||
''}
|
||||
|
||||
pixelfed-manage route:cache
|
||||
pixelfed-manage view:cache
|
||||
pixelfed-manage config:cache
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
# Cache must live across multiple systemd units runtimes.
|
||||
"d ${cfg.runtimeDir}/ 0700 ${user} ${group} - -"
|
||||
"d ${cfg.runtimeDir}/cache 0700 ${user} ${group} - -"
|
||||
];
|
||||
|
||||
# Enable NGINX to access our phpfpm-socket.
|
||||
users.users."${config.services.nginx.group}".extraGroups = [ cfg.group ];
|
||||
services.nginx = mkIf (cfg.nginx != null) {
|
||||
enable = true;
|
||||
virtualHosts."${cfg.domain}" = mkMerge [
|
||||
cfg.nginx
|
||||
{
|
||||
root = lib.mkForce "${pixelfed}/public/";
|
||||
locations."/".tryFiles = "$uri $uri/ /index.php?query_string";
|
||||
locations."/favicon.ico".extraConfig = ''
|
||||
access_log off; log_not_found off;
|
||||
'';
|
||||
locations."/robots.txt".extraConfig = ''
|
||||
access_log off; log_not_found off;
|
||||
'';
|
||||
locations."~ \\.php$".extraConfig = ''
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.pixelfed.socket};
|
||||
fastcgi_index index.php;
|
||||
'';
|
||||
locations."~ /\\.(?!well-known).*".extraConfig = ''
|
||||
deny all;
|
||||
'';
|
||||
extraConfig = ''
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Content-Type-Options "nosniff";
|
||||
index index.html index.htm index.php;
|
||||
error_page 404 /index.php;
|
||||
client_max_body_size ${toString cfg.maxUploadSize};
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue