Project import generated by Copybara.

GitOrigin-RevId: 2893f56de08021cffd9b6b6dfc70fd9ccd51eb60
This commit is contained in:
Default email 2024-06-24 14:47:55 -04:00
parent 56bae7e5ef
commit 83627f9931
1153 changed files with 33764 additions and 11428 deletions

View file

@ -67,6 +67,9 @@
/nixos/lib/make-disk-image.nix @raitobezarius
# Nix, the package manager
# @raitobezarius is not "code owner", but is listed here to be notified of changes
# pertaining to the Nix package manager.
# i.e. no authority over those files.
pkgs/tools/package-management/nix/ @raitobezarius
nixos/modules/installer/tools/nix-fallback-paths.nix @raitobezarius
@ -93,7 +96,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @raitobezarius
/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
@ -137,9 +139,9 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @raitobezarius
/pkgs/top-level/haskell-packages.nix @sternenseemann @maralorn @ncfavier
# Perl
/pkgs/development/interpreters/perl @stigtsp @zakame @dasJ @marcusramberg
/pkgs/top-level/perl-packages.nix @stigtsp @zakame @dasJ @marcusramberg
/pkgs/development/perl-modules @stigtsp @zakame @dasJ @marcusramberg
/pkgs/development/interpreters/perl @stigtsp @zakame @marcusramberg
/pkgs/top-level/perl-packages.nix @stigtsp @zakame @marcusramberg
/pkgs/development/perl-modules @stigtsp @zakame @marcusramberg
# R
/pkgs/applications/science/math/R @jbedo
@ -152,6 +154,7 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @raitobezarius
# C compilers
/pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @RossComputerGuy
/pkgs/development/compilers/emscripten @raitobezarius
/doc/languages-frameworks/emscripten.section.md @raitobezarius
@ -363,3 +366,16 @@ pkgs/by-name/lx/lxc* @adamcstephens
pkgs/by-name/lx/lxd* @adamcstephens
pkgs/os-specific/linux/lxc/ @adamcstephens
# ExpidusOS, Flutter
/pkgs/development/compilers/flutter @RossComputerGuy
/pkgs/desktops/expidus @RossComputerGuy
# GNU Tar & Zip
/pkgs/tools/archivers/gnutar @RossComputerGuy
/pkgs/tools/archivers/zip @RossComputerGuy
# SELinux
/pkgs/os-specific/linux/checkpolicy @RossComputerGuy
/pkgs/os-specific/linux/libselinux @RossComputerGuy
/pkgs/os-specific/linux/libsepol @RossComputerGuy

View file

@ -9,22 +9,40 @@ pkgs.makeSetupHook {
name = "something-hook";
propagatedBuildInputs = [ pkgs.commandsomething ];
depsTargetTargetPropagated = [ pkgs.libsomething ];
} ./script.sh
} ./script.sh;
```
### setup hook that depends on the hello package and runs hello and @shell@ is substituted with path to bash {#sec-pkgs.makeSetupHook-usage-example}
```nix
pkgs.makeSetupHook {
pkgs.makeSetupHook
{
name = "run-hello-hook";
propagatedBuildInputs = [ pkgs.hello ];
substitutions = { shell = "${pkgs.bash}/bin/bash"; };
passthru.tests.greeting = callPackage ./test { };
meta.platforms = lib.platforms.linux;
} (writeScript "run-hello-hook.sh" ''
# Put dependencies here if they have hooks or necessary dependencies propagated
# otherwise prefer direct paths to executables.
propagatedBuildInputs = [
pkgs.hello
pkgs.cowsay
];
substitutions = {
shell = "${pkgs.bash}/bin/bash";
cowsay = "${pkgs.cowsay}/bin/cowsay";
};
}
(
writeScript "run-hello-hook.sh" ''
#!@shell@
# the direct path to the executable has to be here because
# this will be run when the file is sourced
# at which point '$PATH' has not yet been populated with inputs
@cowsay@ cow
_printHelloHook() {
hello
'')
}
preConfigureHooks+=(_printHelloHook)
''
);
```
## Attributes {#sec-pkgs.makeSetupHook-attributes}

View file

@ -101,7 +101,7 @@ See the [Dart documentation](#ssec-dart-applications) for more details on requir
`flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter319` and `flutter322`, instead of using `flutter` directly.
```nix
{ flutter, fetchFromGitHub }:
{ flutter322, fetchFromGitHub }:
flutter322.buildFlutterApplication {
pname = "firmware-updater";

View file

@ -120,14 +120,6 @@ buildDunePackage rec {
}
```
Note about `minimalOCamlVersion`. A deprecated version of this argument was
spelled `minimumOCamlVersion`; setting the old attribute wrongly modifies the
derivation hash and is therefore inappropriate. As a technical dept, currently
packaged libraries may still use the old spelling: maintainers are invited to
fix this when updating packages. Massive renaming is strongly discouraged as it
would be challenging to review, difficult to test, and will cause unnecessary
rebuild.
The build will automatically fail if two distinct versions of the same library
are added to `buildInputs` (which usually happens transitively because of
`propagatedBuildInputs`). Set `dontDetectOcamlConflicts` to true to disable this

View file

@ -214,7 +214,7 @@ Note: this is not possible anymore for Neovim.
Nix expressions for Vim plugins are stored in [pkgs/applications/editors/vim/plugins](https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/editors/vim/plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`nix-shell -p vimPluginsUpdater --run vim-plugins-updater`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/updater.nix). This creates a [generated.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/vim-plugin-names).
After running the updater, if nvim-treesitter received an update, also run [`nvim-treesitter/update.py`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/update.py) to update the tree sitter grammars for `nvim-treesitter`.
When the vim updater detects an nvim-treesitter update, it also runs [`nvim-treesitter/update.py $(nix-build -A vimPlugins.nvim-treesitter)`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/update.py) to update the tree sitter grammars for `nvim-treesitter`.
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/vim/plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:

View file

@ -11,7 +11,7 @@ let
in
rec {
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs intersectAttrs;
/**

View file

@ -64,22 +64,21 @@ let
# linux kernel configuration
kernel = callLibs ./kernel.nix;
inherit (builtins) add addErrorContext attrNames concatLists
deepSeq elem elemAt filter genericClosure genList getAttr
hasAttr head isAttrs isBool isInt isList isPath isString length
lessThan listToAttrs pathExists readFile replaceStrings seq
stringLength sub substring tail trace;
# TODO: For consistency, all builtins should also be available from a sub-library;
# these are the only ones that are currently not
inherit (builtins) addErrorContext isPath trace;
inherit (self.trivial) id const pipe concat or and xor bitAnd bitOr bitXor
bitNot boolToString mergeAttrs flip mapNullable inNixShell isFloat min max
importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum
info showWarnings nixpkgsVersion version isInOldestRelease
mod compare splitByAndCompare
mod compare splitByAndCompare seq deepSeq lessThan add sub
functionArgs setFunctionArgs isFunction toFunction mirrorFunctionArgs
toHexString toBaseDigits inPureEvalMode;
toHexString toBaseDigits inPureEvalMode isBool isInt pathExists
genericClosure readFile;
inherit (self.fixedPoints) fix fix' converge extends composeExtensions
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
getAttrFromPath attrVals attrNames attrValues getAttrs catAttrs filterAttrs
filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs
mapAttrs' mapAttrsToList attrsToList concatMapAttrs mapAttrsRecursive
mapAttrsRecursiveCond genAttrs isDerivation toDerivation optionalAttrs
@ -87,14 +86,16 @@ let
recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets
mapCartesianProduct updateManyAttrsByPath;
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
ifilter0 concatMap flatten remove findSingle findFirst any all count
mapCartesianProduct updateManyAttrsByPath listToAttrs hasAttr getAttr isAttrs intersectAttrs removeAttrs;
inherit (self.lists) singleton forEach map foldr fold foldl foldl' imap0 imap1
filter ifilter0 concatMap flatten remove findSingle findFirst any all count
optional optionals toList range replicate partition zipListsWith zipLists
reverseList listDfs toposort sort sortOn naturalSort compareLists take
drop sublist last init crossLists unique allUnique intersectLists
subtractLists mutuallyExclusive groupBy groupBy';
subtractLists mutuallyExclusive groupBy groupBy' concatLists genList
length head tail elem elemAt isList;
inherit (self.strings) concatStrings concatMapStrings concatImapStrings
stringLength substring isString replaceStrings
intersperse concatStringsSep concatMapStringsSep
concatImapStringsSep concatLines makeSearchPath makeSearchPathOutput
makeLibraryPath makeIncludePath makeBinPath optionalString
@ -105,7 +106,7 @@ let
escapeRegex escapeURL escapeXML replaceChars lowerChars
upperChars toLower toUpper addContextFrom splitString
removePrefix removeSuffix versionOlder versionAtLeast
getName getVersion
getName getVersion match split
cmakeOptionType cmakeBool cmakeFeature
mesonOption mesonBool mesonEnable
nameFromURL enableFeature enableFeatureAs withFeature

View file

@ -530,6 +530,13 @@ in mkLicense lset) ({
fullName = "Unspecified free software license";
};
fsl11Mit = {
fullName = "Functional Source License, Version 1.1, MIT Future License";
url = "https://fsl.software/FSL-1.1-MIT.template.md";
free = false;
redistributable = true;
};
ftl = {
spdxId = "FTL";
fullName = "Freetype Project License";
@ -1278,11 +1285,21 @@ in mkLicense lset) ({
fullName = "xinetd License";
};
xskat = {
spdxId = "XSkat";
fullName = "XSkat License";
};
zlib = {
spdxId = "Zlib";
fullName = "zlib License";
};
zsh = {
url = "https://github.com/zsh-users/zsh/blob/master/LICENCE";
fulllName = "Zsh License";
};
zpl20 = {
spdxId = "ZPL-2.0";
fullName = "Zope Public License 2.0";
@ -1293,10 +1310,6 @@ in mkLicense lset) ({
fullName = "Zope Public License 2.1";
};
xskat = {
spdxId = "XSkat";
fullName = "XSkat License";
};
} // {
# TODO: remove legacy aliases
apsl10 = {

View file

@ -60,23 +60,23 @@ rec {
armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi";
rust.rustcTarget = "armv7-linux-androideabi";
sdkVer = "28";
ndkVer = "24";
sdkVer = "33";
ndkVer = "26";
useAndroidPrebuilt = true;
} // platforms.armv7a-android;
aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android";
rust.rustcTarget = "aarch64-linux-android";
sdkVer = "28";
ndkVer = "24";
sdkVer = "33";
ndkVer = "26";
useAndroidPrebuilt = true;
};
aarch64-android = {
config = "aarch64-unknown-linux-android";
sdkVer = "30";
ndkVer = "24";
sdkVer = "33";
ndkVer = "26";
libc = "bionic";
useAndroidPrebuilt = false;
useLLVM = true;

View file

@ -1551,12 +1551,6 @@
githubId = 56009;
name = "Arcadio Rubio García";
};
arcayr = {
email = "nix@arcayr.online";
github = "arcayr";
githubId = 11192354;
name = "Elliot Speck";
};
archer-65 = {
email = "mario.liguori.056@gmail.com";
github = "archer-65";
@ -1983,6 +1977,12 @@
githubId = 12958979;
name = "Mika Naylor";
};
autra = {
email = "augustin.trancart@gmail.com";
github = "autra";
githubId = 1576598;
name = "Augustin Trancart";
};
autrimpo = {
email = "michal@koutensky.net";
github = "autrimpo";
@ -3962,6 +3962,12 @@
githubId = 40290417;
name = "Seb Blair";
};
CompileTime = {
email = "socialcoms@posteo.de";
github = "Compile-Time";
githubId = 18414241;
name = "Andreas Erdes";
};
confus = {
email = "con-f-use@gmx.net";
github = "con-f-use";
@ -6506,6 +6512,18 @@
githubId = 8182846;
name = "Francesco Gazzetta";
};
fidgetingbits = {
name = "fidgetingbits";
email = "nixpkgs.xe7au@passmail.net";
matrix = "@fidgetingbits:matrix.org";
github = "fidgetingbits";
githubId = 13679876;
keys = [
{ fingerprint = "U+vNNrQxJRj3NPu9EoD0LFZssRbk6LBg4YPN5nFvQvs"; }
{ fingerprint = "lX5ewVcaQLxuzqI92gujs3jFNki4d8qF+PATexMijoQ"; }
{ fingerprint = "elY15tXap1tddxbBVoUoAioe1u0RDWti5rc9cauSmwo"; }
];
};
figsoda = {
email = "figsoda@pm.me";
matrix = "@figsoda:matrix.org";
@ -6812,6 +6830,14 @@
matrix = "@frogamic:beeper.com";
keys = [ { fingerprint = "779A 7CA8 D51C C53A 9C51 43F7 AAE0 70F0 67EC 00A5"; } ];
};
frontear = {
name = "Ali Rizvi";
email = "perm-iterate-0b@icloud.com";
matrix = "@frontear:matrix.org";
github = "Frontear";
githubId = 31909298;
keys = [ { fingerprint = "C170 11B7 C0AA BB3F 7415 022C BCB5 CEFD E222 82F5"; } ];
};
frontsideair = {
email = "photonia@gmail.com";
github = "frontsideair";
@ -7373,12 +7399,6 @@
github = "gmacon";
githubId = 238853;
};
gmemstr = {
email = "git@gmem.ca";
github = "gmemstr";
githubId = 1878840;
name = "Gabriel Simmer";
};
gnxlxnxx = {
email = "gnxlxnxx@web.de";
github = "gnxlxnxx";
@ -8399,6 +8419,12 @@
githubId = 7403236;
name = "Markus J. Ankenbrand";
};
iivusly = {
email = "iivusly@icloud.com";
github = "iivusly";
githubId = 52052910;
name = "iivusly";
};
ikervagyok = {
email = "ikervagyok@gmail.com";
github = "ikervagyok";
@ -9822,6 +9848,11 @@
githubId = 1918771;
name = "Joe Doyle";
};
jpds = {
github = "jpds";
githubId = 29158971;
name = "Jonathan Davies";
};
jpentland = {
email = "joe.pentland@gmail.com";
github = "jpentland";
@ -9957,6 +9988,12 @@
githubId = 5802758;
name = "Joshua Trees";
};
jtszalay = {
email = "jamestszalay@gmail.com";
github = "jtszalay";
githubId = 589502;
name = "James Szalay";
};
juancmuller = {
email = "nix@juancmuller.com";
githubId = 208500;
@ -10574,13 +10611,6 @@
name = "Kat Inskip";
keys = [ { fingerprint = "9CC6 44B5 69CD A59B C874 C4C9 E8DD E3ED 1C90 F3A0"; } ];
};
kiwi = {
email = "envy1988@gmail.com";
github = "Kiwi";
githubId = 35715;
name = "Robert Djubek";
keys = [ { fingerprint = "8992 44FC D291 5CA2 0A97 802C 156C 88A5 B0A0 4B2A"; } ];
};
kjeremy = {
email = "kjeremy@gmail.com";
name = "Jeremy Kolb";
@ -10593,6 +10623,11 @@
github = "kkharji";
githubId = 65782666;
};
kkoniuszy = {
name = "Kacper Koniuszy";
github = "kkoniuszy";
githubId = 120419423;
};
klden = {
name = "Kenzyme Le";
email = "kl@kenzymele.com";
@ -11297,12 +11332,6 @@
github = "LogicalOverflow";
githubId = 5919957;
};
lheckemann = {
email = "git@sphalerite.org";
github = "lheckemann";
githubId = 341954;
name = "Linus Heckemann";
};
lhvwb = {
email = "nathaniel.baxter@gmail.com";
github = "nathanielbaxter";
@ -11635,6 +11664,13 @@
githubId = 10626;
name = "Andreas Wagner";
};
lpchaim = {
email = "lpchaim@gmail.comm";
matrix = "@lpchaim:matrix.org";
github = "lpchaim";
githubId = 4030336;
name = "Lucas Chaim";
};
lpostula = {
email = "lois@postu.la";
github = "loispostula";
@ -13137,6 +13173,12 @@
githubId = 3269878;
name = "Miguel Madrid Mencía";
};
mimvoid = {
github = "mimvoid";
githubId = 153698678;
email = "mimvoid@proton.me";
name = "mimvoid";
};
mindavi = {
email = "rol3517@gmail.com";
github = "Mindavi";
@ -13413,14 +13455,6 @@
githubId = 754512;
name = "Mogria";
};
mohe2015 = {
name = "Moritz Hedtke";
email = "Moritz.Hedtke@t-online.de";
matrix = "@moritz.hedtke:matrix.org";
github = "mohe2015";
githubId = 13287984;
keys = [ { fingerprint = "1248 D3E1 1D11 4A85 75C9 8934 6794 D45A 488C 2EDE"; } ];
};
momeemt = {
name = "Mutsuha Asada";
email = "me@momee.mt";
@ -15196,6 +15230,12 @@
githubId = 79252025;
name = "Nicolas Benes";
};
panky = {
email = "dev@pankajraghav.com";
github = "Panky-codes";
githubId = 33182938;
name = "Pankaj";
};
paperdigits = {
email = "mica@silentumbrella.com";
github = "paperdigits";
@ -15798,6 +15838,12 @@
githubId = 4303706;
keys = [ { fingerprint = "B00F E582 FD3F 0732 EA48 3937 F558 14E4 D687 4375"; } ];
};
pladypus = {
name = "Peter Loftus";
email = "loftusp5976+nixpkgs@gmail.com";
github = "pladypus";
githubId = 56337621;
};
plchldr = {
email = "mail@oddco.de";
github = "plchldr";
@ -17688,13 +17734,6 @@
githubId = 226872;
name = "Samuel Ainsworth";
};
samueldr = {
email = "samuel@dionne-riel.com";
matrix = "@samueldr:matrix.org";
github = "samueldr";
githubId = 132835;
name = "Samuel Dionne-Riel";
};
samuelefacenda = {
name = "Samuele Facenda";
email = "samuele.facenda@gmail.com";
@ -18798,14 +18837,6 @@
githubId = 53029739;
name = "Joshua Ortiz";
};
Sorixelle = {
email = "ruby+nixpkgs@srxl.me";
matrix = "@ruby:isincredibly.gay";
name = "Ruby Iris Juric";
github = "Sorixelle";
githubId = 38685302;
keys = [ { fingerprint = "2D76 76C7 A28E 16FC 75C7 268D 1B55 6ED8 4B0E 303A"; } ];
};
sorki = {
email = "srk@48.io";
github = "sorki";
@ -19535,6 +19566,12 @@
githubId = 870673;
name = "Takuo Yonezawa";
};
TakWolf = {
email = "takwolf@foxmail.com";
github = "TakWolf";
githubId = 6064962;
name = "TakWolf";
};
talkara = {
email = "taito.horiuchi@relexsolutions.com";
github = "talkara";
@ -20025,12 +20062,6 @@
githubId = 1391883;
name = "Tom Hall";
};
thubrecht = {
email = "tom@hubrecht.ovh";
github = "Tom-Hubrecht";
githubId = 26650391;
name = "Tom Hubrecht";
};
Thunderbottom = {
email = "chinmaydpai@gmail.com";
github = "Thunderbottom";
@ -21561,12 +21592,6 @@
githubId = 11740700;
name = "Andrei Pampu";
};
wolfangaukang = {
email = "clone.gleeful135+nixpkgs@anonaddy.me";
github = "WolfangAukang";
githubId = 8378365;
name = "P. R. d. O.";
};
wolfgangwalther = {
name = "Wolfgang Walther";
email = "walther@technowledgy.de";

View file

@ -677,12 +677,6 @@ with lib.maintainers;
shortName = "Mercury Employees";
};
mobile = {
members = [ samueldr ];
scope = "Maintain Mobile NixOS.";
shortName = "Mobile";
};
nix = {
members = [
eelco

View file

@ -453,7 +453,7 @@ In addition to numerous new and upgraded packages, this release has the followin
The new names are as follows:
- `bindAddress`: [`services.keycloak.settings.http-host`](#opt-services.keycloak.settings.http-host)
- `forceBackendUrlToFrontendUrl`: [`services.keycloak.settings.hostname-strict-backchannel`](#opt-services.keycloak.settings.hostname-strict-backchannel)
- `forceBackendUrlToFrontendUrl`: `services.keycloak.settings.hostname-strict-backchannel`
- `httpPort`: [`services.keycloak.settings.http-port`](#opt-services.keycloak.settings.http-port)
- `httpsPort`: [`services.keycloak.settings.https-port`](#opt-services.keycloak.settings.https-port)

View file

@ -62,7 +62,7 @@ In addition to numerous new and upgraded packages, this release has the followin
<!-- Please keep entries alphabetically sorted. -->
- [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server software.
The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the ankisyncd software.
- [ALVR](https://github.com/alvr-org/alvr), a VR desktop streamer. Available as [programs.alvr](#opt-programs.alvr.enable).

View file

@ -23,13 +23,35 @@
## Backward Incompatibilities {#sec-release-24.11-incompatibilities}
- `transmission` package has been aliased with a `trace` warning to `transmission_3`. Since [Transmission 4 has been released last year](https://github.com/transmission/transmission/releases/tag/4.0.0), and Transmission 3 will eventually go away, it was decided perform this warning alias to make people aware of the new version. The `services.transmission.package` defaults to `transmission_3` as well because the upgrade can cause data loss in certain specific usage patterns (examples: [#5153](https://github.com/transmission/transmission/issues/5153), [#6796](https://github.com/transmission/transmission/issues/6796)). Please make sure to back up to your data directory per your usage:
- `transmission-gtk`: `~/.config/transmission`
- `transmission-daemon` using NixOS module: `${config.services.transmission.home}/.config/transmission-daemon` (defaults to `/var/lib/transmission/.config/transmission-daemon`)
- `androidenv.androidPkgs_9_0` has been removed, and replaced with `androidenv.androidPkgs` for a more complete Android SDK including support for Android 9 and later.
- `wstunnel` has had a major version upgrade that entailed rewriting the program in Rust.
The module was updated to accommodate for breaking changes.
Breaking changes to the module API were minimised as much as possible,
but some were nonetheless inevitable due to changes in the upstream CLI.
Certain options were moved from separate CLI arguments into the forward specifications,
and those options were also removed from the module's API,
please consult the wstunnel man page for more detail.
Also be aware that if you have set additional options in `services.wstunnel.{clients,servers}.<name>.extraArgs`,
that those might have been removed or modified upstream.
- `clang-tools_<version>` packages have been moved into `llvmPackages_<version>` (i.e. `clang-tools_18` is now `llvmPackages_18.clang-tools`).
- For convenience, the top-level `clang-tools` attribute remains and is now bound to `llvmPackages.clang-tools`.
- Top-level `clang_tools_<version>` attributes are now aliases; these will be removed in a future release.
- `nginx` package no longer includes `gd` and `geoip` dependencies. For enabling it, override `nginx` package with the optionals `withImageFilter` and `withGeoIP`.
- `openssh` and `openssh_hpn` are now compiled without Kerberos 5 / GSSAPI support in an effort to reduce the attack surface of the components for the majority of users. Users needing this support can
use the new `opensshWithKerberos` and `openssh_hpnWithKerberos` flavors (e.g. `programs.ssh.package = pkgs.openssh_gssapi`).
- `security.ipa.ipaHostname` now defaults to the value of `networking.fqdn` if
it is set, instead of the previous hardcoded default of
`${networking.hostName}.${security.ipa.domain}`.
- `nvimpager` was updated to version 0.13.0, which changes the order of user and
nvimpager settings: user commands in `-c` and `--cmd` now override the
respective default settings because they are executed later.
@ -53,6 +75,10 @@
before changing the package to `pkgs.stalwart-mail` in
[`services.stalwart-mail.package`](#opt-services.stalwart-mail.package).
- `androidndkPkgs` has been updated to `androidndkPkgs_26`.
- Android NDK version 26 and SDK version 33 are now the default versions used for cross compilation to android.
- `haskell.lib.compose.justStaticExecutables` now disallows references to GHC in the
output by default, to alert users to closure size issues caused by
[#164630](https://github.com/NixOS/nixpkgs/issues/164630). See ["Packaging
@ -61,10 +87,19 @@
for information on working around `output '...' is not allowed to refer to
the following paths` errors caused by this change.
- The `stalwart-mail` service now runs under the `stalwart-mail` system user
instead of a dynamically created one via `DynamicUser`, to avoid automatic
ownership changes on its large file store each time the service was started.
This change requires to manually move the state directory from
`/var/lib/private/stalwart-mail` to `/var/lib/stalwart-mail` and to
change the ownership of the directory and its content to `stalwart-mail`.
- The `stalwart-mail` module now uses RocksDB as the default storage backend
for `stateVersion` ≥ 24.11. (It was previously using SQLite for structured
data and the filesystem for blobs).
- `libe57format` has been updated to `>= 3.0.0`, which contains some backward-incompatible API changes. See the [release note](https://github.com/asmaloney/libE57Format/releases/tag/v3.0.0) for more details.
- `zx` was updated to v8, which introduces several breaking changes.
See the [v8 changelog](https://github.com/google/zx/releases/tag/8.0.0) for more information.
@ -77,6 +112,9 @@
services.portunus.ldap.package = pkgs.openldap.override { libxcrypt = pkgs.libxcrypt-legacy; };
```
- `keycloak` was updated to version 25, which introduces new hostname related options.
See [Upgrading Guide](https://www.keycloak.org/docs/25.0.1/upgrading/#migrating-to-25-0-0) for instructions.
- The `tracy` package no longer works on X11, since it's moved to Wayland
support, which is the intended default behavior by Tracy maintainers.
X11 users have to switch to the new package `tracy-x11`.

View file

@ -603,10 +603,11 @@ let format' = format; in let
${lib.optionalString installBootLoader ''
# In this throwaway resource, we only have /dev/vda, but the actual VM may refer to another disk for bootloader, e.g. /dev/vdb
# Use this option to create a symlink from vda to any arbitrary device you want.
${optionalString (config.boot.loader.grub.enable && config.boot.loader.grub.device != "/dev/vda") ''
mkdir -p $(dirname ${config.boot.loader.grub.device})
ln -s /dev/vda ${config.boot.loader.grub.device}
''}
${optionalString (config.boot.loader.grub.enable) (lib.concatMapStringsSep " " (device:
lib.optionalString (device != "/dev/vda") ''
mkdir -p "$(dirname ${device})"
ln -s /dev/vda ${device}
'') config.boot.loader.grub.devices)}
# Set up core system link, bootloader (sd-boot, GRUB, uboot, etc.), etc.

View file

@ -275,7 +275,6 @@ in
chattr +C "$DEVICE" 2>/dev/null || true
dd if=/dev/zero of="$DEVICE" bs=1M count=${toString sw.size}
chmod 0600 ${sw.device}
${optionalString (!sw.randomEncryption.enable) "mkswap ${sw.realDevice}"}
fi
''}
@ -292,9 +291,12 @@ in
unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
unitConfig.DefaultDependencies = false; # needed to prevent a cycle
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = sw.randomEncryption.enable;
serviceConfig.ExecStop = optionalString sw.randomEncryption.enable "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = sw.randomEncryption.enable;
UMask = "0177";
ExecStop = optionalString sw.randomEncryption.enable "${pkgs.cryptsetup}/bin/cryptsetup luksClose ${sw.deviceName}";
};
restartIfChanged = false;
};

View file

@ -1,7 +1,7 @@
{
x86_64-linux = "/nix/store/azvn85cras6xv4z5j85fiy406f24r1q0-nix-2.18.1";
i686-linux = "/nix/store/9bnwy7f9h0kzdzmcnjjsjg0aak5waj40-nix-2.18.1";
aarch64-linux = "/nix/store/hh65xwqm9s040s3cgn9vzcmrxj0sf5ij-nix-2.18.1";
x86_64-darwin = "/nix/store/6zi5fqzn9n17wrk8r41rhdw4j7jqqsi3-nix-2.18.1";
aarch64-darwin = "/nix/store/0pbq6wzr2f1jgpn5212knyxpwmkjgjah-nix-2.18.1";
x86_64-linux = "/nix/store/yrsmzlw2lgbknzwic1gy1gmv3l2w1ax8-nix-2.18.3";
i686-linux = "/nix/store/ds9381l9mlwfaclvqnkzn3jl4qb8m3y1-nix-2.18.3";
aarch64-linux = "/nix/store/hw1zny3f8520zyskmp1qaybv1ir5ilxh-nix-2.18.3";
x86_64-darwin = "/nix/store/z08yc4sl1fr65q53wz6pw30h67qafaln-nix-2.18.3";
aarch64-darwin = "/nix/store/p57m7m0wrz8sqxiwinzpwzqzak82zn75-nix-2.18.3";
}

View file

@ -880,6 +880,7 @@
./services/monitoring/osquery.nix
./services/monitoring/parsedmarc.nix
./services/monitoring/prometheus/alertmanager-irc-relay.nix
./services/monitoring/prometheus/alertmanager-webhook-logger.nix
./services/monitoring/prometheus/alertmanager.nix
./services/monitoring/prometheus/default.nix
./services/monitoring/prometheus/exporters.nix

View file

@ -63,7 +63,7 @@ in
systemd = lib.mkIf cfg.systemd.setPath.enable {
user.extraConfig = ''
DefaultEnvironment="PATH=$PATH:/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin:/run/wrappers/bin"
DefaultEnvironment="PATH=/run/wrappers/bin:/etc/profiles/per-user/%u/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:$PATH"
'';
};
}

View file

@ -23,7 +23,7 @@ in
};
package = lib.mkPackageOption pkgs "xonsh" {
example = "xonsh.override { extraPackages = ps: [ ps.requests ]; }";
example = "xonsh.wrapper.override { extraPackages = ps: [ ps.requests ]; }";
};
config = lib.mkOption {
@ -61,17 +61,14 @@ in
aliases['ls'] = _ls_alias
del _ls_alias
${cfg.config}
'';
environment.systemPackages = [ cfg.package ];
environment.shells =
[ "/run/current-system/sw/bin/xonsh"
"${cfg.package}/bin/xonsh"
environment.shells = [
"/run/current-system/sw/bin/xonsh"
"${lib.getExe cfg.package}"
];
};
}

View file

@ -85,6 +85,18 @@ in {
description = "Whether to cache credentials.";
};
ipaHostname = mkOption {
type = types.str;
example = "myworkstation.example.com";
default = if config.networking.domain != null then config.networking.fqdn
else "${config.networking.hostName}.${cfg.domain}";
defaultText = literalExpression ''
if config.networking.domain != null then config.networking.fqdn
else "''${networking.hostName}.''${security.ipa.domain}"
'';
description = "Fully-qualified hostname used to identify this host in the IPA domain.";
};
ifpAllowedUids = mkOption {
type = types.listOf types.str;
default = ["root"];
@ -218,7 +230,7 @@ in {
ipa_domain = ${cfg.domain}
ipa_server = _srv_, ${cfg.server}
ipa_hostname = ${config.networking.hostName}.${cfg.domain}
ipa_hostname = ${cfg.ipaHostname}
cache_credentials = ${pyBool cfg.cacheCredentials}
krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords}
@ -232,7 +244,6 @@ in {
ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock
[sssd]
debug_level = 65510
services = nss, sudo, pam, ssh, ifp
domains = ${cfg.domain}
@ -244,7 +255,6 @@ in {
pam_verbosity = 3
[sudo]
debug_level = 65510
[autofs]

View file

@ -42,5 +42,5 @@ in with lib; {
};
};
};
meta.maintainers = [ maintainers.lheckemann ];
meta.maintainers = [ ];
}

View file

@ -261,7 +261,7 @@ in {
name = "service-account";
CN = "system:service-account-signer";
action = ''
systemctl reload \
systemctl restart \
kube-apiserver.service \
kube-controller-manager.service
'';

View file

@ -237,6 +237,8 @@ in {
serviceConfig = {
User = cfg.user;
StateDirectory = mkIf (hasPrefix "/var/lib/jenkins" cfg.home) "jenkins";
# For (possible) socket use
RuntimeDirectory = "jenkins";
};
};
};

View file

@ -264,10 +264,13 @@ in {
enable = true;
package = kdePackages.kwallet-pam;
};
kde.kwallet = {
kde = {
allowNullPassword = true;
kwallet = {
enable = true;
package = kdePackages.kwallet-pam;
};
};
kde-fingerprint = lib.mkIf config.services.fprintd.enable { fprintAuth = true; };
kde-smartcard = lib.mkIf config.security.pam.p11.enable { p11Auth = true; };
};

View file

@ -1,45 +1,52 @@
# GNOME Keyring daemon.
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.gnome.gnome-keyring;
in
{
meta = {
maintainers = lib.teams.gnome.members;
};
###### interface
options = {
services.gnome.gnome-keyring = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to enable GNOME Keyring daemon, a service designed to
enable = lib.mkEnableOption ''
GNOME Keyring daemon, a service designed to
take care of the user's security credentials,
such as user names and passwords.
such as user names and passwords
'';
};
};
};
###### implementation
config = lib.mkIf config.services.gnome.gnome-keyring.enable {
config = lib.mkIf cfg.enable {
environment.systemPackages = [ pkgs.gnome.gnome-keyring ];
services.dbus.packages = [ pkgs.gnome.gnome-keyring pkgs.gcr ];
services.dbus.packages = [
pkgs.gnome.gnome-keyring
pkgs.gcr
];
xdg.portal.extraPortals = [ pkgs.gnome.gnome-keyring ];
security.pam.services.login.enableGnomeKeyring = true;
security.pam.services = lib.mkMerge [
{
login.enableGnomeKeyring = true;
}
(lib.mkIf config.services.xserver.displayManager.gdm.enable {
gdm-password.enableGnomeKeyring = true;
gdm-autologin.enableGnomeKeyring = true;
})
(lib.mkIf (config.services.xserver.displayManager.gdm.enable && config.services.fprintd.enable) {
gdm-fingerprint.enableGnomeKeyring = true;
})
];
security.wrappers.gnome-keyring-daemon = {
owner = "root";
@ -47,7 +54,5 @@
capabilities = "cap_ipc_lock=ep";
source = "${pkgs.gnome.gnome-keyring}/bin/gnome-keyring-daemon";
};
};
}

View file

@ -28,7 +28,7 @@ in {
boot.initrd.kernelModules = lib.optionals cfg.initrd.enable [ "amdgpu" ];
hardware.opengl = lib.mkIf cfg.opencl.enable {
hardware.graphics = lib.mkIf cfg.opencl.enable {
enable = lib.mkDefault true;
extraPackages = [
pkgs.rocmPackages.clr

View file

@ -518,8 +518,9 @@ in {
# recreate symlinks for desired components
declare -a components=(${escapeShellArgs cfg.customComponents})
for component in "''${components[@]}"; do
path="$(dirname $(find "$component" -name "manifest.json"))"
ln -fns "$path" "${cfg.configDir}/custom_components/"
readarray -t manifests < <(find "$component" -name manifest.json)
readarray -t paths < <(dirname "''${manifests[@]}")
ln -fns "''${paths[@]}" "${cfg.configDir}/custom_components/"
done
'';
in

View file

@ -646,7 +646,7 @@ in {
};
meta = {
maintainers = with lib.maintainers; [ lheckemann qyliss ];
maintainers = with lib.maintainers; [ qyliss ];
doc = ./mailman.md;
};

View file

@ -37,8 +37,6 @@ in {
ansi = mkDefault false; # no colour markers to journald
enable = mkDefault true;
};
queue.path = mkDefault "${dataDir}/queue";
report.path = mkDefault "${dataDir}/reports";
store = if useLegacyStorage then {
# structured data in SQLite, blobs on filesystem
db.type = mkDefault "sqlite";
@ -62,6 +60,9 @@ in {
resolver.public-suffix = lib.mkDefault [
"file://${pkgs.publicsuffix-list}/share/publicsuffix/public_suffix_list.dat"
];
config.resource = {
spam-filter = lib.mkDefault "file://${cfg.package}/etc/stalwart/spamfilter.toml";
};
};
# This service stores a potentially large amount of data.
@ -83,9 +84,9 @@ in {
after = [ "local-fs.target" "network.target" ];
preStart = if useLegacyStorage then ''
mkdir -p ${dataDir}/{queue,reports,data/blobs}
mkdir -p ${dataDir}/data/blobs
'' else ''
mkdir -p ${dataDir}/{queue,reports,db}
mkdir -p ${dataDir}/db
'';
serviceConfig = {

View file

@ -98,9 +98,25 @@ in
- otherwise defaults to `false`
- `false`: disable GPU, only use CPU
- `"rocm"`: supported by most modern AMD GPUs
- may require overriding gpu type with `services.ollama.rocmOverrideGfx`
if rocm doesn't detect your AMD gpu
- `"cuda"`: supported by most modern NVIDIA GPUs
'';
};
rocmOverrideGfx = lib.mkOption {
type = types.nullOr types.str;
default = null;
example = "10.3.0";
description = ''
Override what rocm will detect your gpu model as.
For example, make rocm treat your RX 5700 XT (or any other model)
as an RX 6900 XT using a value of `"10.3.0"` (gfx 1030).
This sets the value of `HSA_OVERRIDE_GFX_VERSION`. See [ollama's docs](
https://github.com/ollama/ollama/blob/main/docs/gpu.md#amd-radeon
) for details.
'';
};
environmentVariables = lib.mkOption {
type = types.attrsOf types.str;
default = { };
@ -136,6 +152,7 @@ in
HOME = cfg.home;
OLLAMA_MODELS = cfg.models;
OLLAMA_HOST = "${cfg.host}:${toString cfg.port}";
HSA_OVERRIDE_GFX_VERSION = lib.mkIf (cfg.rocmOverrideGfx != null) cfg.rocmOverrideGfx;
};
serviceConfig = {
ExecStart = "${lib.getExe ollamaPackage} serve";

View file

@ -117,5 +117,5 @@ in
};
};
meta.maintainers = with lib.maintainers; [ drupol ];
meta.maintainers = with lib.maintainers; [ ];
}

View file

@ -1,16 +1,32 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
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;
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}";
@ -43,7 +59,7 @@ let
ALLOW_GROUPS = mkOption {
type = types.listOf safeStr;
default = [];
default = [ ];
description = ''
List of groups allowed to operate with the config.
@ -53,7 +69,7 @@ let
ALLOW_USERS = mkOption {
type = types.listOf safeStr;
default = [];
default = [ ];
example = [ "alice" ];
description = ''
List of users allowed to operate with the config. "root" is always
@ -78,6 +94,54 @@ let
Defines whether hourly snapshots should be created.
'';
};
TIMELINE_LIMIT_HOURLY = mkOption {
type = types.str;
default = "10";
description = ''
Limits for timeline cleanup.
'';
};
TIMELINE_LIMIT_DAILY = mkOption {
type = types.str;
default = "10";
description = ''
Limits for timeline cleanup.
'';
};
TIMELINE_LIMIT_WEEKLY = mkOption {
type = types.str;
default = "0";
description = ''
Limits for timeline cleanup.
'';
};
TIMELINE_LIMIT_MONTHLY = mkOption {
type = types.str;
default = "10";
description = ''
Limits for timeline cleanup.
'';
};
TIMELINE_LIMIT_QUARTERLY = mkOption {
type = types.str;
default = "0";
description = ''
Limits for timeline cleanup.
'';
};
TIMELINE_LIMIT_YEARLY = mkOption {
type = types.str;
default = "10";
description = ''
Limits for timeline cleanup.
'';
};
};
in
@ -152,38 +216,53 @@ in
is valid here, even if NixOS doesn't document it.
'';
type = types.attrsOf (types.submodule {
freeformType = types.attrsOf (types.oneOf [ (types.listOf safeStr) types.bool safeStr types.number ]);
type = types.attrsOf (
types.submodule {
freeformType = types.attrsOf (
types.oneOf [
(types.listOf safeStr)
types.bool
safeStr
types.number
]
);
options = configOptions;
});
}
);
};
};
config = mkIf (cfg.configs != {}) (let
documentation = [ "man:snapper(8)" "man:snapper-configs(5)" ];
in {
config = mkIf (cfg.configs != { }) (
let
documentation = [
"man:snapper(8)"
"man:snapper-configs(5)"
];
in
{
environment = {
systemPackages = [ pkgs.snapper ];
# Note: snapper/config-templates/default is only needed for create-config
# which is not the NixOS way to configure.
etc = {
etc =
{
"sysconfig/snapper".text = ''
SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
'';
}
// (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
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;
});
// (mapAttrs' (
name: subvolume:
nameValuePair "snapper/configs/${name}" ({
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; });
};
services.dbus.packages = [ pkgs.snapper ];
@ -245,19 +324,21 @@ in
unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
};
assertions =
concatMap
(name:
assertions = concatMap (
name:
let
sub = cfg.configs.${name};
in
[ { assertion = !(sub ? extraConfig);
[
{
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);
@ -265,8 +346,11 @@ in
The option definition `services.snapper.configs.${name}.${attr}' has been renamed to `services.snapper.configs.${name}.${toUpper attr}'.
'';
})
[ "fstype" "subvolume" ]
)
(attrNames cfg.configs);
});
[
"fstype"
"subvolume"
]
) (attrNames cfg.configs);
}
);
}

View file

@ -324,7 +324,8 @@ in
};
preStart =
let
version = pkgs.sourcehut.${srvsrht}.version;
package = pkgs.sourcehut.${srvsrht};
version = package.version;
stateDir = "/var/lib/sourcehut/${srvsrht}";
in
mkBefore ''
@ -336,14 +337,14 @@ in
if test ! -e ${stateDir}/db; then
# Setup the initial database.
# Note that it stamps the alembic head afterward
${cfg.python}/bin/${srvsrht}-initdb
${package}/bin/${srvsrht}-initdb
echo ${version} >${stateDir}/db
fi
${optionalString cfg.settings.${iniKey}.migrate-on-upgrade ''
if [ "$(cat ${stateDir}/db)" != "${version}" ]; then
# Manage schema migrations using alembic
${cfg.python}/bin/${srvsrht}-migrate -a upgrade head
${package}/bin/${srvsrht}-migrate -a upgrade head
echo ${version} >${stateDir}/db
fi
''}
@ -389,7 +390,7 @@ in
after = [ "network.target" "${srvsrht}.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${cfg.python}/bin/${timerName}";
ExecStart = "${pkgs.sourcehut.${srvsrht}}/bin/${timerName}";
};
}
(timer.service or { })

View file

@ -22,7 +22,7 @@ let
${lib.toShellVars env}
eval "$(${config.systemd.package}/bin/systemctl show -pUID,GID,MainPID tandoor-recipes.service)"
exec ${pkgs.util-linux}/bin/nsenter \
-t $MainPID -m -S $UID -G $GID \
-t $MainPID -m -S $UID -G $GID --wdns=${env.MEDIA_ROOT} \
${pkg}/bin/tandoor-recipes "$@"
'';
in
@ -88,7 +88,7 @@ in
Group = "tandoor_recipes";
DynamicUser = true;
StateDirectory = "tandoor-recipes";
WorkingDirectory = "/var/lib/tandoor-recipes";
WorkingDirectory = env.MEDIA_ROOT;
RuntimeDirectory = "tandoor-recipes";
BindReadOnlyPaths = [

View file

@ -60,7 +60,7 @@ in {
"-templates ${cfg.templateDir}"
];
in {
ExecStart = "${pkgs.grafana_reporter}/bin/grafana-reporter ${args}";
ExecStart = "${pkgs.grafana-reporter}/bin/grafana-reporter ${args}";
};
};
};

View file

@ -13,6 +13,9 @@ let
ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin
ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin
ln -s /run/wrappers/bin/systemd-journal.plugin $out/libexec/netdata/plugins.d/systemd-journal.plugin
ln -s /run/wrappers/bin/logs-management.plugin $out/libexec/netdata/plugins.d/logs-management.plugin
ln -s /run/wrappers/bin/network-viewer.plugin $out/libexec/netdata/plugins.d/network-viewer.plugin
ln -s /run/wrappers/bin/debugfs.plugin $out/libexec/netdata/plugins.d/debugfs.plugin
'';
plugins = [
@ -47,6 +50,7 @@ let
defaultUser = "netdata";
isThereAnyWireGuardTunnels = config.networking.wireguard.enable || lib.any (c: lib.hasAttrByPath [ "netdevConfig" "Kind" ] c && c.netdevConfig.Kind == "wireguard") (builtins.attrValues config.systemd.network.netdevs);
in {
options = {
services.netdata = {
@ -86,6 +90,14 @@ in {
Whether to enable python-based plugins
'';
};
recommendedPythonPackages = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable a set of recommended Python plugins
by installing extra Python packages.
'';
};
extraPackages = mkOption {
type = types.functionTo (types.listOf types.package);
default = ps: [];
@ -198,13 +210,26 @@ in {
}
];
# Includes a set of recommended Python plugins in exchange of imperfect disk consumption.
services.netdata.python.extraPackages = lib.mkIf cfg.python.recommendedPythonPackages (ps: [
ps.requests
ps.pandas
ps.numpy
ps.psycopg2
ps.python-ldap
ps.netdata-pandas
ps.changefinder
]);
services.netdata.configDir.".opt-out-from-anonymous-statistics" = mkIf (!cfg.enableAnalyticsReporting) (pkgs.writeText ".opt-out-from-anonymous-statistics" "");
environment.etc."netdata/netdata.conf".source = configFile;
environment.etc."netdata/conf.d".source = configDirectory;
systemd.services.netdata = {
description = "Real time performance monitoring";
after = [ "network.target" ];
after = [ "network.target" "suid-sgid-wrappers.service" ];
# No wrapper means no "useful" netdata.
requires = [ "suid-sgid-wrappers.service" ];
wantedBy = [ "multi-user.target" ];
path = (with pkgs; [
curl
@ -213,10 +238,16 @@ in {
which
procps
bash
nvme-cli # for go.d
iw # for charts.d
apcupsd # for charts.d
# TODO: firehol # for FireQoS -- this requires more NixOS module support.
util-linux # provides logger command; required for syslog health alarms
])
++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages)
++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package);
++ lib.optional config.virtualisation.libvirtd.enable config.virtualisation.libvirtd.package
++ lib.optional config.virtualisation.docker.enable config.virtualisation.docker.package
++ lib.optionals config.virtualisation.podman.enable [ pkgs.jq config.virtualisation.podman.package ];
environment = {
PYTHONPATH = "${cfg.package}/libexec/netdata/python.d/python_modules";
NETDATA_PIPENAME = "/run/netdata/ipc";
@ -256,6 +287,8 @@ in {
# Configuration directory and mode
ConfigurationDirectory = "netdata";
ConfigurationDirectoryMode = "0755";
# AmbientCapabilities
AmbientCapabilities = lib.optional isThereAnyWireGuardTunnels "CAP_NET_ADMIN";
# Capabilities
CapabilityBoundingSet = [
"CAP_DAC_OVERRIDE" # is required for freeipmi and slabinfo plugins
@ -269,7 +302,7 @@ in {
"CAP_SYS_CHROOT" # is required for cgroups plugin
"CAP_SETUID" # is required for cgroups and cgroups-network plugins
"CAP_SYSLOG" # is required for systemd-journal plugin
];
] ++ lib.optional isThereAnyWireGuardTunnels "CAP_NET_ADMIN";
# Sandboxing
ProtectSystem = "full";
ProtectHome = "read-only";
@ -308,6 +341,14 @@ in {
permissions = "u+rx,g+x,o-rwx";
};
"debugfs.plugin" = {
source = "${cfg.package}/libexec/netdata/plugins.d/debugfs.plugin.org";
capabilities = "cap_dac_read_search+ep";
owner = cfg.user;
group = cfg.group;
permissions = "u+rx,g+x,o-rwx";
};
"cgroup-network" = {
source = "${cfg.package}/libexec/netdata/plugins.d/cgroup-network.org";
capabilities = "cap_setuid+ep";
@ -332,6 +373,14 @@ in {
permissions = "u+rx,g+x,o-rwx";
};
"logs-management.plugin" = {
source = "${cfg.package}/libexec/netdata/plugins.d/logs-management.plugin.org";
capabilities = "cap_dac_read_search,cap_syslog+ep";
owner = cfg.user;
group = cfg.group;
permissions = "u+rx,g+x,o-rwx";
};
"slabinfo.plugin" = {
source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org";
capabilities = "cap_dac_override+ep";
@ -348,6 +397,14 @@ in {
group = cfg.group;
permissions = "u+rx,g+x,o-rwx";
};
} // optionalAttrs (cfg.package.withNetworkViewer) {
"network-viewer.plugin" = {
source = "${cfg.package}/libexec/netdata/plugins.d/network-viewer.plugin.org";
capabilities = "cap_sys_admin,cap_dac_read_search,cap_sys_ptrace+ep";
owner = cfg.user;
group = cfg.group;
permissions = "u+rx,g+x,o-rwx";
};
};
security.pam.loginLimits = [
@ -359,6 +416,8 @@ in {
${defaultUser} = {
group = defaultUser;
isSystemUser = true;
extraGroups = lib.optional config.virtualisation.docker.enable "docker"
++ lib.optional config.virtualisation.podman.enable "podman";
};
};

View file

@ -0,0 +1,70 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.prometheus.alertmanagerWebhookLogger;
in
{
options.services.prometheus.alertmanagerWebhookLogger = {
enable = mkEnableOption "Alertmanager Webhook Logger";
package = mkPackageOption pkgs "alertmanager-webhook-logger" { };
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = "Extra command line options to pass to alertmanager-webhook-logger.";
};
};
config = mkIf cfg.enable {
systemd.services.alertmanager-webhook-logger = {
description = "Alertmanager Webhook Logger";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/alertmanager-webhook-logger \
${escapeShellArgs cfg.extraFlags}
'';
DynamicUser = true;
NoNewPrivileges = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
ProtectHome = "tmpfs";
PrivateTmp = true;
PrivateDevices = true;
PrivateIPC = true;
ProtectHostname = true;
ProtectClock = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallFilter = [
"@system-service"
"~@cpu-emulation"
"~@privileged"
"~@reboot"
"~@setuid"
"~@swap"
];
};
};
};
meta.maintainers = [ maintainers.jpds ];
}

View file

@ -4,7 +4,7 @@ let
inherit (lib.attrsets) optionalAttrs;
inherit (lib.generators) toINIWithGlobalSection;
inherit (lib.lists) optional;
inherit (lib.modules) mkIf;
inherit (lib.modules) mkIf mkRemovedOptionModule;
inherit (lib.options) literalExpression mkEnableOption mkOption;
inherit (lib.strings) escape;
inherit (lib.types) attrsOf bool int lines oneOf str submodule;
@ -27,6 +27,13 @@ let
in
{
imports = [
(mkRemovedOptionModule [ "services" "davfs2" "extraConfig" ] ''
The option extraConfig got removed, please migrate to
services.davfs2.settings instead.
'')
];
options.services.davfs2 = {
enable = mkEnableOption "davfs2";

View file

@ -52,9 +52,6 @@ in
serviceConfig = {
ExecStart = "${pkgs.antennas}/bin/antennas";
# Antennas expects all resources like html and config to be relative to it's working directory
WorkingDirectory = "${pkgs.antennas}/libexec/antennas/deps/antennas/";
# Hardening
CapabilityBoundingSet = [ "" ];
DynamicUser = true;

View file

@ -37,7 +37,6 @@ in
{
meta.maintainers = with maintainers; [
misuzu
thubrecht
];
meta.doc = ./netbird.md;

View file

@ -16,7 +16,7 @@ in
{
meta = {
maintainers = with lib.maintainers; [thubrecht patrickdag];
maintainers = with lib.maintainers; [patrickdag];
doc = ./server.md;
};

View file

@ -1,83 +1,94 @@
{ config, lib, options, pkgs, utils, ... }:
with lib;
{ config
, lib
, pkgs
, ...
}:
let
cfg = config.services.wstunnel;
attrsToArgs = attrs: utils.escapeSystemdExecArgs (
mapAttrsToList
(name: value: if value == true then "--${name}" else "--${name}=${value}")
attrs
);
hostPortToString = { host, port }: "${host}:${builtins.toString port}";
hostPortToString = { host, port }: "${host}:${toString port}";
hostPortSubmodule = {
options = {
host = mkOption {
host = lib.mkOption {
description = "The hostname.";
type = types.str;
type = lib.types.str;
};
port = mkOption {
port = lib.mkOption {
description = "The port.";
type = types.port;
type = lib.types.port;
};
};
};
commonOptions = {
enable = mkOption {
description = "Whether to enable this `wstunnel` instance.";
type = types.bool;
enable = lib.mkEnableOption "this `wstunnel` instance." // {
default = true;
};
package = mkPackageOption pkgs "wstunnel" {};
package = lib.mkPackageOption pkgs "wstunnel" { };
autoStart = mkOption {
description = "Whether this tunnel server should be started automatically.";
type = types.bool;
autoStart =
lib.mkEnableOption "starting this wstunnel instance automatically." // {
default = true;
};
extraArgs = mkOption {
description = "Extra command line arguments to pass to `wstunnel`. Attributes of the form `argName = true;` will be translated to `--argName`, and `argName = \"value\"` to `--argName=value`.";
type = with types; attrsOf (either str bool);
default = {};
extraArgs = lib.mkOption {
description = ''
Extra command line arguments to pass to `wstunnel`.
Attributes of the form `argName = true;` will be translated to `--argName`,
and `argName = \"value\"` to `--argName value`.
'';
type = with lib.types; attrsOf (either str bool);
default = { };
example = {
"someNewOption" = true;
"someNewOptionWithValue" = "someValue";
};
};
loggingLevel = mkOption {
loggingLevel = lib.mkOption {
description = ''
Passed to --log-lvl
Control the log verbosity. i.e: TRACE, DEBUG, INFO, WARN, ERROR, OFF
For more details, checkout [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#example-syntax)
'';
type = types.nullOr types.str;
type = lib.types.nullOr lib.types.str;
example = "INFO";
default = null;
};
environmentFile = mkOption {
description = "Environment file to be passed to the systemd service. Useful for passing secrets to the service to prevent them from being world-readable in the Nix store. Note however that the secrets are passed to `wstunnel` through the command line, which makes them locally readable for all users of the system at runtime.";
type = types.nullOr types.path;
environmentFile = lib.mkOption {
description = ''
Environment file to be passed to the systemd service.
Useful for passing secrets to the service to prevent them from being
world-readable in the Nix store.
Note however that the secrets are passed to `wstunnel` through
the command line, which makes them locally readable for all users of
the system at runtime.
'';
type = lib.types.nullOr lib.types.path;
default = null;
example = "/var/lib/secrets/wstunnelSecrets";
};
};
serverSubmodule = { config, ...}: {
serverSubmodule = { config, ... }: {
options = commonOptions // {
listen = mkOption {
description = "Address and port to listen on. Setting the port to a value below 1024 will also give the process the required `CAP_NET_BIND_SERVICE` capability.";
type = types.submodule hostPortSubmodule;
listen = lib.mkOption {
description = ''
Address and port to listen on.
Setting the port to a value below 1024 will also give the process
the required `CAP_NET_BIND_SERVICE` capability.
'';
type = lib.types.submodule hostPortSubmodule;
default = {
host = "0.0.0.0";
port = if config.enableHTTPS then 443 else 80;
};
defaultText = literalExpression ''
defaultText = lib.literalExpression ''
{
host = "0.0.0.0";
port = if enableHTTPS then 443 else 80;
@ -85,39 +96,50 @@ let
'';
};
restrictTo = mkOption {
description = "Accepted traffic will be forwarded only to this service. Set to `null` to allow forwarding to arbitrary addresses.";
type = types.listOf (types.submodule hostPortSubmodule);
default = [];
restrictTo = lib.mkOption {
description = ''
Accepted traffic will be forwarded only to this service.
'';
type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
default = [ ];
example = [{
host = "127.0.0.1";
port = 51820;
}];
};
enableHTTPS = mkOption {
enableHTTPS = lib.mkOption {
description = "Use HTTPS for the tunnel server.";
type = types.bool;
type = lib.types.bool;
default = true;
};
tlsCertificate = mkOption {
description = "TLS certificate to use instead of the hardcoded one in case of HTTPS connections. Use together with `tlsKey`.";
type = types.nullOr types.path;
tlsCertificate = lib.mkOption {
description = ''
TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
Use together with `tlsKey`.
'';
type = lib.types.nullOr lib.types.path;
default = null;
example = "/var/lib/secrets/cert.pem";
};
tlsKey = mkOption {
description = "TLS key to use instead of the hardcoded on in case of HTTPS connections. Use together with `tlsCertificate`.";
type = types.nullOr types.path;
tlsKey = lib.mkOption {
description = ''
TLS key to use instead of the hardcoded on in case of HTTPS connections.
Use together with `tlsCertificate`.
'';
type = lib.types.nullOr lib.types.path;
default = null;
example = "/var/lib/secrets/key.pem";
};
useACMEHost = mkOption {
description = "Use a certificate generated by the NixOS ACME module for the given host. Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.";
type = types.nullOr types.str;
useACMEHost = lib.mkOption {
description = ''
Use a certificate generated by the NixOS ACME module for the given host.
Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
'';
type = lib.types.nullOr lib.types.str;
default = null;
example = "example.com";
};
@ -126,95 +148,113 @@ let
clientSubmodule = { config, ... }: {
options = commonOptions // {
connectTo = mkOption {
connectTo = lib.mkOption {
description = "Server address and port to connect to.";
type = types.str;
type = lib.types.str;
example = "https://wstunnel.server.com:8443";
};
localToRemote = mkOption {
localToRemote = lib.mkOption {
description = ''Listen on local and forwards traffic from remote.'';
type = types.listOf (types.str);
default = [];
type = lib.types.listOf (lib.types.str);
default = [ ];
example = [
"tcp://1212:google.com:443"
"unix:///tmp/wstunnel.sock:g.com:443"
];
};
remoteToLocal = mkOption {
remoteToLocal = lib.mkOption {
description = "Listen on remote and forwards traffic from local. Only tcp is supported";
type = types.listOf (types.str);
default = [];
type = lib.types.listOf lib.types.str;
default = [ ];
example = [
"tcp://1212:google.com:443"
"unix://wstunnel.sock:g.com:443"
];
};
addNetBind = mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
httpProxy = mkOption {
httpProxy = lib.mkOption {
description = ''
Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
::: {.warning}
Passwords specified here will be world-readable in the Nix store! To pass a password to the service, point the `environmentFile` option to a file containing `PROXY_PASSWORD=<your-password-here>` and set this option to `<user>:$PROXY_PASSWORD@<host>:<port>`. Note however that this will also locally leak the passwords at runtime via e.g. /proc/<pid>/cmdline.
Passwords specified here will be world-readable in the Nix store!
To pass a password to the service, point the `environmentFile` option
to a file containing `PROXY_PASSWORD=<your-password-here>` and set
this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
Note however that this will also locally leak the passwords at
runtime via e.g. /proc/<pid>/cmdline.
:::
'';
type = types.nullOr types.str;
type = lib.types.nullOr lib.types.str;
default = null;
};
soMark = mkOption {
description = "Mark network packets with the SO_MARK sockoption with the specified value. Setting this option will also enable the required `CAP_NET_ADMIN` capability for the systemd service.";
type = types.nullOr types.int;
soMark = lib.mkOption {
description = ''
Mark network packets with the SO_MARK sockoption with the specified value.
Setting this option will also enable the required `CAP_NET_ADMIN` capability
for the systemd service.
'';
type = lib.types.nullOr lib.types.ints.unsigned;
default = null;
};
upgradePathPrefix = mkOption {
description = "Use a specific HTTP path prefix that will show up in the upgrade request to the `wstunnel` server. Useful when running `wstunnel` behind a reverse proxy.";
type = types.nullOr types.str;
upgradePathPrefix = lib.mkOption {
description = ''
Use a specific HTTP path prefix that will show up in the upgrade
request to the `wstunnel` server.
Useful when running `wstunnel` behind a reverse proxy.
'';
type = lib.types.nullOr lib.types.str;
default = null;
example = "wstunnel";
};
tlsSNI = mkOption {
tlsSNI = lib.mkOption {
description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
type = types.nullOr types.str;
type = lib.types.nullOr lib.types.str;
default = null;
};
tlsVerifyCertificate = mkOption {
tlsVerifyCertificate = lib.mkOption {
description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
type = types.bool;
type = lib.types.bool;
default = true;
};
# The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
websocketPingInterval = mkOption {
websocketPingInterval = lib.mkOption {
description = "Frequency at which the client will send websocket ping to the server.";
type = types.nullOr types.ints.unsigned;
type = lib.types.nullOr lib.types.ints.unsigned;
default = null;
};
upgradeCredentials = mkOption {
upgradeCredentials = lib.mkOption {
description = ''
Use these credentials to authenticate during the HTTP upgrade request (Basic authorization type, `USER:[PASS]`).
Use these credentials to authenticate during the HTTP upgrade request
(Basic authorization type, `USER:[PASS]`).
::: {.warning}
Passwords specified here will be world-readable in the Nix store! To pass a password to the service, point the `environmentFile` option to a file containing `HTTP_PASSWORD=<your-password-here>` and set this option to `<user>:$HTTP_PASSWORD`. Note however that this will also locally leak the passwords at runtime via e.g. /proc/<pid>/cmdline.
Passwords specified here will be world-readable in the Nix store!
To pass a password to the service, point the `environmentFile` option
to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
option to `<user>:$HTTP_PASSWORD`.
Note however that this will also locally leak the passwords at runtime
via e.g. /proc/<pid>/cmdline.
:::
'';
type = types.nullOr types.str;
type = lib.types.nullOr lib.types.str;
default = null;
};
customHeaders = mkOption {
customHeaders = lib.mkOption {
description = "Custom HTTP headers to send during the upgrade request.";
type = types.attrsOf types.str;
default = {};
type = lib.types.attrsOf lib.types.str;
default = { };
example = {
"X-Some-Header" = "some-value";
};
@ -224,38 +264,28 @@ let
generateServerUnit = name: serverCfg: {
name = "wstunnel-server-${name}";
value = {
value =
let
certConfig = config.security.acme.certs.${serverCfg.useACMEHost};
in
{
description = "wstunnel server - ${name}";
requires = [ "network.target" "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = optional serverCfg.autoStart "multi-user.target";
wantedBy = lib.optional serverCfg.autoStart "multi-user.target";
serviceConfig = let
certConfig = config.security.acme.certs."${serverCfg.useACMEHost}";
in {
Type = "simple";
ExecStart = with serverCfg; let
resolvedTlsCertificate = if useACMEHost != null
then "${certConfig.directory}/fullchain.pem"
else tlsCertificate;
resolvedTlsKey = if useACMEHost != null
then "${certConfig.directory}/key.pem"
else tlsKey;
in ''
${package}/bin/wstunnel \
server \
${concatStringsSep " " (builtins.map (hostPair: "--restrict-to ${utils.escapeSystemdExecArg (hostPortToString hostPair)}") restrictTo)} \
${optionalString (resolvedTlsCertificate != null) "--tls-certificate ${utils.escapeSystemdExecArg resolvedTlsCertificate}"} \
${optionalString (resolvedTlsKey != null) "--tls-private-key ${utils.escapeSystemdExecArg resolvedTlsKey}"} \
${optionalString (loggingLevel != null) "--log-lvl ${loggingLevel}"} \
${attrsToArgs extraArgs} \
${utils.escapeSystemdExecArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
'';
EnvironmentFile = optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
environment.RUST_LOG = serverCfg.loggingLevel;
serviceConfig = {
Type = "exec";
EnvironmentFile =
lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
DynamicUser = true;
SupplementaryGroups = optional (serverCfg.useACMEHost != null) certConfig.group;
SupplementaryGroups =
lib.optional (serverCfg.useACMEHost != null) certConfig.group;
PrivateTmp = true;
AmbientCapabilities = optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
AmbientCapabilities =
lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
NoNewPrivileges = true;
RestrictNamespaces = "uts ipc pid user cgroup";
ProtectSystem = "strict";
@ -265,7 +295,31 @@ let
ProtectControlGroups = true;
PrivateDevices = true;
RestrictSUIDSGID = true;
Restart = "on-failure";
RestartSec = 2;
RestartSteps = 20;
RestartMaxDelaySec = "5min";
};
script = with serverCfg; ''
${lib.getExe package} \
server \
${lib.cli.toGNUCommandLineShell { } (
lib.recursiveUpdate
{
restrict-to = map hostPortToString restrictTo;
tls-certificate = if useACMEHost != null
then "${certConfig.directory}/fullchain.pem"
else "${tlsCertificate}";
tls-private-key = if useACMEHost != null
then "${certConfig.directory}/key.pem"
else "${tlsKey}";
}
extraArgs
)} \
${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
'';
};
};
@ -275,30 +329,19 @@ let
description = "wstunnel client - ${name}";
requires = [ "network.target" "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = optional clientCfg.autoStart "multi-user.target";
wantedBy = lib.optional clientCfg.autoStart "multi-user.target";
environment.RUST_LOG = clientCfg.loggingLevel;
serviceConfig = {
Type = "simple";
ExecStart = with clientCfg; ''
${package}/bin/wstunnel client \
${concatStringsSep " " (builtins.map (x: "--local-to-remote ${x}") localToRemote)} \
${concatStringsSep " " (builtins.map (x: "--remote-to-local ${x}") remoteToLocal)} \
${concatStringsSep " " (mapAttrsToList (n: v: "--http-headers \"${n}: ${v}\"") customHeaders)} \
${optionalString (httpProxy != null) "--http-proxy ${httpProxy}"} \
${optionalString (soMark != null) "--socket-so-mark=${toString soMark}"} \
${optionalString (upgradePathPrefix != null) "--http-upgrade-path-prefix ${upgradePathPrefix}"} \
${optionalString (tlsSNI != null) "--tls-sni-override ${tlsSNI}"} \
${optionalString tlsVerifyCertificate "--tls-verify-certificate"} \
${optionalString (websocketPingInterval != null) "--websocket-ping-frequency-sec ${toString websocketPingInterval}"} \
${optionalString (upgradeCredentials != null) "--http-upgrade-credentials ${upgradeCredentials}"} \
${optionalString (loggingLevel != null) "--log-lvl ${loggingLevel}"} \
${attrsToArgs extraArgs} \
${utils.escapeSystemdExecArg connectTo}
'';
EnvironmentFile = optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
Type = "exec";
EnvironmentFile =
lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
DynamicUser = true;
PrivateTmp = true;
AmbientCapabilities = (optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]) ++ (optionals (clientCfg.addNetBind) [ "CAP_NET_BIND_SERVICE" ]);
AmbientCapabilities =
(lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++
(lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
NoNewPrivileges = true;
RestrictNamespaces = "uts ipc pid user cgroup";
ProtectSystem = "strict";
@ -308,17 +351,45 @@ let
ProtectControlGroups = true;
PrivateDevices = true;
RestrictSUIDSGID = true;
};
};
};
in {
options.services.wstunnel = {
enable = mkEnableOption "wstunnel";
servers = mkOption {
Restart = "on-failure";
RestartSec = 2;
RestartSteps = 20;
RestartMaxDelaySec = "5min";
};
script = with clientCfg; ''
${lib.getExe package} \
client \
${lib.cli.toGNUCommandLineShell { } (
lib.recursiveUpdate
{
local-to-remote = localToRemote;
remote-to-local = remoteToLocal;
http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
http-proxy = httpProxy;
socket-so-mark = soMark;
http-upgrade-path-prefix = upgradePathPrefix;
tls-sni-override = tlsSNI;
tls-verify-certificate = tlsVerifyCertificate;
websocket-ping-frequency-sec = websocketPingInterval;
http-upgrade-credentials = upgradeCredentials;
}
extraArgs
)} \
${lib.escapeShellArg connectTo}
'';
};
};
in
{
options.services.wstunnel = {
enable = lib.mkEnableOption "wstunnel";
servers = lib.mkOption {
description = "`wstunnel` servers to set up.";
type = types.attrsOf (types.submodule serverSubmodule);
default = {};
type = lib.types.attrsOf (lib.types.submodule serverSubmodule);
default = { };
example = {
"wg-tunnel" = {
listen = {
@ -336,13 +407,13 @@ in {
};
};
clients = mkOption {
clients = lib.mkOption {
description = "`wstunnel` clients to set up.";
type = types.attrsOf (types.submodule clientSubmodule);
default = {};
type = lib.types.attrsOf (lib.types.submodule clientSubmodule);
default = { };
example = {
"wg-tunnel" = {
connectTo = "https://wstunnel.server.com:8443";
connectTo = "wss://wstunnel.server.com:8443";
localToRemote = [
"tcp://1212:google.com:443"
"tcp://2:n.lan:4?proxy_protocol"
@ -356,28 +427,42 @@ in {
};
};
config = mkIf cfg.enable {
systemd.services = (mapAttrs' generateServerUnit (filterAttrs (n: v: v.enable) cfg.servers)) // (mapAttrs' generateClientUnit (filterAttrs (n: v: v.enable) cfg.clients));
config = lib.mkIf cfg.enable {
systemd.services =
(lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) //
(lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
assertions = (mapAttrsToList (name: serverCfg: {
assertion = !(serverCfg.useACMEHost != null && (serverCfg.tlsCertificate != null || serverCfg.tlsKey != null));
assertions =
(lib.mapAttrsToList
(name: serverCfg: {
assertion =
!(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
message = ''
Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
'';
}) cfg.servers) ++
(mapAttrsToList (name: serverCfg: {
assertion = !((serverCfg.tlsCertificate != null || serverCfg.tlsKey != null) && !(serverCfg.tlsCertificate != null && serverCfg.tlsKey != null));
})
cfg.servers) ++
(lib.mapAttrsToList
(name: serverCfg: {
assertion =
(serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) ||
(serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
message = ''
services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
'';
}) cfg.servers) ++
(mapAttrsToList (name: clientCfg: {
assertion = !(clientCfg.localToRemote == [] && clientCfg.remoteToLocal == []);
})
cfg.servers) ++
(lib.mapAttrsToList
(name: clientCfg: {
assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]);
message = ''
Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set.
'';
}) cfg.clients);
})
cfg.clients);
};
meta.maintainers = with maintainers; [ alyaeanyx neverbehave ];
meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ];
}

View file

@ -4,7 +4,9 @@ with lib;
let
cfg = config.services.zerotierone;
localConfFile = pkgs.writeText "zt-local.conf" (builtins.toJSON cfg.localConf);
settingsFormat = pkgs.formats.json {};
localConfFile = settingsFormat.generate "zt-local.conf" cfg.localConf;
localConfFilePath = "/var/lib/zerotier-one/local.conf";
in
{
@ -41,7 +43,7 @@ in
example = {
settings.allowTcpFallbackRelay = false;
};
type = types.nullOr types.attrs;
type = settingsFormat.type;
};
config = mkIf cfg.enable {
@ -60,7 +62,7 @@ in
chown -R root:root /var/lib/zerotier-one
'' + (concatMapStrings (netId: ''
touch "/var/lib/zerotier-one/networks.d/${netId}.conf"
'') cfg.joinNetworks) + optionalString (cfg.localConf != null) ''
'') cfg.joinNetworks) + optionalString (cfg.localConf != {}) ''
if [ -L "${localConfFilePath}" ]
then
rm ${localConfFilePath}

View file

@ -6,7 +6,7 @@ let
cfg = config.services.sslmate-agent;
in {
meta.maintainers = with maintainers; [ wolfangaukang ];
meta.maintainers = [ ];
options = {
services.sslmate-agent = {

View file

@ -4,7 +4,7 @@ let
settingsFormat = (pkgs.formats.json { });
in
{
meta.maintainers = with lib.maintainers; [ mohe2015 ];
meta.maintainers = with lib.maintainers; [ ];
options = {
services.step-ca = {

View file

@ -174,7 +174,10 @@ in
};
};
package = mkPackageOption pkgs "transmission" {};
package = mkPackageOption pkgs "transmission" {
default = "transmission_3";
example = "pkgs.transmission_4";
};
downloadDirPermissions = mkOption {
type = with types; nullOr str;

View file

@ -33,10 +33,10 @@ let
${optionalString (cfg.settings.DB_CONNECTION == "sqlite")
"touch ${cfg.dataDir}/storage/database/database.sqlite"}
${artisan} cache:clear
${artisan} package:discover
${artisan} firefly-iii:upgrade-database
${artisan} firefly-iii:laravel-passport-keys
${artisan} cache:clear
${artisan} view:cache
${artisan} route:cache
${artisan} config:cache
@ -283,8 +283,6 @@ in {
before = [ "phpfpm-firefly-iii.service" ];
serviceConfig = {
ExecStart = firefly-iii-maintenance;
RuntimeDirectory = "phpfpm";
RuntimeDirectoryPreserve = true;
RemainAfterExit = true;
} // commonServiceConfig;
unitConfig.JoinsNamespaceOf = "phpfpm-firefly-iii.service";

View file

@ -68,13 +68,11 @@ to `/auth`. See the option description
for more details.
:::
[](#opt-services.keycloak.settings.hostname-strict-backchannel)
determines whether Keycloak should force all requests to go
through the frontend URL. By default,
Keycloak allows backend requests to
instead use its local hostname or IP address and may also
advertise it to clients through its OpenID Connect Discovery
endpoint.
[](#opt-services.keycloak.settings.hostname-backchannel-dynamic)
Keycloak has the capability to offer a separate URL for backchannel requests,
enabling internal communication while maintaining the use of a public URL
for frontchannel requests. Moreover, the backchannel is dynamically
resolved based on incoming headers endpoint.
For more information on hostname configuration, see the [Hostname
section of the Keycloak Server Installation and Configuration

View file

@ -328,8 +328,7 @@ in
};
hostname = mkOption {
type = nullOr str;
default = null;
type = str;
example = "keycloak.example.com";
description = ''
The hostname part of the public URL used as base for
@ -340,16 +339,13 @@ in
'';
};
hostname-strict-backchannel = mkOption {
hostname-backchannel-dynamic = mkOption {
type = bool;
default = false;
example = true;
description = ''
Whether Keycloak should force all requests to go
through the frontend URL. By default, Keycloak allows
backend requests to instead use its local hostname or
IP address and may also advertise it to clients
through its OpenID Connect Discovery endpoint.
Enables dynamic resolving of backchannel URLs,
including hostname, scheme, port and context path.
See <https://www.keycloak.org/server/hostname>
for more information about hostname configuration.
@ -482,12 +478,20 @@ in
message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably";
}
{
assertion = cfg.settings.hostname != null || cfg.settings.hostname-url or null != null;
message = "Setting the Keycloak hostname is required, see `services.keycloak.settings.hostname`";
assertion = cfg.settings.hostname-url or null == null;
message = ''
The option `services.keycloak.settings.hostname-url' has been removed.
Set `services.keycloak.settings.hostname' instead.
See [New Hostname options](https://www.keycloak.org/docs/25.0.0/upgrading/#new-hostname-options) for details.
'';
}
{
assertion = !(cfg.settings.hostname != null && cfg.settings.hostname-url or null != null);
message = "`services.keycloak.settings.hostname` and `services.keycloak.settings.hostname-url` are mutually exclusive";
assertion = cfg.settings.hostname-strict-backchannel or null == null;
message = ''
The option `services.keycloak.settings.hostname-strict-backchannel' has been removed.
Set `services.keycloak.settings.hostname-backchannel-dynamic' instead.
See [New Hostname options](https://www.keycloak.org/docs/25.0.0/upgrading/#new-hostname-options) for details.
'';
}
];

View file

@ -80,6 +80,12 @@ let
mkKeyValue = generators.mkKeyValueDefault {} " = ";
};
phpCli = concatStringsSep " " ([
"${getExe phpPackage}"
] ++ optionals (cfg.cli.memoryLimit != null) [
"-dmemory_limit=${cfg.cli.memoryLimit}"
]);
occ = pkgs.writeScriptBin "nextcloud-occ" ''
#! ${pkgs.runtimeShell}
cd ${webroot}
@ -89,7 +95,7 @@ let
fi
export NEXTCLOUD_CONFIG_DIR="${datadir}/config"
$sudo \
${phpPackage}/bin/php \
${phpCli} \
occ "$@"
'';
@ -196,6 +202,9 @@ let
in {
imports = [
(mkRenamedOptionModule
[ "services" "nextcloud" "cron" "memoryLimit" ]
[ "services" "nextcloud" "cli" "memoryLimit" ])
(mkRemovedOptionModule [ "services" "nextcloud" "enableBrokenCiphersForSSE" ] ''
This option has no effect since there's no supported Nextcloud version packaged here
using OpenSSL for RC4 SSE.
@ -446,7 +455,13 @@ in {
dbtableprefix = mkOption {
type = types.nullOr types.str;
default = null;
description = "Table prefix in Nextcloud's database.";
description = ''
Table prefix in Nextcloud's database.
__Note:__ since Nextcloud 20 it's not an option anymore to create a database
schema with a custom table prefix. This option only exists for backwards compatibility
with installations that were originally provisioned with Nextcloud <20.
'';
};
adminuser = mkOption {
type = types.str;
@ -642,7 +657,6 @@ in {
type = types.package;
default = occ;
defaultText = literalMD "generated script";
internal = true;
description = ''
The nextcloud-occ program preconfigured to target this Nextcloud instance.
'';
@ -794,7 +808,7 @@ in {
};
};
cron.memoryLimit = mkOption {
cli.memoryLimit = mkOption {
type = types.nullOr types.str;
default = null;
example = "1G";
@ -826,6 +840,13 @@ in {
Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
Please migrate your configuration to config.services.nextcloud.poolSettings.
'')
++ (optional (cfg.config.dbtableprefix != null) ''
Using `services.nextcloud.config.dbtableprefix` is deprecated. Fresh installations with this
option set are not allowed anymore since v20.
If you have an existing installation with a custom table prefix, make sure it is
set correctly in `config.php` and remove the option from your NixOS config.
'')
++ (optional (versionOlder cfg.package.version "25") (upgradeWarning 24 "22.11"))
++ (optional (versionOlder cfg.package.version "26") (upgradeWarning 25 "23.05"))
++ (optional (versionOlder cfg.package.version "27") (upgradeWarning 26 "23.11"))
@ -1010,14 +1031,8 @@ in {
serviceConfig = {
Type = "exec";
User = "nextcloud";
ExecCondition = "${lib.getExe phpPackage} -f ${webroot}/occ status -e";
ExecStart = lib.concatStringsSep " " ([
(lib.getExe phpPackage)
] ++ optional (cfg.cron.memoryLimit != null) "-dmemory_limit=${cfg.cron.memoryLimit}"
++ [
"-f"
"${webroot}/cron.php"
]);
ExecCondition = "${phpCli} -f ${webroot}/occ status -e";
ExecStart = "${phpCli} -f ${webroot}/cron.php";
KillMode = "process";
};
};
@ -1041,7 +1056,7 @@ in {
serviceConfig = {
Type = "exec";
User = "nextcloud";
ExecCondition = "${lib.getExe phpPackage} -f ${webroot}/occ status -e";
ExecCondition = "${phpCli} -f ${webroot}/occ status -e";
};
};
};

View file

@ -219,5 +219,5 @@ in
users.groups.zitadel = lib.mkIf (cfg.group == "zitadel") { };
};
meta.maintainers = with lib.maintainers; [ Sorixelle ];
meta.maintainers = [ ];
}

View file

@ -71,9 +71,7 @@ in {
host = mkOption {
type = lib.types.str;
default = "bluemap.${config.networking.domain}";
defaultText = lib.literalExpression "bluemap.\${config.networking.domain}";
description = "Domain to configure nginx for";
description = "Domain on which nginx will serve the bluemap webapp";
};
onCalendar = mkOption {

View file

@ -116,7 +116,7 @@ in
] # TODO: NetworkManager doesn't belong here
++ optional config.networking.networkmanager.enable networkmanagerapplet
++ optional config.powerManagement.enable xfce4-power-manager
++ optionals config.hardware.pulseaudio.enable [
++ optionals (config.hardware.pulseaudio.enable || config.services.pipewire.pulse.enable) [
pavucontrol
# volume up/down keys support:
# xfce4-pulseaudio-plugin includes all the functionalities of xfce4-volumed-pulse

View file

@ -48,7 +48,7 @@ in
assertions = (attrValues (mapAttrs
(device: _: {
assertion = (any (fs: fs.device == device && (elem fs.fsType supportedFs)) config.system.build.fileSystems) || (hasAttr device config.boot.initrd.luks.devices);
assertion = (any (fs: fs.device == device && (elem fs.fsType supportedFs) || (fs.fsType == "zfs" && hasPrefix "${device}/" fs.device)) config.system.build.fileSystems) || (hasAttr device config.boot.initrd.luks.devices);
message = ''
No filesystem or LUKS device with the name ${device} is declared in your configuration.'';
})

View file

@ -17,8 +17,7 @@ let
cfgZED = config.services.zfs.zed;
selectModulePackage = package: config.boot.kernelPackages.${package.kernelModuleAttribute};
clevisDatasets = map (e: e.device) (filter (e: e.device != null && (hasAttr e.device config.boot.initrd.clevis.devices) && e.fsType == "zfs" && (fsNeededForBoot e)) config.system.build.fileSystems);
clevisDatasets = attrNames (filterAttrs (device: _: any (e: e.fsType == "zfs" && (fsNeededForBoot e) && (e.device == device || hasPrefix "${device}/" e.device)) config.system.build.fileSystems) config.boot.initrd.clevis.devices);
inInitrd = config.boot.initrd.supportedFilesystems.zfs or false;
inSystem = config.boot.supportedFilesystems.zfs or false;

View file

@ -9,10 +9,10 @@ in
config = {
system.build.OCIImage = import ../../lib/make-disk-image.nix {
inherit config lib pkgs;
inherit (cfg) diskSize;
name = "oci-image";
configFile = ./oci-config-user.nix;
format = "qcow2";
diskSize = 8192;
partitionTableType = if cfg.efi then "efi" else "legacy";
};

View file

@ -9,6 +9,12 @@
Whether the OCI instance is using EFI.
'';
};
diskSize = lib.mkOption {
type = lib.types.int;
default = 8192;
description = "Size of the disk image created in MB.";
example = "diskSize = 12 * 1024; # 12GiB";
};
};
};
}

View file

@ -22,5 +22,5 @@
};
};
meta.maintainers = [ lib.maintainers.lheckemann ];
meta.maintainers = [ ];
}

View file

@ -11,8 +11,7 @@ let
#!${pkgs.runtimeShell}
if [ ! -e ~/.ssh/authorized_keys ]; then
mkdir -m 0700 -p ~/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" >> ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keys
install -m 0600 <(echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key") ~/.ssh/authorized_keys
fi
'';
in

View file

@ -500,7 +500,8 @@ in {
libreddit = handleTest ./libreddit.nix {};
librenms = handleTest ./librenms.nix {};
libresprite = handleTest ./libresprite.nix {};
libreswan = handleTest ./libreswan.nix {};
libreswan = runTest ./libreswan.nix;
libreswan-nat = runTest ./libreswan-nat.nix;
librewolf = handleTest ./firefox.nix { firefoxPackage = pkgs.librewolf; };
libuiohook = handleTest ./libuiohook.nix {};
libvirtd = handleTest ./libvirtd.nix {};
@ -774,7 +775,7 @@ in {
printing-service = handleTest ./printing.nix { socket = false; };
private-gpt = handleTest ./private-gpt.nix {};
privoxy = handleTest ./privoxy.nix {};
prometheus = handleTest ./prometheus.nix {};
prometheus = handleTest ./prometheus {};
prometheus-exporters = handleTest ./prometheus-exporters.nix {};
prosody = handleTest ./xmpp/prosody.nix {};
prosody-mysql = handleTest ./xmpp/prosody-mysql.nix {};
@ -957,6 +958,7 @@ in {
systemd-homed = handleTest ./systemd-homed.nix {};
systemtap = handleTest ./systemtap.nix {};
tandoor-recipes = handleTest ./tandoor-recipes.nix {};
tandoor-recipes-script-name = handleTest ./tandoor-recipes-script-name.nix {};
tang = handleTest ./tang.nix {};
taskserver = handleTest ./taskserver.nix {};
tayga = handleTest ./tayga.nix {};
@ -966,6 +968,7 @@ in {
teleport = handleTest ./teleport.nix {};
thelounge = handleTest ./thelounge.nix {};
terminal-emulators = handleTest ./terminal-emulators.nix {};
thanos = handleTest ./thanos.nix {};
tiddlywiki = handleTest ./tiddlywiki.nix {};
tigervnc = handleTest ./tigervnc.nix {};
timescaledb = handleTest ./timescaledb.nix {};
@ -980,7 +983,7 @@ in {
traefik = handleTestOn ["aarch64-linux" "x86_64-linux"] ./traefik.nix {};
trafficserver = handleTest ./trafficserver.nix {};
transfer-sh = handleTest ./transfer-sh.nix {};
transmission = handleTest ./transmission.nix { transmission = pkgs.transmission; };
transmission_3 = handleTest ./transmission.nix { transmission = pkgs.transmission_3; };
transmission_4 = handleTest ./transmission.nix { transmission = pkgs.transmission_4; };
# tracee requires bpf
tracee = handleTestOn ["x86_64-linux"] ./tracee.nix {};
@ -1045,6 +1048,7 @@ in {
wordpress = handleTest ./wordpress.nix {};
wrappers = handleTest ./wrappers.nix {};
writefreely = handleTest ./web-apps/writefreely.nix {};
wstunnel = runTest ./wstunnel.nix;
xandikos = handleTest ./xandikos.nix {};
xautolock = handleTest ./xautolock.nix {};
xfce = handleTest ./xfce.nix {};

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix (
{
name = "crabfit";
meta.maintainers = with lib.maintainers; [ thubrecht ];
meta.maintainers = with lib.maintainers; [ ];
nodes = {
machine =

View file

@ -44,6 +44,8 @@ in {
# test loading custom components
customComponents = with pkgs.home-assistant-custom-components; [
prometheus_sensor
# tests loading multiple components from a single package
spook
];
# test loading lovelace modules
@ -179,7 +181,8 @@ in {
with subtest("Check that custom components get installed"):
hass.succeed("test -f ${configDir}/custom_components/prometheus_sensor/manifest.json")
hass.wait_until_succeeds("journalctl -u home-assistant.service | grep -q 'We found a custom integration prometheus_sensor which has not been tested by Home Assistant'")
for integration in ("prometheus_sensor", "spook", "spook_inverse"):
hass.wait_until_succeeds(f"journalctl -u home-assistant.service | grep -q 'We found a custom integration {integration} which has not been tested by Home Assistant'")
with subtest("Check that lovelace modules are referenced and fetchable"):
hass.succeed("grep -q 'mini-graph-card-bundle.js' '${configDir}/configuration.yaml'")
@ -228,7 +231,8 @@ in {
cursor = get_journal_cursor()
hass.succeed("${system}/specialisation/removeCustomThings/bin/switch-to-configuration test")
hass.fail("grep -q 'mini-graph-card-bundle.js' '${configDir}/ui-lovelace.yaml'")
hass.fail("test -f ${configDir}/custom_components/prometheus_sensor/manifest.json")
for integration in ("prometheus_sensor", "spook", "spook_inverse"):
hass.fail(f"test -f ${configDir}/custom_components/{integration}/manifest.json")
wait_for_homeassistant(cursor)
with subtest("Check that no errors were logged"):

View file

@ -9,7 +9,7 @@ let
testWithCompressor = compressor: testing.makeTest {
name = "initrd-secrets-${compressor}";
meta.maintainers = [ lib.maintainers.lheckemann ];
meta.maintainers = [ ];
nodes.machine = { ... }: {
virtualisation.useBootLoader = true;

View file

@ -37,6 +37,8 @@
clevisLuksFallback
clevisZfs
clevisZfsFallback
clevisZfsParentDataset
clevisZfsParentDatasetFallback
gptAutoRoot
clevisBcachefs
clevisBcachefsFallback

View file

@ -714,7 +714,7 @@ let
'';
};
mkClevisZfsTest = { fallback ? false }: makeInstallerTest "clevis-zfs${optionalString fallback "-fallback"}" {
mkClevisZfsTest = { fallback ? false, parentDataset ? false }: makeInstallerTest "clevis-zfs${optionalString parentDataset "-parent-dataset"}${optionalString fallback "-fallback"}" {
clevisTest = true;
clevisFallbackTest = fallback;
enableOCR = fallback;
@ -731,17 +731,27 @@ let
"udevadm settle",
"mkswap /dev/vda2 -L swap",
"swapon -L swap",
'' + optionalString (!parentDataset) ''
"zpool create -O mountpoint=legacy rpool /dev/vda3",
"echo -n password | zfs create"
+ " -o encryption=aes-256-gcm -o keyformat=passphrase rpool/root",
'' + optionalString (parentDataset) ''
"echo -n password | zpool create -O mountpoint=none -O encryption=on -O keyformat=passphrase rpool /dev/vda3",
"zfs create -o mountpoint=legacy rpool/root",
'' +
''
"mount -t zfs rpool/root /mnt",
"mkfs.ext3 -L boot /dev/vda1",
"mkdir -p /mnt/boot",
"mount LABEL=boot /mnt/boot",
"udevadm settle")
'';
extraConfig = ''
extraConfig = optionalString (!parentDataset) ''
boot.initrd.clevis.devices."rpool/root".secretFile = "/etc/nixos/clevis-secret.jwe";
'' + optionalString (parentDataset) ''
boot.initrd.clevis.devices."rpool".secretFile = "/etc/nixos/clevis-secret.jwe";
'' +
''
boot.zfs.requestEncryptionCredentials = true;
@ -1359,6 +1369,8 @@ in {
clevisLuksFallback = mkClevisLuksTest { fallback = true; };
clevisZfs = mkClevisZfsTest { };
clevisZfsFallback = mkClevisZfsTest { fallback = true; };
clevisZfsParentDataset = mkClevisZfsTest { parentDataset = true; };
clevisZfsParentDatasetFallback = mkClevisZfsTest { parentDataset = true; fallback = true; };
} // optionalAttrs systemdStage1 {
stratisRoot = makeInstallerTest "stratisRoot" {
createPartitions = ''

View file

@ -44,7 +44,6 @@ let
};
plugins = with config.services.keycloak.package.plugins; [
keycloak-discord
keycloak-metrics-spi
];
};
environment.systemPackages = with pkgs; [
@ -122,14 +121,6 @@ let
| jq -r '"Authorization: bearer " + .access_token' >admin_auth_header
""")
# Register the metrics SPI
keycloak.succeed(
"""${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt""",
"""KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password "$(<${adminPasswordFile})" """,
"""KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'""",
"""curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'"""
)
# Publish the realm, including a test OIDC client and user
keycloak.succeed(
"curl -sSf -H @admin_auth_header -X POST -H 'Content-Type: application/json' -d @${realmDataJson} '${frontendUrl}/admin/realms/'"

View file

@ -0,0 +1,238 @@
# This test sets up an IPsec VPN server that allows a client behind an IPv4 NAT
# router to access the IPv6 internet. We check that the client initially can't
# ping an IPv6 hosts and its connection to the server can be eavesdropped by
# the router, but once the IPsec tunnel is enstablished it can talk to an
# IPv6-only host and the connection is secure.
#
# Notes:
# - the VPN is implemented using policy-based routing.
# - the client is assigned an IPv6 address from the same /64 subnet
# of the server, without DHCPv6 or SLAAC.
# - the server acts as NDP proxy for the client, so that the latter
# becomes reachable at its assigned IPv6 via the server.
# - the client falls back to TCP if UDP is blocked
{ lib, pkgs, ... }:
let
# Common network setup
baseNetwork = {
# shared hosts file
networking.extraHosts = lib.mkVMOverride ''
203.0.113.1 router
203.0.113.2 server
2001:db8::2 inner
192.168.1.1 client
'';
# open a port for testing
networking.firewall.allowedUDPPorts = [ 1234 ];
};
# Common IPsec configuration
baseTunnel = {
services.libreswan.enable = true;
environment.etc."ipsec.d/tunnel.secrets" =
{ text = ''@server %any : PSK "j1JbIi9WY07rxwcNQ6nbyThKCf9DGxWOyokXIQcAQUnafsNTUJxfsxwk9WYK8fHj"'';
mode = "600";
};
};
# Helpers to add a static IP address on an interface
setAddress4 = iface: addr: {
networking.interfaces.${iface}.ipv4.addresses =
lib.mkVMOverride [ { address = addr; prefixLength = 24; } ];
};
setAddress6 = iface: addr: {
networking.interfaces.${iface}.ipv6.addresses =
lib.mkVMOverride [ { address = addr; prefixLength = 64; } ];
};
in
{
name = "libreswan-nat";
meta = with lib.maintainers; {
maintainers = [ rnhmjoj ];
};
nodes.router = { pkgs, ... }: lib.mkMerge [
baseNetwork
(setAddress4 "eth1" "203.0.113.1")
(setAddress4 "eth2" "192.168.1.1")
{
virtualisation.vlans = [ 1 2 ];
environment.systemPackages = [ pkgs.tcpdump ];
networking.nat = {
enable = true;
externalInterface = "eth1";
internalInterfaces = [ "eth2" ];
};
networking.firewall.trustedInterfaces = [ "eth2" ];
}
];
nodes.inner = lib.mkMerge [
baseNetwork
(setAddress6 "eth1" "2001:db8::2")
{ virtualisation.vlans = [ 3 ]; }
];
nodes.server = lib.mkMerge [
baseNetwork
baseTunnel
(setAddress4 "eth1" "203.0.113.2")
(setAddress6 "eth2" "2001:db8::1")
{
virtualisation.vlans = [ 1 3 ];
networking.firewall.allowedUDPPorts = [ 500 4500 ];
networking.firewall.allowedTCPPorts = [ 993 ];
# see https://github.com/NixOS/nixpkgs/pull/310857
networking.firewall.checkReversePath = false;
boot.kernel.sysctl = {
# enable forwarding packets
"net.ipv6.conf.all.forwarding" = 1;
"net.ipv4.conf.all.forwarding" = 1;
# enable NDP proxy for VPN clients
"net.ipv6.conf.all.proxy_ndp" = 1;
};
services.libreswan.configSetup = "listen-tcp=yes";
services.libreswan.connections.tunnel = ''
# server
left=203.0.113.2
leftid=@server
leftsubnet=::/0
leftupdown=${pkgs.writeScript "updown" ''
# act as NDP proxy for VPN clients
if test "$PLUTO_VERB" = up-client-v6; then
ip neigh add proxy "$PLUTO_PEER_CLIENT_NET" dev eth2
fi
if test "$PLUTO_VERB" = down-client-v6; then
ip neigh del proxy "$PLUTO_PEER_CLIENT_NET" dev eth2
fi
''}
# clients
right=%any
rightaddresspool=2001:db8:0:0:c::/97
modecfgdns=2001:db8::1
# clean up vanished clients
dpddelay=30
auto=add
keyexchange=ikev2
rekey=no
narrowing=yes
fragmentation=yes
authby=secret
leftikeport=993
retransmit-timeout=10s
'';
}
];
nodes.client = lib.mkMerge [
baseNetwork
baseTunnel
(setAddress4 "eth1" "192.168.1.2")
{
virtualisation.vlans = [ 2 ];
networking.defaultGateway = {
address = "192.168.1.1";
interface = "eth1";
};
services.libreswan.connections.tunnel = ''
# client
left=%defaultroute
leftid=@client
leftmodecfgclient=yes
leftsubnet=::/0
# server
right=203.0.113.2
rightid=@server
rightsubnet=::/0
auto=add
narrowing=yes
rekey=yes
fragmentation=yes
authby=secret
# fallback when UDP is blocked
enable-tcp=fallback
tcp-remoteport=993
retransmit-timeout=5s
'';
}
];
testScript =
''
def client_to_host(machine, msg: str):
"""
Sends a message from client to server
"""
machine.execute("nc -lu :: 1234 >/tmp/msg &")
client.sleep(1)
client.succeed(f"echo '{msg}' | nc -uw 0 {machine.name} 1234")
client.sleep(1)
machine.succeed(f"grep '{msg}' /tmp/msg")
def eavesdrop():
"""
Starts eavesdropping on the router
"""
match = "udp port 1234"
router.execute(f"tcpdump -i eth1 -c 1 -Avv {match} >/tmp/log &")
start_all()
with subtest("Network is up"):
client.wait_until_succeeds("ping -c1 server")
client.succeed("systemctl restart ipsec")
server.succeed("systemctl restart ipsec")
with subtest("Router can eavesdrop cleartext traffic"):
eavesdrop()
client_to_host(server, "I secretly love turnip")
router.sleep(1)
router.succeed("grep turnip /tmp/log")
with subtest("Libreswan is ready"):
client.wait_for_unit("ipsec")
server.wait_for_unit("ipsec")
client.succeed("ipsec checkconfig")
server.succeed("ipsec checkconfig")
with subtest("Client can't ping VPN host"):
client.fail("ping -c1 inner")
with subtest("Client can start the tunnel"):
client.succeed("ipsec start tunnel")
client.succeed("ip -6 addr show lo | grep -q 2001:db8:0:0:c")
with subtest("Client can ping VPN host"):
client.wait_until_succeeds("ping -c1 2001:db8::1")
client.succeed("ping -c1 inner")
with subtest("Eve no longer can eavesdrop"):
eavesdrop()
client_to_host(inner, "Just kidding, I actually like rhubarb")
router.sleep(1)
router.fail("grep rhubarb /tmp/log")
with subtest("TCP fallback is available"):
server.succeed("iptables -I nixos-fw -p udp -j DROP")
client.succeed("ipsec restart")
client.execute("ipsec start tunnel")
client.wait_until_succeeds("ping -c1 inner")
'';
}

View file

@ -3,7 +3,7 @@
# Eve can eavesdrop the plaintext traffic between Alice and Bob, but once they
# enable the secure tunnel Eve's spying becomes ineffective.
import ./make-test-python.nix ({ lib, pkgs, ... }:
{ lib, pkgs, ... }:
let
@ -133,4 +133,4 @@ in
eve.sleep(1)
eve.fail("grep rhubarb /tmp/log")
'';
})
}

View file

@ -41,14 +41,14 @@ let
in {
matomo = matomoTest pkgs.matomo // {
name = "matomo";
meta.maintainers = with maintainers; [ florianjacob kiwi mmilata twey boozedog ];
meta.maintainers = with maintainers; [ florianjacob mmilata twey boozedog ];
};
matomo-beta = matomoTest pkgs.matomo-beta // {
name = "matomo-beta";
meta.maintainers = with maintainers; [ florianjacob kiwi mmilata twey boozedog ];
meta.maintainers = with maintainers; [ florianjacob mmilata twey boozedog ];
};
matomo_5 = matomoTest pkgs.matomo_5 // {
name = "matomo-5";
meta.maintainers = with maintainers; [ florianjacob kiwi mmilata twey boozedog ] ++ lib.teams.flyingcircus.members;
meta.maintainers = with maintainers; [ florianjacob mmilata twey boozedog ] ++ lib.teams.flyingcircus.members;
};
}

View file

@ -11,7 +11,10 @@ import ./make-test-python.nix ({ pkgs, ...} : {
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ curl jq netdata ];
services.netdata.enable = true;
services.netdata = {
enable = true;
python.recommendedPythonPackages = true;
};
};
};

View file

@ -38,7 +38,6 @@ runTest ({ config, ... }: {
services.nextcloud = {
enable = true;
datadir = "/var/lib/nextcloud-data";
config.dbtableprefix = "nixos_";
autoUpdateApps = {
enable = true;
startAt = "20:00";

View file

@ -5,7 +5,7 @@ in
{
name = "private-gpt";
meta = with lib.maintainers; {
maintainers = [ drupol ];
maintainers = [ ];
};
nodes = {

View file

@ -0,0 +1,148 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-alertmanager";
nodes = {
prometheus = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
alertmanagers = [
{
scheme = "http";
static_configs = [
{
targets = [
"alertmanager:${toString config.services.prometheus.alertmanager.port}"
];
}
];
}
];
rules = [
''
groups:
- name: test
rules:
- alert: InstanceDown
expr: up == 0
for: 5s
labels:
severity: page
annotations:
summary: "Instance {{ $labels.instance }} down"
''
];
scrapeConfigs = [
{
job_name = "alertmanager";
static_configs = [
{
targets = [
"alertmanager:${toString config.services.prometheus.alertmanager.port}"
];
}
];
}
{
job_name = "node";
static_configs = [
{
targets = [
"node:${toString config.services.prometheus.exporters.node.port}"
];
}
];
}
];
};
};
alertmanager = { config, pkgs, ... }: {
services.prometheus.alertmanager = {
enable = true;
openFirewall = true;
configuration = {
global = {
resolve_timeout = "1m";
};
route = {
# Root route node
receiver = "test";
group_by = ["..."];
continue = false;
group_wait = "1s";
group_interval = "15s";
repeat_interval = "24h";
};
receivers = [
{
name = "test";
webhook_configs = [
{
url = "http://logger:6725";
send_resolved = true;
max_alerts = 0;
}
];
}
];
};
};
};
logger = { config, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 6725 ];
services.prometheus.alertmanagerWebhookLogger.enable = true;
};
};
testScript = ''
alertmanager.wait_for_unit("alertmanager")
alertmanager.wait_for_open_port(9093)
alertmanager.wait_until_succeeds("curl -s http://127.0.0.1:9093/-/ready")
#alertmanager.wait_until_succeeds("journalctl -o cat -u alertmanager.service | grep 'version=${pkgs.prometheus-alertmanager.version}'")
logger.wait_for_unit("alertmanager-webhook-logger")
logger.wait_for_open_port(6725)
prometheus.wait_for_unit("prometheus")
prometheus.wait_for_open_port(9090)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(up\{job=\"alertmanager\"\}==1)' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=sum(alertmanager_build_info)%20by%20(version)' | "
+ "jq '.data.result[0].metric.version' | grep '\"${pkgs.prometheus-alertmanager.version}\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(up\{job=\"node\"\}!=1)' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=alertmanager_notifications_total\{integration=\"webhook\"\}' | "
+ "jq '.data.result[0].value[1]' | grep -v '\"0\"'"
)
logger.wait_until_succeeds(
"journalctl -o cat -u alertmanager-webhook-logger.service | grep '\"alertname\":\"InstanceDown\"'"
)
'';
})

View file

@ -0,0 +1,116 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-config-reload";
nodes = {
prometheus = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
enableReload = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = [
{
targets = [
"prometheus:${toString config.services.prometheus.port}"
];
}
];
}
];
};
specialisation = {
"prometheus-config-change" = {
configuration = {
environment.systemPackages = [ pkgs.yq ];
# This configuration just adds a new prometheus job
# to scrape the node_exporter metrics of the s3 machine.
services.prometheus = {
scrapeConfigs = [
{
job_name = "node";
static_configs = [
{
targets = [ "node:${toString config.services.prometheus.exporters.node.port}" ];
}
];
}
];
};
};
};
};
};
};
testScript = ''
prometheus.wait_for_unit("prometheus")
prometheus.wait_for_open_port(9090)
# Check if switching to a NixOS configuration that changes the prometheus
# configuration reloads (instead of restarts) prometheus before the switch
# finishes successfully:
with subtest("config change reloads prometheus"):
import json
# We check if prometheus has finished reloading by looking for the message
# "Completed loading of configuration file" in the journal between the start
# and finish of switching to the new NixOS configuration.
#
# To mark the start we record the journal cursor before starting the switch:
cursor_before_switching = json.loads(
prometheus.succeed("journalctl -n1 -o json --output-fields=__CURSOR")
)["__CURSOR"]
# Now we switch:
prometheus_config_change = prometheus.succeed(
"readlink /run/current-system/specialisation/prometheus-config-change"
).strip()
prometheus.succeed(prometheus_config_change + "/bin/switch-to-configuration test")
# Next we retrieve all logs since the start of switching:
logs_after_starting_switching = prometheus.succeed(
"""
journalctl --after-cursor='{cursor_before_switching}' -o json --output-fields=MESSAGE
""".format(
cursor_before_switching=cursor_before_switching
)
)
# Finally we check if the message "Completed loading of configuration file"
# occurs before the "finished switching to system configuration" message:
finished_switching_msg = (
"finished switching to system configuration " + prometheus_config_change
)
reloaded_before_switching_finished = False
finished_switching = False
for log_line in logs_after_starting_switching.split("\n"):
msg = json.loads(log_line)["MESSAGE"]
if "Completed loading of configuration file" in msg:
reloaded_before_switching_finished = True
if msg == finished_switching_msg:
finished_switching = True
break
assert reloaded_before_switching_finished
assert finished_switching
# Check if the reloaded config includes the new node job:
prometheus.succeed(
"""
curl -sf http://127.0.0.1:9090/api/v1/status/config \
| jq -r .data.yaml \
| yq '.scrape_configs | any(.job_name == "node")' \
| grep true
"""
)
'';
})

View file

@ -0,0 +1,13 @@
{ system ? builtins.currentSystem
, config ? { }
, pkgs ? import ../../.. { inherit system config; }
}:
{
alertmanager = import ./alertmanager.nix { inherit system pkgs; };
config-reload = import ./config-reload.nix { inherit system pkgs; };
federation = import ./federation.nix { inherit system pkgs; };
prometheus-pair = import ./prometheus-pair.nix { inherit system pkgs; };
pushgateway = import ./pushgateway.nix { inherit system pkgs; };
remote-write = import ./remote-write.nix { inherit system pkgs; };
}

View file

@ -0,0 +1,213 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-federation";
nodes = {
global1 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "federate";
honor_labels = true;
metrics_path = "/federate";
params = {
"match[]" = [
"{job=\"node\"}"
"{job=\"prometheus\"}"
];
};
static_configs = [
{
targets = [
"prometheus1:${toString config.services.prometheus.port}"
"prometheus2:${toString config.services.prometheus.port}"
];
}
];
}
{
job_name = "prometheus";
static_configs = [
{
targets = [
"global1:${toString config.services.prometheus.port}"
"global2:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
global2 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "federate";
honor_labels = true;
metrics_path = "/federate";
params = {
"match[]" = [
"{job=\"node\"}"
"{job=\"prometheus\"}"
];
};
static_configs = [
{
targets = [
"prometheus1:${toString config.services.prometheus.port}"
"prometheus2:${toString config.services.prometheus.port}"
];
}
];
}
{
job_name = "prometheus";
static_configs = [
{
targets = [
"global1:${toString config.services.prometheus.port}"
"global2:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
prometheus1 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "node";
static_configs = [
{
targets = [
"node1:${toString config.services.prometheus.exporters.node.port}"
];
}
];
}
{
job_name = "prometheus";
static_configs = [
{
targets = [
"prometheus1:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
prometheus2 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "node";
static_configs = [
{
targets = [
"node2:${toString config.services.prometheus.exporters.node.port}"
];
}
];
}
{
job_name = "prometheus";
static_configs = [
{
targets = [
"prometheus2:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
node1 = { config, pkgs, ... }: {
services.prometheus.exporters.node = {
enable = true;
openFirewall = true;
};
};
node2 = { config, pkgs, ... }: {
services.prometheus.exporters.node = {
enable = true;
openFirewall = true;
};
};
};
testScript = ''
for machine in node1, node2:
machine.wait_for_unit("prometheus-node-exporter")
machine.wait_for_open_port(9100)
for machine in prometheus1, prometheus2, global1, global2:
machine.wait_for_unit("prometheus")
machine.wait_for_open_port(9090)
# Verify both servers got the same data from the exporter
for machine in prometheus1, prometheus2:
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(up\{job=\"node\"\})' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(prometheus_build_info)' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
for machine in global1, global2:
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(up\{job=\"node\"\})' | "
+ "jq '.data.result[0].value[1]' | grep '\"2\"'"
)
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(prometheus_build_info)' | "
+ "jq '.data.result[0].value[1]' | grep '\"4\"'"
)
'';
})

View file

@ -0,0 +1,87 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-pair";
nodes = {
prometheus1 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = [
{
targets = [
"prometheus1:${toString config.services.prometheus.port}"
"prometheus2:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
prometheus2 = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = [
{
targets = [
"prometheus1:${toString config.services.prometheus.port}"
"prometheus2:${toString config.services.prometheus.port}"
];
}
];
}
];
};
};
};
testScript = ''
for machine in prometheus1, prometheus2:
machine.wait_for_unit("prometheus")
machine.wait_for_open_port(9090)
machine.wait_until_succeeds("journalctl -o cat -u prometheus.service | grep 'version=${pkgs.prometheus.version}'")
machine.wait_until_succeeds("curl -sSf http://localhost:9090/-/healthy")
# Prometheii ready - run some queries
for machine in prometheus1, prometheus2:
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=prometheus_build_info\{instance=\"prometheus1:9090\",version=\"${pkgs.prometheus.version}\"\}' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=prometheus_build_info\{instance=\"prometheus1:9090\"\}' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=sum(prometheus_build_info)%20by%20(version)' | "
+ "jq '.data.result[0].metric.version' | grep '\"${pkgs.prometheus.version}\"'"
)
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=sum(prometheus_build_info)%20by%20(version)' | "
+ "jq '.data.result[0].value[1]' | grep '\"2\"'"
)
prometheus1.log(prometheus1.succeed("systemd-analyze security prometheus.service | grep -v ''"))
'';
})

View file

@ -0,0 +1,94 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-pushgateway";
nodes = {
prometheus = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
scrapeConfigs = [
{
job_name = "pushgateway";
static_configs = [
{
targets = [
"pushgateway:9091"
];
}
];
}
];
};
};
pushgateway = { config, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 9091 ];
services.prometheus.pushgateway = {
enable = true;
};
};
client = { config, pkgs, ... }: {
};
};
testScript = ''
pushgateway.wait_for_unit("pushgateway")
pushgateway.wait_for_open_port(9091)
pushgateway.wait_until_succeeds("curl -s http://127.0.0.1:9091/-/ready")
pushgateway.wait_until_succeeds("journalctl -o cat -u pushgateway.service | grep 'version=${pkgs.prometheus-pushgateway.version}'")
prometheus.wait_for_unit("prometheus")
prometheus.wait_for_open_port(9090)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=count(up\{job=\"pushgateway\"\})' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=sum(pushgateway_build_info)%20by%20(version)' | "
+ "jq '.data.result[0].metric.version' | grep '\"${pkgs.prometheus-pushgateway.version}\"'"
)
client.wait_for_unit("network-online.target")
# Add a metric and check in Prometheus
client.wait_until_succeeds(
"echo 'some_metric 3.14' | curl --data-binary @- http://pushgateway:9091/metrics/job/some_job"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=some_metric' | "
+ "jq '.data.result[0].value[1]' | grep '\"3.14\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=absent(some_metric)' | "
+ "jq '.data.result[0].value[1]' | grep 'null'"
)
# Delete the metric, check not in Prometheus
client.wait_until_succeeds(
"curl -X DELETE http://pushgateway:9091/metrics/job/some_job"
)
prometheus.wait_until_fails(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=some_metric' | "
+ "jq '.data.result[0].value[1]' | grep '\"3.14\"'"
)
prometheus.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=absent(some_metric)' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
'';
})

View file

@ -0,0 +1,73 @@
import ../make-test-python.nix ({ lib, pkgs, ... }:
{
name = "prometheus-remote-write";
nodes = {
receiver = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
extraFlags = [ "--web.enable-remote-write-receiver" ];
};
};
prometheus = { config, pkgs, ... }: {
environment.systemPackages = [ pkgs.jq ];
networking.firewall.allowedTCPPorts = [ config.services.prometheus.port ];
services.prometheus = {
enable = true;
globalConfig.scrape_interval = "2s";
remoteWrite = [
{
url = "http://receiver:9090/api/v1/write";
}
];
scrapeConfigs = [
{
job_name = "node";
static_configs = [
{
targets = [
"node:${toString config.services.prometheus.exporters.node.port}"
];
}
];
}
];
};
};
node = { config, pkgs, ... }: {
services.prometheus.exporters.node = {
enable = true;
openFirewall = true;
};
};
};
testScript = ''
node.wait_for_unit("prometheus-node-exporter")
node.wait_for_open_port(9100)
for machine in prometheus, receiver:
machine.wait_for_unit("prometheus")
machine.wait_for_open_port(9090)
# Verify both servers got the same data from the exporter
for machine in prometheus, receiver:
machine.wait_until_succeeds(
"curl -sf 'http://127.0.0.1:9090/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
)
'';
})

View file

@ -0,0 +1,95 @@
import ./make-test-python.nix (
{ pkgs, lib, ... }:
{
name = "tandoor-recipes-script-name";
nodes.machine =
{ pkgs, nodes, ... }:
{
services.tandoor-recipes = {
enable = true;
extraConfig = {
SCRIPT_NAME = "/any/path";
STATIC_URL = "${nodes.machine.services.tandoor-recipes.extraConfig.SCRIPT_NAME}/static/";
};
};
};
testScript =
{ nodes, ... }:
let
inherit (nodes.machine.services.tandoor-recipes) address port;
inherit (nodes.machine.services.tandoor-recipes.extraConfig) SCRIPT_NAME;
in
''
from html.parser import HTMLParser
origin_url = "http://${address}:${toString port}"
base_url = f"{origin_url}${SCRIPT_NAME}"
login_path = "/admin/login/"
login_url = f"{base_url}{login_path}"
cookie_jar_path = "/tmp/cookies.txt"
curl = f"curl --cookie {cookie_jar_path} --cookie-jar {cookie_jar_path} --fail --header 'Origin: {origin_url}' --show-error --silent"
print("Wait for the service to respond")
machine.wait_for_unit("tandoor-recipes.service")
machine.wait_until_succeeds(f"{curl} {login_url}")
username = "username"
password = "password"
print("Create admin user")
machine.succeed(
f"DJANGO_SUPERUSER_PASSWORD='{password}' /var/lib/tandoor-recipes/tandoor-recipes-manage createsuperuser --no-input --username='{username}' --email=nobody@example.com"
)
print("Get CSRF token for later requests")
csrf_token = machine.succeed(f"grep csrftoken {cookie_jar_path} | cut --fields=7").rstrip()
print("Log in as admin user")
machine.succeed(
f"{curl} --data 'csrfmiddlewaretoken={csrf_token}' --data 'username={username}' --data 'password={password}' {login_url}"
)
print("Get the contents of the logged in main page")
logged_in_page = machine.succeed(f"{curl} --location {base_url}")
class UrlParser(HTMLParser):
def __init__(self):
super().__init__()
self.urls: list[str] = []
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
if tag == "form":
for name, value in attrs:
if name == "action" and value is not None:
assert not value.endswith(login_path)
break
if tag != "a":
return
for name, value in attrs:
if name == "href" and value is not None:
if value.startswith(base_url):
self.urls.append(value)
elif value.startswith("/"):
self.urls.append(f"{origin_url}{value}")
else:
print("Ignoring external URL: {value}")
break
parser = UrlParser()
parser.feed(logged_in_page)
for url in parser.urls:
with subtest(f"Verify that {url} can be reached"):
machine.succeed(f"{curl} {url}")
'';
meta.maintainers = with lib.maintainers; [ l0b0 ];
}
)

View file

@ -212,8 +212,6 @@ in import ./make-test-python.nix {
};
testScript = { nodes, ... } : ''
import json
# Before starting the other machines we first make sure that our S3 service is online
# and has a bucket added for thanos:
s3.start()
@ -289,61 +287,5 @@ in import ./make-test-python.nix {
+ "jq .thanos.labels.some_label | "
+ "grep 'required by thanos'"
)
# Check if switching to a NixOS configuration that changes the prometheus
# configuration reloads (instead of restarts) prometheus before the switch
# finishes successfully:
with subtest("config change reloads prometheus"):
# We check if prometheus has finished reloading by looking for the message
# "Completed loading of configuration file" in the journal between the start
# and finish of switching to the new NixOS configuration.
#
# To mark the start we record the journal cursor before starting the switch:
cursor_before_switching = json.loads(
prometheus.succeed("journalctl -n1 -o json --output-fields=__CURSOR")
)["__CURSOR"]
# Now we switch:
prometheus_config_change = prometheus.succeed(
"readlink /run/current-system/specialisation/prometheus-config-change"
).strip()
prometheus.succeed(prometheus_config_change + "/bin/switch-to-configuration test")
# Next we retrieve all logs since the start of switching:
logs_after_starting_switching = prometheus.succeed(
"""
journalctl --after-cursor='{cursor_before_switching}' -o json --output-fields=MESSAGE
""".format(
cursor_before_switching=cursor_before_switching
)
)
# Finally we check if the message "Completed loading of configuration file"
# occurs before the "finished switching to system configuration" message:
finished_switching_msg = (
"finished switching to system configuration " + prometheus_config_change
)
reloaded_before_switching_finished = False
finished_switching = False
for log_line in logs_after_starting_switching.split("\n"):
msg = json.loads(log_line)["MESSAGE"]
if "Completed loading of configuration file" in msg:
reloaded_before_switching_finished = True
if msg == finished_switching_msg:
finished_switching = True
break
assert reloaded_before_switching_finished
assert finished_switching
# Check if the reloaded config includes the new s3-node_exporter job:
prometheus.succeed(
"""
curl -sf http://127.0.0.1:${toString queryPort}/api/v1/status/config \
| jq -r .data.yaml \
| yq '.scrape_configs | any(.job_name == "s3-node_exporter")' \
| grep true
"""
)
'';
}

View file

@ -7,7 +7,7 @@ with import ../lib/testing-python.nix { inherit system pkgs; };
makeTest {
name = "tigervnc";
meta = with pkgs.lib.maintainers; {
maintainers = [ lheckemann ];
maintainers = [ ];
};
nodes = {

View file

@ -1,6 +1,6 @@
import ./make-test-python.nix ({ pkgs, ...} : {
name = "timezone";
meta.maintainers = with pkgs.lib.maintainers; [ lheckemann ];
meta.maintainers = with pkgs.lib.maintainers; [ ];
nodes = {
node_eutz = { pkgs, ... }: {

View file

@ -0,0 +1,96 @@
let
certs = import ./common/acme/server/snakeoil-certs.nix;
domain = certs.domain;
in
{
name = "wstunnel";
nodes = {
server = {
virtualisation.vlans = [ 1 ];
security.pki.certificateFiles = [ certs.ca.cert ];
networking = {
useNetworkd = true;
useDHCP = false;
firewall.enable = false;
};
systemd.network.networks."01-eth1" = {
name = "eth1";
networkConfig.Address = "10.0.0.1/24";
};
services.wstunnel = {
enable = true;
servers.my-server = {
listen = {
host = "10.0.0.1";
port = 443;
};
tlsCertificate = certs.${domain}.cert;
tlsKey = certs.${domain}.key;
};
};
};
client = {
virtualisation.vlans = [ 1 ];
security.pki.certificateFiles = [ certs.ca.cert ];
networking = {
useNetworkd = true;
useDHCP = false;
firewall.enable = false;
extraHosts = ''
10.0.0.1 ${domain}
'';
};
systemd.network.networks."01-eth1" = {
name = "eth1";
networkConfig.Address = "10.0.0.2/24";
};
services.wstunnel = {
enable = true;
clients.my-client = {
autoStart = false;
connectTo = "wss://${domain}:443";
localToRemote = [
"tcp://8080:localhost:2080"
];
remoteToLocal = [
"tcp://2081:localhost:8081"
];
};
};
};
};
testScript = /* python */ ''
start_all()
server.wait_for_unit("wstunnel-server-my-server.service")
client.wait_for_open_port(443, "10.0.0.1")
client.systemctl("start wstunnel-client-my-client.service")
client.wait_for_unit("wstunnel-client-my-client.service")
with subtest("connection from client to server"):
server.succeed("nc -l 2080 >/tmp/msg &")
client.sleep(1)
client.succeed('nc -w1 localhost 8080 <<<"Hello from client"')
server.succeed('grep "Hello from client" /tmp/msg')
with subtest("connection from server to client"):
client.succeed("nc -l 8081 >/tmp/msg &")
server.sleep(1)
server.succeed('nc -w1 localhost 2081 <<<"Hello from server"')
client.succeed('grep "Hello from server" /tmp/msg')
client.systemctl("stop wstunnel-client-my-client.service")
'';
}

View file

@ -202,7 +202,7 @@ stdenv.mkDerivation rec {
# Documentation.
cc-by-30
];
maintainers = with maintainers; [ lheckemann veprbl wegank ];
maintainers = with maintainers; [ veprbl wegank ];
platforms = platforms.unix;
};
}

View file

@ -27,11 +27,11 @@
stdenv.mkDerivation rec {
pname = "bitwig-studio";
version = "5.1.8";
version = "5.1.9";
src = fetchurl {
url = "https://downloads.bitwig.com/stable/${version}/${pname}-${version}.deb";
sha256 = "sha256-KxNLae/uTYL1m/X+/7wr7hhKfw31NpB9Mw9RzfrTuus=";
url = "https://www.bitwig.com/dl/Bitwig%20Studio/${version}/installer_linux/";
hash = "sha256-J5kLqXCMnGb0ZMhES6PQIPjN51ptlBGj4Fy8qSzJ6Qg=";
};
nativeBuildInputs = [ dpkg makeWrapper wrapGAppsHook3 ];

View file

@ -8,12 +8,12 @@
, samplerateSupport ? jackSupport, libsamplerate ? null
, ossSupport ? false, alsa-oss ? null
, pulseaudioSupport ? config.pulseaudio or false, libpulseaudio ? null
, sndioSupport ? false, sndio ? null
, mprisSupport ? stdenv.isLinux, systemd ? null
# TODO: add these
#, artsSupport
#, roarSupport
#, sndioSupport
#, sunSupport
#, waveoutSupport
@ -59,11 +59,11 @@ let
(mkFlag samplerateSupport "CONFIG_SAMPLERATE=y" libsamplerate)
(mkFlag ossSupport "CONFIG_OSS=y" alsa-oss)
(mkFlag pulseaudioSupport "CONFIG_PULSE=y" libpulseaudio)
(mkFlag sndioSupport "CONFIG_SNDIO=y" sndio)
(mkFlag mprisSupport "CONFIG_MPRIS=y" systemd)
#(mkFlag artsSupport "CONFIG_ARTS=y")
#(mkFlag roarSupport "CONFIG_ROAR=y")
#(mkFlag sndioSupport "CONFIG_SNDIO=y")
#(mkFlag sunSupport "CONFIG_SUN=y")
#(mkFlag waveoutSupport "CONFIG_WAVEOUT=y")
@ -92,13 +92,13 @@ in
stdenv.mkDerivation rec {
pname = "cmus";
version = "2.10.0-unstable-2023-11-05";
version = "2.11.0";
src = fetchFromGitHub {
owner = "cmus";
repo = "cmus";
rev = "23afab39902d3d97c47697196b07581305337529";
sha256 = "sha256-pxDIYbeJMoaAuErCghWJpDSh1WbYbhgJ7+ca5WLCrOs=";
rev = "v${version}";
hash = "sha256-kUJC+ORLkYD57mPL/1p5VCm9yiNzVdOZhxp7sVP6oMw=";
};
nativeBuildInputs = [ pkg-config ];

View file

@ -23,13 +23,13 @@ with lib.strings;
let
version = "2.72.14";
version = "2.74.6";
src = fetchFromGitHub {
owner = "grame-cncm";
repo = "faust";
rev = version;
sha256 = "sha256-RdSXiOYwKsfyrfHEughCeSwa9VFM6/3pMg54yCMpzLU=";
sha256 = "sha256-0r7DjTrsNKZ5ZmWoA+Y9OXyJFUiUFZiPQb1skXXWYTw=";
fetchSubmodules = true;
};

View file

@ -1,13 +1,13 @@
{ stdenv, lib, fetchFromGitHub, faust2jaqt, faust2lv2 }:
stdenv.mkDerivation rec {
pname = "faustPhysicalModeling";
version = "2.72.14";
version = "2.74.6";
src = fetchFromGitHub {
owner = "grame-cncm";
repo = "faust";
rev = version;
sha256 = "sha256-UBMVU2oAfoAaSQXxZxV+LFq8dyb5dvy/0cCG4XywZVc=";
sha256 = "sha256-2qgw7pauDZBvEb5iySNiq2Fq+T+qw+AjVTwxaSQ9Eko=";
};
buildInputs = [ faust2jaqt faust2lv2 ];

View file

@ -15,6 +15,7 @@
, desktop-file-utils
, dbus
, openssl
, glib-networking
, sqlite
, gst_all_1
, wrapGAppsHook4
@ -22,19 +23,19 @@
stdenv.mkDerivation rec {
pname = "gnome-podcasts";
version = "0.6.1";
version = "0.7.1";
src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "World";
repo = "podcasts";
rev = version;
hash = "sha256-LPwCYgAFgUMFQZ0i4ldiuGYGMMWcMqYct3/o7eTIhmU=";
hash = "sha256-KCjHT/4AeJ+RXCtawkhs6f4D8NCJotYIPk3tGr5YG9M=";
};
cargoDeps = rustPlatform.fetchCargoTarball {
inherit pname version src;
hash = "sha256-n3ZcUhqn1rvvgkBKSKvH0b8wbOCqcBGwpb2OqMe8h0s=";
hash = "sha256-XTfKqKs7874ak7Lzscxw8E2qcnJOWMZaaol8TpIB6Vw=";
};
nativeBuildInputs = [
@ -56,6 +57,7 @@ stdenv.mkDerivation rec {
gettext
dbus
openssl
glib-networking
sqlite
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
@ -66,13 +68,13 @@ stdenv.mkDerivation rec {
# tests require network
doCheck = false;
meta = with lib; {
meta = {
description = "Listen to your favorite podcasts";
mainProgram = "gnome-podcasts";
homepage = "https://apps.gnome.org/Podcasts/";
license = licenses.gpl3Plus;
maintainers = teams.gnome.members;
platforms = platforms.unix;
license = lib.licenses.gpl3Plus;
maintainers = lib.teams.gnome.members;
platforms = lib.platforms.unix;
broken = stdenv.isDarwin; # never built on Hydra https://hydra.nixos.org/job/nixpkgs/trunk/gnome-podcasts.x86_64-darwin
};
}

View file

@ -10,18 +10,18 @@
buildGoModule rec {
pname = "go-musicfox";
version = "4.4.1";
version = "4.5.3";
src = fetchFromGitHub {
owner = "go-musicfox";
repo = "go-musicfox";
rev = "v${version}";
hash = "sha256-pIfQ0ufn8W0opm+N6IPFBPWNxNWMOU7FudPtIFop51c=";
hash = "sha256-qf4XAAfWWlHAnNGhXaYpnjj+2z+/lWOHaTyv8R4UDgQ=";
};
deleteVendor = true;
vendorHash = "sha256-ey78zeCSEuRgteG5ZRb4uO88E6lwEgqSxKfjJg3NGT4=";
vendorHash = "sha256-oz/kVp/Jj2Lmo19UFOn2VPD/iWbSRCbmKy8fK8RdkYs=";
subPackages = [ "cmd/musicfox.go" ];

View file

@ -16,7 +16,7 @@ stdenv.mkDerivation {
meta = with lib; {
homepage = "https://www.parabola.me.uk/alsa/pmidi.html";
description = "Straightforward command line program to play midi files through the ALSA sequencer";
maintainers = with maintainers; [ lheckemann ];
maintainers = with maintainers; [ ];
license = licenses.gpl2;
mainProgram = "pmidi";
};

View file

@ -52,7 +52,7 @@ buildNpmPackage rec {
description = "Pocket Casts webapp, packaged for the Linux Desktop";
homepage = "https://github.com/felicianotech/pocket-casts-desktop-app";
license = licenses.mit;
maintainers = with maintainers; [ wolfangaukang ];
maintainers = [ ];
mainProgram = "pocket-casts";
platforms = platforms.linux;
};

View file

@ -1,4 +1,5 @@
{ fetchFromGitHub
{ stdenvNoCC
, fetchFromGitHub
, lib
, cmake
, mkDerivation
@ -26,12 +27,18 @@ mkDerivation rec {
installFlags = [ "DESTDIR=$(out)" ];
postInstall = lib.optionalString stdenvNoCC.isDarwin ''
mkdir -p $out/Applications
mv $out/bin/spotify-qt.app $out/Applications
ln $out/Applications/spotify-qt.app/Contents/MacOS/spotify-qt $out/bin/spotify-qt
'';
meta = with lib; {
description = "Lightweight unofficial Spotify client using Qt";
mainProgram = "spotify-qt";
homepage = "https://github.com/kraxarn/spotify-qt";
license = licenses.gpl3Only;
maintainers = with maintainers; [ ];
maintainers = with maintainers; [ iivusly ];
platforms = platforms.unix;
};
}

View file

@ -14,14 +14,14 @@ let
# If an update breaks things, one of those might have valuable info:
# https://aur.archlinux.org/packages/spotify/
# https://community.spotify.com/t5/Desktop-Linux
version = "1.2.31.1205.g4d59ad7c";
version = "1.2.37.701.ge66eb7bc";
# To get the latest stable revision:
# curl -H 'X-Ubuntu-Series: 16' 'https://api.snapcraft.io/api/v1/snaps/details/spotify?channel=stable' | jq '.download_url,.version,.last_updated'
# To get general information:
# curl -H 'Snap-Device-Series: 16' 'https://api.snapcraft.io/v2/snaps/info/spotify' | jq '.'
# More examples of api usage:
# https://github.com/canonical-websites/snapcraft.io/blob/master/webapp/publisher/snaps/views.py
rev = "75";
rev = "76";
deps = [
alsa-lib
@ -86,8 +86,9 @@ stdenv.mkDerivation {
# spotify ourselves:
# https://community.spotify.com/t5/Desktop-Linux/Redistribute-Spotify-on-Linux-Distributions/td-p/1695334
src = fetchurl {
name = "spotify-${version}-${rev}.snap";
url = "https://api.snapcraft.io/api/v1/snaps/download/pOBIoZ2LrCB3rDohMxoYGnbN14EHOgD7_${rev}.snap";
hash = "sha512-o4iLcbNqbsxo9YJMy0SXO7Udv4CMhhBcsf53UuqWKFFWY/jKVN+Lb+dB7Jf9+UowpmbrP44w97Oi+dnbfFXYjQ==";
hash = "sha512-k7aw1QM3NCFkm0tXcHgYyeEBagGFpCL6JdWlFruJszPloiCy5vopOsD4PdqyiSEs0rSUP0rLxX2UBs3XuI5cUA==";
};
nativeBuildInputs = [ wrapGAppsHook3 makeShellWrapper squashfsTools ];
@ -120,11 +121,15 @@ stdenv.mkDerivation {
# Prevent double wrapping
dontWrapGApps = true;
env = rec {
libdir = "${placeholder "out"}/lib/spotify";
librarypath = "${lib.makeLibraryPath deps}:${libdir}";
};
installPhase =
''
runHook preInstall
libdir=$out/lib/spotify
mkdir -p $libdir
mv ./usr/* $out/
@ -147,16 +152,6 @@ stdenv.mkDerivation {
--interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--set-rpath $rpath $out/share/spotify/spotify
librarypath="${lib.makeLibraryPath deps}:$libdir"
wrapProgramShell $out/share/spotify/spotify \
''${gappsWrapperArgs[@]} \
${lib.optionalString (deviceScaleFactor != null) ''
--add-flags "--force-device-scale-factor=${toString deviceScaleFactor}" \
''} \
--prefix LD_LIBRARY_PATH : "$librarypath" \
--prefix PATH : "${gnome.zenity}/bin" \
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--enable-features=UseOzonePlatform --ozone-platform=wayland}}"
# fix Icon line in the desktop file (#48062)
sed -i "s:^Icon=.*:Icon=spotify-client:" "$out/share/spotify/spotify.desktop"
@ -175,6 +170,21 @@ stdenv.mkDerivation {
runHook postInstall
'';
fixupPhase = ''
runHook preFixup
wrapProgramShell $out/share/spotify/spotify \
''${gappsWrapperArgs[@]} \
${lib.optionalString (deviceScaleFactor != null) ''
--add-flags "--force-device-scale-factor=${toString deviceScaleFactor}" \
''} \
--prefix LD_LIBRARY_PATH : "$librarypath" \
--prefix PATH : "${gnome.zenity}/bin" \
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--enable-features=UseOzonePlatform --ozone-platform=wayland}}"
runHook postFixup
'';
meta = meta // {
maintainers = with lib.maintainers; [ eelco ftrvxmtrx sheenobu timokau ma27 ];
};

View file

@ -152,7 +152,7 @@ stdenv.mkDerivation rec {
mainProgram = "tenacity";
homepage = "https://tenacityaudio.org/";
license = licenses.gpl2Plus;
maintainers = with maintainers; [ irenes lheckemann ];
maintainers = with maintainers; [ irenes ];
platforms = platforms.linux;
};
}

View file

@ -38,11 +38,11 @@ let
in
stdenv.mkDerivation rec {
pname = "bisq-desktop";
version = "1.9.15";
version = "1.9.16";
src = fetchurl {
url = "https://github.com/bisq-network/bisq/releases/download/v${version}/Bisq-64bit-${version}.deb";
sha256 = "0bz4yzfrzn9rwsmwwnsqdgxsqd42dyiz3vxi53qxj36h49nh8lzg";
sha256 = "sha256-DxYgZgDa3vOHj7svJqu/pdyXKZ+uBTy35Fchw49xxoA=";
};
nativeBuildInputs = [

View file

@ -2,16 +2,16 @@
buildGoModule rec {
pname = "dcrwallet";
version = "2.0.2";
version = "2.0.3";
src = fetchFromGitHub {
owner = "decred";
repo = "dcrwallet";
rev = "release-v${version}";
hash = "sha256-fsmil9YQNvXDyBxyt+Ei3F5U/dvbrzbZ01+v9o3+jVY=";
hash = "sha256-sRwGpOVydfZjgo7W+4RsHC4JElPyilbV5xhcHxPh2Wc=";
};
vendorHash = "sha256-ehtgsBCFzMft8285IjpsQ6y9HPb/UpZmcj9X4m8ZKXo=";
vendorHash = "sha256-lVVIS3FL8XwthCpzRKdw59NVtHVxXQ0ouD7jYQzOecM=";
subPackages = [ "." ];

View file

@ -5,13 +5,13 @@
buildGoModule rec {
pname = "lndhub-go";
version = "1.0.0";
version = "1.0.1";
src = fetchFromGitHub {
owner = "getAlby";
repo = "lndhub.go";
rev = version;
sha256 = "sha256-PHBzM/lYYu6hXa5jiFQR/K5j+vmxaYH7xuoxOhFbhMk=";
sha256 = "sha256-YOLqMIfZSGD+AOng1XWCBlzaHkPnQc+2kmDXF2fh+ps=";
};
vendorHash = "sha256-Vo29w04cRW0syD2tjieKVeZ3srFNuEC3T17birVWn6k=";

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