Project import generated by Copybara.

GitOrigin-RevId: 1925c603f17fc89f4c8f6bf6f631a802ad85d784
This commit is contained in:
Default email 2024-09-26 11:04:55 +00:00
parent 159e378cbb
commit 7e47f3658e
6010 changed files with 77932 additions and 31702 deletions

View file

@ -171,3 +171,6 @@ cffc27daf06c77c0d76bc35d24b929cb9d68c3c9
# nixos/kanidm: inherit lib, nixfmt # nixos/kanidm: inherit lib, nixfmt
8f18393d380079904d072007fb19dc64baef0a3a 8f18393d380079904d072007fb19dc64baef0a3a
# fetchurl: nixfmt-rfc-style
ce21e97a1f20dee15da85c084f9d1148d84f853b

View file

@ -120,7 +120,8 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
/nixos/modules/system/boot/loader/systemd-boot @JulienMalka /nixos/modules/system/boot/loader/systemd-boot @JulienMalka
# Images and installer media # Images and installer media
/nixos/modules/installer/cd-dvd/ /nixos/modules/profiles/installation-device.nix @ElvishJerricco
/nixos/modules/installer/cd-dvd/ @ElvishJerricco
/nixos/modules/installer/sd-card/ /nixos/modules/installer/sd-card/
# Updaters # Updaters
@ -162,7 +163,7 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
# C compilers # C compilers
/pkgs/development/compilers/gcc /pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @RossComputerGuy /pkgs/development/compilers/llvm @alyssais @RossComputerGuy
/pkgs/development/compilers/emscripten @raitobezarius /pkgs/development/compilers/emscripten @raitobezarius
/doc/languages-frameworks/emscripten.section.md @raitobezarius /doc/languages-frameworks/emscripten.section.md @raitobezarius
@ -336,9 +337,6 @@ pkgs/by-name/fo/forgejo/ @adamcstephens @bendlas @emilylange
/pkgs/build-support/node/fetch-npm-deps @winterqt /pkgs/build-support/node/fetch-npm-deps @winterqt
/doc/languages-frameworks/javascript.section.md @winterqt /doc/languages-frameworks/javascript.section.md @winterqt
# environment.noXlibs option aka NoX
/nixos/modules/config/no-x-libs.nix @SuperSandro2000
# OCaml # OCaml
/pkgs/build-support/ocaml @ulrikstrid /pkgs/build-support/ocaml @ulrikstrid
/pkgs/development/compilers/ocaml @ulrikstrid /pkgs/development/compilers/ocaml @ulrikstrid

View file

@ -1,6 +1,9 @@
ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com> ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com>
Anderson Torres <torres.anderson.85@protonmail.com> Anderson Torres <torres.anderson.85@protonmail.com>
Atemu <git@atemu.net> <atemu.main@gmail.com> Atemu <git@atemu.net> <atemu.main@gmail.com>
Christina Sørensen <christina@cafkafk.com>
Christina Sørensen <christina@cafkafk.com> <christinaafk@gmail.com>
Christina Sørensen <christina@cafkafk.com> <89321978+cafkafk@users.noreply.github.com>
Daniel Løvbrøtte Olsen <me@dandellion.xyz> <daniel.olsen99@gmail.com> Daniel Løvbrøtte Olsen <me@dandellion.xyz> <daniel.olsen99@gmail.com>
Fabian Affolter <mail@fabian-affolter.ch> <fabian@affolter-engineering.ch> Fabian Affolter <mail@fabian-affolter.ch> <fabian@affolter-engineering.ch>
goatastronaut0212 <goatastronaut0212@outlook.com> <goatastronaut0212@proton.me> goatastronaut0212 <goatastronaut0212@outlook.com> <goatastronaut0212@proton.me>

View file

@ -2,10 +2,20 @@
This directory houses the sources files for the Nixpkgs reference manual. This directory houses the sources files for the Nixpkgs reference manual.
Going forward, it should only contain [reference](https://nix.dev/contributing/documentation/diataxis#reference) documentation. > [!IMPORTANT]
For tutorials, guides and explanations, contribute to <https://nix.dev/> instead. > We are actively restructuring our documentation to follow the [Diátaxis framework](https://diataxis.fr/)
>
> Going forward, this directory should **only** contain [reference documentation](https://nix.dev/contributing/documentation/diataxis#reference).
> For tutorials, guides and explanations, contribute to <https://nix.dev/> instead.
>
> We are actively working to generate **all** reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code.
> This also provides the benefit of using `:doc` in the `nix repl` to view reference documentation locally on the fly.
For documentation only relevant for contributors, use Markdown files and code comments in the source code. For documentation only relevant for contributors, use Markdown files next to the source and regular code comments.
> [!TIP]
> Feedback for improving support for parsing and rendering doc-comments is highly appreciated.
> [Open an issue](https://github.com/NixOS/nixpkgs/issues/new?labels=6.topic%3A+documentation&title=Doc%3A+) to request bugfixes or new features.
Rendered documentation: Rendered documentation:
- [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/) - [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/)

View file

@ -453,7 +453,7 @@ See [](#ex-dockerTools-streamLayeredImage-exploringlayers) to understand how the
`streamLayeredImage` allows scripts to be run when creating the additional layer with symlinks, allowing custom behaviour to affect the final results of the image (see the documentation of the `extraCommands` and `fakeRootCommands` attributes). `streamLayeredImage` allows scripts to be run when creating the additional layer with symlinks, allowing custom behaviour to affect the final results of the image (see the documentation of the `extraCommands` and `fakeRootCommands` attributes).
The resulting repository tarball will list a single image as specified by the `name` and `tag` attributes. The resulting repository tarball will list a single image as specified by the `name` and `tag` attributes.
By default, that image will use a static creation date (see documentation for the `created` attribute). By default, that image will use a static creation date (see documentation for the `created` and `mtime` attributes).
This allows the function to produce reproducible images. This allows the function to produce reproducible images.
### Inputs {#ssec-pkgs-dockerTools-streamLayeredImage-inputs} ### Inputs {#ssec-pkgs-dockerTools-streamLayeredImage-inputs}
@ -516,6 +516,7 @@ This allows the function to produce reproducible images.
`created` (String; _optional_) `created` (String; _optional_)
: Specifies the time of creation of the generated image. : Specifies the time of creation of the generated image.
This date will be used for the image metadata.
This should be either a date and time formatted according to [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) or `"now"`, in which case the current date will be used. This should be either a date and time formatted according to [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) or `"now"`, in which case the current date will be used.
:::{.caution} :::{.caution}
@ -524,6 +525,18 @@ This allows the function to produce reproducible images.
_Default value:_ `"1970-01-01T00:00:01Z"`. _Default value:_ `"1970-01-01T00:00:01Z"`.
`mtime` (String; _optional_)
: Specifies the time used for the modification timestamp of files within the layers of the generated image.
This should be either a date and time formatted according to [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) or `"now"`, in which case the current date will be used.
:::{.caution}
Using a non-constant date will cause built layers to have a different hash each time, preventing deduplication.
Using `"now"` also means that the generated image will not be reproducible anymore (because the date will always change whenever it's built).
:::
_Default value:_ `"1970-01-01T00:00:01Z"`.
`uid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-uid} `uid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-uid}
`gid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-gid} `gid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-gid}
`uname` (String; _optional_) []{#dockerTools-buildLayeredImage-arg-uname} `uname` (String; _optional_) []{#dockerTools-buildLayeredImage-arg-uname}

View file

@ -501,7 +501,7 @@ writeTextFile {
text = '' text = ''
Contents of File Contents of File
''; '';
destination = "share/my-file"; destination = "/share/my-file";
} }
``` ```
@ -586,7 +586,7 @@ writeTextFile {
echo "hi" echo "hi"
''; '';
executable = true; executable = true;
destination = "bin/my-script"; destination = "/bin/my-script";
} }
``` ```
@ -674,7 +674,7 @@ writeTextFile {
echo "hi" echo "hi"
''; '';
executable = true; executable = true;
destination = "bin/my-script"; destination = "/bin/my-script";
} }
``` ```

View file

@ -23,12 +23,13 @@ The recommended way of defining a derivation for a Coq library, is to use the `c
* if it is a string of the form `owner:branch` then it tries to download the `branch` of owner `owner` for a project of the same name using the same vcs, and the `version` attribute of the resulting derivation is set to `"dev"`, additionally if the owner is not provided (i.e. if the `owner:` prefix is missing), it defaults to the original owner of the package (see below), * if it is a string of the form `owner:branch` then it tries to download the `branch` of owner `owner` for a project of the same name using the same vcs, and the `version` attribute of the resulting derivation is set to `"dev"`, additionally if the owner is not provided (i.e. if the `owner:` prefix is missing), it defaults to the original owner of the package (see below),
* if it is a string of the form `"#N"`, and the domain is github, then it tries to download the current head of the pull request `#N` from github, * if it is a string of the form `"#N"`, and the domain is github, then it tries to download the current head of the pull request `#N` from github,
* `defaultVersion` (optional). Coq libraries may be compatible with some specific versions of Coq only. The `defaultVersion` attribute is used when no `version` is provided (or if `version = null`) to select the version of the library to use by default, depending on the context. This selection will mainly depend on a `coq` version number but also possibly on other packages versions (e.g. `mathcomp`). If its value ends up to be `null`, the package is marked for removal in end-user `coqPackages` attribute set. * `defaultVersion` (optional). Coq libraries may be compatible with some specific versions of Coq only. The `defaultVersion` attribute is used when no `version` is provided (or if `version = null`) to select the version of the library to use by default, depending on the context. This selection will mainly depend on a `coq` version number but also possibly on other packages versions (e.g. `mathcomp`). If its value ends up to be `null`, the package is marked for removal in end-user `coqPackages` attribute set.
* `release` (optional, defaults to `{}`), lists all the known releases of the library and for each of them provides an attribute set with at least a `hash` attribute (you may put the empty string `""` in order to automatically insert a fake hash, this will trigger an error which will allow you to find the correct hash), each attribute set of the list of releases also takes optional overloading arguments for the fetcher as below (i.e.`domain`, `owner`, `repo`, `rev` assuming the default fetcher is used) and optional overrides for the result of the fetcher (i.e. `version` and `src`). * `release` (optional, defaults to `{}`), lists all the known releases of the library and for each of them provides an attribute set with at least a `hash` attribute (you may put the empty string `""` in order to automatically insert a fake hash, this will trigger an error which will allow you to find the correct hash), each attribute set of the list of releases also takes optional overloading arguments for the fetcher as below (i.e.`domain`, `owner`, `repo`, `rev`, `artifact` assuming the default fetcher is used) and optional overrides for the result of the fetcher (i.e. `version` and `src`).
* `fetcher` (optional, defaults to a generic fetching mechanism supporting github or gitlab based infrastructures), is a function that takes at least an `owner`, a `repo`, a `rev`, and a `hash` and returns an attribute set with a `version` and `src`. * `fetcher` (optional, defaults to a generic fetching mechanism supporting github or gitlab based infrastructures), is a function that takes at least an `owner`, a `repo`, a `rev`, and a `hash` and returns an attribute set with a `version` and `src`.
* `repo` (optional, defaults to the value of `pname`), * `repo` (optional, defaults to the value of `pname`),
* `owner` (optional, defaults to `"coq-community"`). * `owner` (optional, defaults to `"coq-community"`).
* `domain` (optional, defaults to `"github.com"`), domains including the strings `"github"` or `"gitlab"` in their names are automatically supported, otherwise, one must change the `fetcher` argument to support them (cf `pkgs/development/coq-modules/heq/default.nix` for an example), * `domain` (optional, defaults to `"github.com"`), domains including the strings `"github"` or `"gitlab"` in their names are automatically supported, otherwise, one must change the `fetcher` argument to support them (cf `pkgs/development/coq-modules/heq/default.nix` for an example),
* `releaseRev` (optional, defaults to `(v: v)`), provides a default mapping from release names to revision hashes/branch names/tags, * `releaseRev` (optional, defaults to `(v: v)`), provides a default mapping from release names to revision hashes/branch names/tags,
* `releaseArtifact` (optional, defaults to `(v: null)`), provides a default mapping from release names to artifact names (only works for github artifact for now),
* `displayVersion` (optional), provides a way to alter the computation of `name` from `pname`, by explaining how to display version numbers, * `displayVersion` (optional), provides a way to alter the computation of `name` from `pname`, by explaining how to display version numbers,
* `namePrefix` (optional, defaults to `[ "coq" ]`), provides a way to alter the computation of `name` from `pname`, by explaining which dependencies must occur in `name`, * `namePrefix` (optional, defaults to `[ "coq" ]`), provides a way to alter the computation of `name` from `pname`, by explaining which dependencies must occur in `name`,
* `nativeBuildInputs` (optional), is a list of executables that are required to build the current derivation, in addition to the default ones (namely `which`, `dune` and `ocaml` depending on whether `useDune`, `useDuneifVersion` and `mlPlugin` are set). * `nativeBuildInputs` (optional), is a list of executables that are required to build the current derivation, in addition to the default ones (namely `which`, `dune` and `ocaml` depending on whether `useDune`, `useDuneifVersion` and `mlPlugin` are set).

View file

@ -47,7 +47,7 @@
checks = forAllSystems (system: { checks = forAllSystems (system: {
tarball = jobs.${system}.tarball; tarball = jobs.${system}.tarball;
# Exclude power64 due to "libressl is not available on the requested hostPlatform" with hostPlatform being power64 # Exclude power64 due to "libressl is not available on the requested hostPlatform" with hostPlatform being power64
} // lib.optionalAttrs (self.legacyPackages.${system}.stdenv.isLinux && !self.legacyPackages.${system}.targetPlatform.isPower64) { } // lib.optionalAttrs (self.legacyPackages.${system}.stdenv.hostPlatform.isLinux && !self.legacyPackages.${system}.targetPlatform.isPower64) {
# Test that ensures that the nixosSystem function can accept a lib argument # Test that ensures that the nixosSystem function can accept a lib argument
# Note: prefer not to extend or modify `lib`, especially if you want to share reusable modules # Note: prefer not to extend or modify `lib`, especially if you want to share reusable modules
# alternatives include: `import` a file, or put a custom library in an option or in `_module.args.<libname>` # alternatives include: `import` a file, or put a custom library in an option or in `_module.args.<libname>`
@ -64,7 +64,7 @@
boot.loader.grub.enable = false; boot.loader.grub.enable = false;
fileSystems."/".device = "nodev"; fileSystems."/".device = "nodev";
# See https://search.nixos.org/options?show=system.stateVersion&query=stateversion # See https://search.nixos.org/options?show=system.stateVersion&query=stateversion
system.stateVersion = lib.versions.majorMinor lib.version; # DON'T do this in real configs! system.stateVersion = lib.trivial.release; # DON'T do this in real configs!
}) })
]; ];
}).config.system.build.toplevel; }).config.system.build.toplevel;

View file

@ -33,7 +33,7 @@ pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" {
nativeBuildInputs = [ nativeBuildInputs = [
nix nix
pkgs.gitMinimal pkgs.gitMinimal
] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools; ] ++ lib.optional pkgs.stdenv.hostPlatform.isLinux pkgs.inotify-tools;
strictDeps = true; strictDeps = true;
} '' } ''
datadir="${nix}/share" datadir="${nix}/share"

View file

@ -2028,6 +2028,13 @@
github = "Atry"; github = "Atry";
githubId = 601530; githubId = 601530;
}; };
attila = {
name = "Attila Oláh";
email = "attila@dorn.haus";
github = "attilaolah";
githubId = 196617;
keys = [ { fingerprint = "BF2E 4759 74D3 88E0 E30C 9604 07E6 C064 3FD1 42C3"; } ];
};
auchter = { auchter = {
name = "Michael Auchter"; name = "Michael Auchter";
email = "a@phire.org"; email = "a@phire.org";
@ -2514,6 +2521,12 @@
githubId = 6145260; githubId = 6145260;
keys = [ { fingerprint = "804B 6CB8 AED5 61D9 3DAD 4DC5 E2F2 2C5E DF20 119D"; } ]; keys = [ { fingerprint = "804B 6CB8 AED5 61D9 3DAD 4DC5 E2F2 2C5E DF20 119D"; } ];
}; };
benchand = {
name = "Ben Chand";
email = "BenChand1995@gmail.com";
github = "BenChand";
githubId = 3618457;
};
bendlas = { bendlas = {
email = "herwig@bendlas.net"; email = "herwig@bendlas.net";
matrix = "@bendlas:matrix.org"; matrix = "@bendlas:matrix.org";
@ -2661,6 +2674,13 @@
githubId = 7346933; githubId = 7346933;
name = "betaboon"; name = "betaboon";
}; };
beviu = {
name = "beviu";
email = "nixpkgs@beviu.com";
github = "beviu";
githubId = 56923875;
keys = [ { fingerprint = "30D6 A755 E3C3 5797 CBBB 05B6 CD20 2E66 5CAD 7D06"; } ];
};
bew = { bew = {
email = "benoit.dechezelles@gmail.com"; email = "benoit.dechezelles@gmail.com";
github = "bew"; github = "bew";
@ -2733,6 +2753,13 @@
githubId = 19915050; githubId = 19915050;
name = "binarycat"; name = "binarycat";
}; };
binary-eater = {
email = "sergeantsagara@protonmail.com";
github = "Binary-Eater";
githubId = 10691440;
name = "Rahul Rameshbabu";
keys = [ { fingerprint = "678A 8DF1 D9F2 B51B 7110 BE53 FF24 7B3E 5411 387B"; } ];
};
binsky = { binsky = {
email = "timo@binsky.org"; email = "timo@binsky.org";
github = "binsky08"; github = "binsky08";
@ -2750,6 +2777,12 @@
githubId = 10164833; githubId = 10164833;
name = "Birk Bohne"; name = "Birk Bohne";
}; };
bjesus = {
email = "nixpkgs@yoavmoshe.com";
github = "bjesus";
githubId = 55081;
name = "Yo'av Moshe";
};
bjornfor = { bjornfor = {
email = "bjorn.forsman@gmail.com"; email = "bjorn.forsman@gmail.com";
github = "bjornfor"; github = "bjornfor";
@ -3306,6 +3339,12 @@
githubId = 141733; githubId = 141733;
name = "Andrew Bruce"; name = "Andrew Bruce";
}; };
camerondugan = {
email = "cameron.dugan@protonmail.com";
github = "camerondugan";
githubId = 54632731;
name = "Cameron Dugan";
};
cameronfyfe = { cameronfyfe = {
email = "cameron.j.fyfe@gmail.com"; email = "cameron.j.fyfe@gmail.com";
github = "cameronfyfe"; github = "cameronfyfe";
@ -3422,6 +3461,12 @@
githubId = 5241813; githubId = 5241813;
name = "Carter Sande"; name = "Carter Sande";
}; };
casaca = {
name = "J McNutt";
email = "jmacasac@hotmail.com";
github = "casaca24";
githubId = 87252279;
};
casey = { casey = {
email = "casey@rodarmor.net"; email = "casey@rodarmor.net";
github = "casey"; github = "casey";
@ -4050,6 +4095,12 @@
email = "jupiter@m.rdis.dev"; email = "jupiter@m.rdis.dev";
name = "Scott Little"; name = "Scott Little";
}; };
codgician = {
email = "codgician@outlook.com";
github = "codgician";
githubId = 15964984;
name = "codgician";
};
codifryed = { codifryed = {
email = "gb@guyboldon.com"; email = "gb@guyboldon.com";
name = "Guy Boldon"; name = "Guy Boldon";
@ -7041,6 +7092,13 @@
githubId = 5918766; githubId = 5918766;
name = "Franz Thoma"; name = "Franz Thoma";
}; };
fnune = {
email = "fausto.nunez@mailbox.org";
github = "fnune";
githubId = 16181067;
name = "Fausto Núñez Alberro";
keys = [ { fingerprint = "668E 01D1 B129 3F42 0A0F 933A C880 6451 94A2 D562"; } ];
};
foo-dogsquared = { foo-dogsquared = {
email = "foodogsquared@foodogsquared.one"; email = "foodogsquared@foodogsquared.one";
github = "foo-dogsquared"; github = "foo-dogsquared";
@ -9079,6 +9137,12 @@
githubId = 54999; githubId = 54999;
name = "Ariel Nunez"; name = "Ariel Nunez";
}; };
interdependence = {
email = "git@williamvandervalk.com";
github = "interdependence";
githubId = 45567423;
name = "William Vandervalk";
};
Intuinewin = { Intuinewin = {
email = "antoinelabarussias@gmail.com"; email = "antoinelabarussias@gmail.com";
github = "Intuinewin"; github = "Intuinewin";
@ -9110,6 +9174,12 @@
githubId = 1817528; githubId = 1817528;
name = "Igor Polyakov"; name = "Igor Polyakov";
}; };
iosmanthus = {
email = "myosmanthustree@gmail.com";
github = "iosmanthus";
githubId = 16307070;
name = "iosmanthus";
};
iquerejeta = { iquerejeta = {
github = "iquerejeta"; github = "iquerejeta";
githubId = 31273774; githubId = 31273774;
@ -9847,6 +9917,11 @@
githubId = 1061229; githubId = 1061229;
name = "Jiehong Ma"; name = "Jiehong Ma";
}; };
jigglycrumb = {
github = "jigglycrumb";
githubId = 1476865;
name = "jigglycrumb";
};
jirkamarsik = { jirkamarsik = {
email = "jiri.marsik89@gmail.com"; email = "jiri.marsik89@gmail.com";
github = "jirkamarsik"; github = "jirkamarsik";
@ -11817,6 +11892,12 @@
githubId = 13804737; githubId = 13804737;
keys = [ { fingerprint = "7FE2 113A A08B 695A C8B8 DDE6 AE53 B4C2 E58E DD45"; } ]; keys = [ { fingerprint = "7FE2 113A A08B 695A C8B8 DDE6 AE53 B4C2 E58E DD45"; } ];
}; };
lgbishop = {
email = "lachlan.bishop@hotmail.com";
github = "lgbishop";
githubId = 125634066;
name = "Lachlan Bishop";
};
lgcl = { lgcl = {
email = "dev@lgcl.de"; email = "dev@lgcl.de";
name = "Leon Vack"; name = "Leon Vack";
@ -12207,6 +12288,12 @@
githubId = 8555953; githubId = 8555953;
name = "Laure Tavard"; name = "Laure Tavard";
}; };
ltrump = {
email = "ltrump@163.com";
github = "L-Trump";
githubId = 37738631;
name = "Luo Chen";
};
ltstf1re = { ltstf1re = {
email = "ltstf1re@disroot.org"; email = "ltstf1re@disroot.org";
github = "lsf1re"; github = "lsf1re";
@ -12252,6 +12339,12 @@
githubId = 15693688; githubId = 15693688;
name = "Lucas Eduardo Wendt"; name = "Lucas Eduardo Wendt";
}; };
lucastso10 = {
email = "lucastso10@gmail.com";
github = "lucastso10";
githubId = 84486266;
name = "Lucas Teixeira Soares";
};
lucc = { lucc = {
email = "lucc+nix@posteo.de"; email = "lucc+nix@posteo.de";
github = "lucc"; github = "lucc";
@ -13415,6 +13508,12 @@
github = "Mephistophiles"; github = "Mephistophiles";
githubId = 4850908; githubId = 4850908;
}; };
merrkry = {
email = "merrkry@tsubasa.moe";
name = "merrkry";
github = "merrkry";
githubId = 124278440;
};
mevatron = { mevatron = {
email = "mevatron@gmail.com"; email = "mevatron@gmail.com";
name = "mevatron"; name = "mevatron";
@ -13895,7 +13994,7 @@
name = "Maciej Kazulak"; name = "Maciej Kazulak";
}; };
mkez = { mkez = {
email = "matias.zwinger+nix@protonmail.com"; email = "matias+nix@zwinger.fi";
github = "mk3z"; github = "mk3z";
githubId = 52108954; githubId = 52108954;
name = "Matias Zwinger"; name = "Matias Zwinger";
@ -15310,6 +15409,19 @@
githubId = 5047052; githubId = 5047052;
name = "Niclas Hirschfeld"; name = "Niclas Hirschfeld";
}; };
nwjsmith = {
email = "nate@theinternate.com";
github = "nwjsmith";
githubId = 1348;
name = "Nate Smith";
};
nyabinary = {
name = "Niko Cantero";
email = "nyanbinary@keemail.me";
matrix = "@niko:conduit.rs";
github = "nyabinary";
githubId = 97130632;
};
nyadiia = { nyadiia = {
email = "nyadiia@pm.me"; email = "nyadiia@pm.me";
github = "nyadiia"; github = "nyadiia";
@ -15317,13 +15429,6 @@
name = "Nadia"; name = "Nadia";
keys = [ { fingerprint = "6B51 E324 238A F455 2381 313A 9254 1B0C D2A9 3AD8"; } ]; keys = [ { fingerprint = "6B51 E324 238A F455 2381 313A 9254 1B0C D2A9 3AD8"; } ];
}; };
nyanbinary = {
email = "nyanbinary@keemail.me";
matrix = "@niko:conduit.rs";
github = "nyabinary";
githubId = 97130632;
name = "Niko";
};
nyanloutre = { nyanloutre = {
email = "paul@nyanlout.re"; email = "paul@nyanlout.re";
github = "nyanloutre"; github = "nyanloutre";
@ -16563,6 +16668,12 @@
githubId = 358550; githubId = 358550;
name = "Philip Lykke Carlsen"; name = "Philip Lykke Carlsen";
}; };
plebhash = {
name = "plebhash";
email = "plebhash@proton.me";
github = "plebhash";
githubId = 147345153;
};
pleshevskiy = { pleshevskiy = {
email = "dmitriy@pleshevski.ru"; email = "dmitriy@pleshevski.ru";
github = "pleshevskiy"; github = "pleshevskiy";
@ -16902,6 +17013,12 @@
githubId = 406946; githubId = 406946;
name = "Valentin Lorentz"; name = "Valentin Lorentz";
}; };
projectinitiative = {
name = "ProjectInitiative";
github = "ProjectInitiative";
githubId = 6314611;
keys = [ { fingerprint = "EEC7 53FC EAAA FD9E 4DC0 9BB5 CAEB 4185 C226 D76B"; } ];
};
prominentretail = { prominentretail = {
email = "me@jakepark.me"; email = "me@jakepark.me";
github = "ProminentRetail"; github = "ProminentRetail";
@ -18037,6 +18154,12 @@
githubId = 17805516; githubId = 17805516;
name = "Rohan Rao"; name = "Rohan Rao";
}; };
rolfschr = {
email = "rolf.schr@posteo.de";
github = "rolfschr";
githubId = 1188465;
name = "Rolf Schröder";
};
rollf = { rollf = {
email = "rolf.schroeder@limbus-medtec.com"; email = "rolf.schroeder@limbus-medtec.com";
github = "rollf"; github = "rollf";
@ -18099,12 +18222,6 @@
github = "rosehobgoblin"; github = "rosehobgoblin";
githubId = 84164410; githubId = 84164410;
}; };
roshaen = {
name = "Roshan Kumar";
email = "roshaen09@gmail.com";
github = "roshaen";
githubId = 58213083;
};
RossComputerGuy = { RossComputerGuy = {
name = "Tristan Ross"; name = "Tristan Ross";
email = "tristan.ross@midstall.com"; email = "tristan.ross@midstall.com";
@ -19233,6 +19350,12 @@
github = "kf5grd"; github = "kf5grd";
githubId = 18297490; githubId = 18297490;
}; };
shogo = {
email = "shouryagoel10000@gmail.com";
github = "Sh0g0-1758";
githubId = 114918019;
name = "Shourya Goel";
};
shortcord = { shortcord = {
name = "Short Cord"; name = "Short Cord";
email = "short@shortcord.com"; email = "short@shortcord.com";
@ -19899,6 +20022,12 @@
github = "srounce"; github = "srounce";
githubId = 60792; githubId = 60792;
}; };
sshine = {
email = "simon@simonshine.dk";
github = "sshine";
githubId = 50879;
name = "Simon Shine";
};
SShrike = { SShrike = {
email = "severen@shrike.me"; email = "severen@shrike.me";
github = "severen"; github = "severen";
@ -23177,6 +23306,12 @@
github = "YoshiRulz"; github = "YoshiRulz";
githubId = 13409956; githubId = 13409956;
}; };
youhaveme9 = {
name = "Roshan Kumar";
email = "roshaen09@gmail.com";
github = "youhaveme9";
githubId = 58213083;
};
yrashk = { yrashk = {
email = "yrashk@gmail.com"; email = "yrashk@gmail.com";
github = "yrashk"; github = "yrashk";

View file

@ -13,5 +13,5 @@ mkShell {
clippy clippy
rustfmt rustfmt
] ]
++ lib.optional stdenv.isDarwin pkgs.libiconv; ++ lib.optional stdenv.hostPlatform.isDarwin pkgs.libiconv;
} }

View file

@ -16,7 +16,7 @@ import utils
LEAF_TEMPLATE = jinja2.Template(''' LEAF_TEMPLATE = jinja2.Template('''
{mkKdeDerivation}: { mkKdeDerivation }:
mkKdeDerivation { mkKdeDerivation {
pname = "{{ pname }}"; pname = "{{ pname }}";
} }
@ -25,7 +25,7 @@ mkKdeDerivation {
ROOT_TEMPLATE = jinja2.Template(''' ROOT_TEMPLATE = jinja2.Template('''
{callPackage}: { {callPackage}: {
{%- for p in packages %} {%- for p in packages %}
{{ p }} = callPackage ./{{ p }} {}; {{ p }} = callPackage ./{{ p }} { };
{%- endfor %} {%- endfor %}
} }
'''.strip()); '''.strip());

View file

@ -114,6 +114,7 @@ middleclass,,,,,,
mimetypes,,,,,, mimetypes,,,,,,
mpack,,,,,, mpack,,,,,,
moonscript,https://raw.githubusercontent.com/leafo/moonscript/master/moonscript-dev-1.rockspec,,,,,arobyn moonscript,https://raw.githubusercontent.com/leafo/moonscript/master/moonscript-dev-1.rockspec,,,,,arobyn
neorg,,,,,,GaetanLepage
neotest,,,,,,mrcjkb neotest,,,,,,mrcjkb
nlua,,,,,,teto nlua,,,,,,teto
nui.nvim,,,,,,mrcjkb nui.nvim,,,,,,mrcjkb

1 name rockspec ref server version luaversion maintainers
114 mimetypes
115 mpack
116 moonscript https://raw.githubusercontent.com/leafo/moonscript/master/moonscript-dev-1.rockspec arobyn
117 neorg GaetanLepage
118 neotest mrcjkb
119 nlua teto
120 nui.nvim mrcjkb

View file

@ -565,6 +565,7 @@ with lib.maintainers;
linux-kernel = { linux-kernel = {
members = [ members = [
TredwellGit TredwellGit
k900
ma27 ma27
nequissimus nequissimus
qyliss qyliss

View file

@ -1,8 +1,6 @@
# Minimal {#sec-profile-minimal} # Minimal {#sec-profile-minimal}
This profile defines a small NixOS configuration. It does not contain any This profile defines a small NixOS configuration. It does not contain any
graphical stuff. It's a very short file that enables graphical stuff. It's a very short file that sets [](#opt-i18n.supportedLocales)
[noXlibs](#opt-environment.noXlibs), sets to only support the user-selected locale, and
[](#opt-i18n.supportedLocales) to [disables packages' documentation](#opt-documentation.enable).
only support the user-selected locale,
and [disables packages' documentation](#opt-documentation.enable).

View file

@ -6,13 +6,13 @@ tedious, so here is a quick way to see if the installer works properly:
```ShellSession ```ShellSession
# mount -t tmpfs none /mnt # mount -t tmpfs none /mnt
# nixos-generate-config --root /mnt # nixos-generate-config --root /mnt
$ nix-build '<nixpkgs/nixos>' -A config.system.build.nixos-install $ nix-build '<nixpkgs>' -A nixos-install
# ./result/bin/nixos-install # ./result/bin/nixos-install
``` ```
To start a login shell in the new NixOS installation in `/mnt`: To start a login shell in the new NixOS installation in `/mnt`:
```ShellSession ```ShellSession
$ nix-build '<nixpkgs/nixos>' -A config.system.build.nixos-enter $ nix-build '<nixpkgs>' -A nixos-enter
# ./result/bin/nixos-enter # ./result/bin/nixos-enter
``` ```

View file

@ -220,6 +220,8 @@ The NixOS installer ships with multiple partitioning tools. The examples
below use `parted`, but also provides `fdisk`, `gdisk`, `cfdisk`, and below use `parted`, but also provides `fdisk`, `gdisk`, `cfdisk`, and
`cgdisk`. `cgdisk`.
Use the command 'lsblk' to find the name of your 'disk' device.
The recommended partition scheme differs depending if the computer uses The recommended partition scheme differs depending if the computer uses
*Legacy Boot* or *UEFI*. *Legacy Boot* or *UEFI*.

View file

@ -46,10 +46,13 @@
If you experience any issues, please report them. If you experience any issues, please report them.
The original Perl script can still be used for now by setting `system.switch.enableNg` to `false`. The original Perl script can still be used for now by setting `system.switch.enableNg` to `false`.
- Support for mounting filesystems from block devices protected with [dm-verity](https://docs.kernel.org/admin-guide/device-mapper/verity.html)
was added through the `boot.initrd.systemd.dmVerity` option.
- The [Xen Hypervisor](https://xenproject.org) is once again available as a virtualisation option under [`virtualisation.xen`](#opt-virtualisation.xen.enable). - The [Xen Hypervisor](https://xenproject.org) is once again available as a virtualisation option under [`virtualisation.xen`](#opt-virtualisation.xen.enable).
- This release includes Xen [4.17.5](https://wiki.xenproject.org/wiki/Xen_Project_4.17_Release_Notes), [4.18.3](https://wiki.xenproject.org/wiki/Xen_Project_4.18_Release_Notes) and [4.19.0](https://wiki.xenproject.org/wiki/Xen_Project_4.19_Release_Notes), as well as support for booting the hypervisor on EFI systems. - This release includes Xen [4.17.5](https://wiki.xenproject.org/wiki/Xen_Project_4.17_Release_Notes), [4.18.3](https://wiki.xenproject.org/wiki/Xen_Project_4.18_Release_Notes) and [4.19.0](https://wiki.xenproject.org/wiki/Xen_Project_4.19_Release_Notes), as well as support for booting the hypervisor on EFI systems.
::: {.warning} ::: {.warning}
Booting into Xen through a legacy BIOS bootloader or with the legacy script-based Stage 1 initrd have been **deprecated**. Only EFI booting and the new systemd-based Stage 1 initrd are supported. Booting into Xen through a legacy BIOS bootloader or with the legacy script-based Stage 1 initrd have been **deprecated**. Only EFI booting and the new systemd-based Stage 1 initrd are supported.
::: :::
- There are two flavours of Xen available by default: `xen`, which includes all built-in components, and `xen-slim`, which replaces the built-in components with their Nixpkgs equivalents. - There are two flavours of Xen available by default: `xen`, which includes all built-in components, and `xen-slim`, which replaces the built-in components with their Nixpkgs equivalents.
- The `qemu-xen-traditional` component has been deprecated by upstream Xen, and is no longer available in any of the Xen packages. - The `qemu-xen-traditional` component has been deprecated by upstream Xen, and is no longer available in any of the Xen packages.
@ -58,7 +61,7 @@
## New Modules {#sec-release-24.11-new-modules} ## New Modules {#sec-release-24.11-new-modules}
- [TaskChampion Sync-Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server), a [Taskwariror 3](https://taskwarrior.org/docs/upgrade-3/) sync server, replacing Taskwarrior 2's sync server named [`taskserver`](https://github.com/GothenburgBitFactory/taskserver). - [TaskChampion Sync-Server](https://github.com/GothenburgBitFactory/taskchampion-sync-server), a [Taskwarrior 3](https://taskwarrior.org/docs/upgrade-3/) sync server, replacing Taskwarrior 2's sync server named [`taskserver`](https://github.com/GothenburgBitFactory/taskserver).
- [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr), proxy server to bypass Cloudflare protection. Available as [services.flaresolverr](#opt-services.flaresolverr.enable) service. - [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr), proxy server to bypass Cloudflare protection. Available as [services.flaresolverr](#opt-services.flaresolverr.enable) service.
@ -146,6 +149,10 @@
- [ToDesk](https://www.todesk.com/linux.html), a remote desktop applicaton. Available as [services.todesk.enable](#opt-services.todesk.enable). - [ToDesk](https://www.todesk.com/linux.html), a remote desktop applicaton. Available as [services.todesk.enable](#opt-services.todesk.enable).
- [Dependency Track](https://dependencytrack.org/), an intelligent Component Analysis platform that allows organizations to identify and reduce risk in the software supply chain. Available as [services.dependency-track](option.html#opt-services.dependency-track).
- [Immich](https://github.com/immich-app/immich), a self-hosted photo and video backup solution. Available as [services.immich](#opt-services.immich.enable).
## Backward Incompatibilities {#sec-release-24.11-incompatibilities} ## 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` 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:
@ -194,6 +201,8 @@
- The `MSMTP_QUEUE` and `MSMTP_LOG` environment variables accepted by `msmtpq` have now been renamed to `MSMTPQ_Q` and `MSMTPQ_LOG` respectively. - The `MSMTP_QUEUE` and `MSMTP_LOG` environment variables accepted by `msmtpq` have now been renamed to `MSMTPQ_Q` and `MSMTPQ_LOG` respectively.
- The logrotate service has received hardening and now requires enabling `allowNetworking`, if logrotate needs to access the network.
- The fcgiwrap module now allows multiple instances running as distinct users. - The fcgiwrap module now allows multiple instances running as distinct users.
The option `services.fgciwrap` now takes an attribute set of the The option `services.fgciwrap` now takes an attribute set of the
configuration of each individual instance. configuration of each individual instance.
@ -254,6 +263,9 @@
- `pkgs.nextcloud27` has been removed since it's EOL. - `pkgs.nextcloud27` has been removed since it's EOL.
- The `environment.noXlibs` option has been removed. It was a common source of unexpected rebuilds and breakage that was often hard to diagnose.
If you need to disable certain libraries, you're encouraged to add your own overlay to your configuration that targets the packages you care about.
- `frigate` was updated past 0.14.0. This release includes various breaking changes, so please go read the [release notes](https://github.com/blakeblackshear/frigate/releases/tag/v0.14.0). - `frigate` was updated past 0.14.0. This release includes various breaking changes, so please go read the [release notes](https://github.com/blakeblackshear/frigate/releases/tag/v0.14.0).
Most prominently access to the webinterface and API are now protected by authentication. Retrieve the auto-created Most prominently access to the webinterface and API are now protected by authentication. Retrieve the auto-created
admin account from the `frigate.service` journal after upgrading. admin account from the `frigate.service` journal after upgrading.
@ -460,11 +472,23 @@
- The `openlens` package got removed, suggested replacment `lens-desktop` - The `openlens` package got removed, suggested replacment `lens-desktop`
- The `services.dnsmasq.extraConfig` option has been removed, as it had been deprecated for over 2 years. This option has been replaced by `services.dnsmasq.settings`.
- The NixOS installation media no longer support the ReiserFS or JFS file systems by default. - The NixOS installation media no longer support the ReiserFS or JFS file systems by default.
- Minimal installer ISOs are no longer built on the small channel. - Minimal installer ISOs are no longer built on the small channel.
Please obtain installer images from the full release channels. Please obtain installer images from the full release channels.
- The `isync` package has been updated to version `1.5.0`, which introduces some breaking changes. See the [compatibility concerns](https://sourceforge.net/projects/isync/files/isync/1.5.0/) for more details.
- Legacy package `globalprotect-openconnect` 1.x and related module
`globalprotect-vpn` were dropped. Two new packages `gpauth` and `gpclient`
from the 2.x version of the GlobalProtect-openconnect project are added in its
place. The GUI components related to the project are non-free and not
packaged.
- Compatible string matching for `hardware.deviceTree.overlays` has been changed to a more correct behavior. See [below](#sec-release-24.11-migration-dto-compatible) for details.
## Other Notable Changes {#sec-release-24.11-notable-changes} ## Other Notable Changes {#sec-release-24.11-notable-changes}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
@ -504,6 +528,8 @@
The derivation now installs "impl" headers selectively instead of by a wildcard. The derivation now installs "impl" headers selectively instead of by a wildcard.
Use `imgui.src` if you just want to access the unpacked sources. Use `imgui.src` if you just want to access the unpacked sources.
- Linux 4.19 has been removed because it will reach its end of life within the lifespan of 24.11
- Unprivileged access to the kernel syslog via `dmesg` is now restricted by default. Users wanting to keep an - Unprivileged access to the kernel syslog via `dmesg` is now restricted by default. Users wanting to keep an
unrestricted access to it can set `boot.kernel.sysctl."kernel.dmesg_restrict" = false`. unrestricted access to it can set `boot.kernel.sysctl."kernel.dmesg_restrict" = false`.
@ -587,3 +613,22 @@ in {
]; ];
}; };
``` ```
### `hardware.deviceTree.overlays` compatible string matching {#sec-release-24.11-migration-dto-compatible}
The original compatible string implementation in older NixOS versions relied on substring matching,
which is incorrect for overlays with multiple compatible strings and other cases.
The new behavior is consistent with what other tools already do - the overlay is considered applicable if,
and only if, _any_ of the compatible strings in the overlay match _any_ of the compatible strings in the DT.
To provide some examples:
| Overlay `compatible` | DT `compatible` | Pre-24.11 behavior | Correct behavior | Notes |
|----------------------|-----------------|--------------------|------------------|--------------------------------------------|
| `"foo"` | `"foo", "bar"` | match | match | Most common use case does not change |
| `"foo"` | `"foobar"` | match | no match | Substrings should not be matched |
| `"foo bar"` | `"foo", "bar"` | match | no match | Separators should not be matched to spaces |
| `"foo", "bar"` | `"baz", "bar"` | no match | match | One compatible string matching is enough |
Note that this also allows writing overlays that explicitly apply to multiple boards.

View file

@ -321,7 +321,7 @@ let format' = format; in let
e2fsprogs e2fsprogs
lkl lkl
config.system.build.nixos-install config.system.build.nixos-install
config.system.build.nixos-enter nixos-enter
nix nix
systemdMinimal systemdMinimal
] ]

View file

@ -124,7 +124,7 @@ let
tools = lib.makeBinPath ( tools = lib.makeBinPath (
with pkgs; [ with pkgs; [
config.system.build.nixos-enter nixos-enter
config.system.build.nixos-install config.system.build.nixos-install
dosfstools dosfstools
e2fsprogs e2fsprogs

View file

@ -112,7 +112,7 @@ let
tools = lib.makeBinPath ( tools = lib.makeBinPath (
with pkgs; [ with pkgs; [
config.system.build.nixos-enter nixos-enter
config.system.build.nixos-install config.system.build.nixos-install
dosfstools dosfstools
e2fsprogs e2fsprogs

View file

@ -52,7 +52,7 @@ let
${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) '' ${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
<!-- Pre-generated font caches --> <!-- Pre-generated font caches -->
<cachedir>${cache}</cachedir> <cachedir>${cache}</cachedir>
${lib.optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) '' ${lib.optionalString (pkgs.stdenv.hostPlatform.isx86_64 && cfg.cache32Bit) ''
<cachedir>${cache32}</cachedir> <cachedir>${cache32}</cachedir>
''} ''}
''} ''}

View file

@ -32,7 +32,7 @@ in {
config = { config = {
assertions = [ assertions = [
{ assertion = isNull config.environment.ldso32 || pkgs.stdenv.isx86_64; { assertion = isNull config.environment.ldso32 || pkgs.stdenv.hostPlatform.isx86_64;
message = "Option environment.ldso32 currently only works on x86_64."; message = "Option environment.ldso32 currently only works on x86_64.";
} }
]; ];
@ -44,7 +44,7 @@ in {
"d /${libDir} 0755 root root - -" "d /${libDir} 0755 root root - -"
"L+ /${libDir}/${ldsoBasename} - - - - ${config.environment.ldso}" "L+ /${libDir}/${ldsoBasename} - - - - ${config.environment.ldso}"
] ]
) ++ optionals pkgs.stdenv.isx86_64 ( ) ++ optionals pkgs.stdenv.hostPlatform.isx86_64 (
if isNull config.environment.ldso32 then [ if isNull config.environment.ldso32 then [
"r /${libDir32}/${ldsoBasename32} - - - - -" "r /${libDir32}/${ldsoBasename32} - - - - -"
] else [ ] else [

View file

@ -1,91 +0,0 @@
# This module gets rid of all dependencies on X11 client libraries
# (including fontconfig).
{ config, lib, ... }:
{
options = {
environment.noXlibs = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Switch off the options in the default configuration that
require X11 libraries. This includes client-side font
configuration and SSH forwarding of X11 authentication
in. Thus, you probably do not want to enable this option if
you want to run X11 programs on this machine via SSH.
'';
};
};
config = lib.mkIf config.environment.noXlibs {
programs.ssh.setXAuthLocation = false;
security.pam.services.su.forwardXAuth = lib.mkForce false;
fonts.fontconfig.enable = false;
nixpkgs.overlays = lib.singleton (lib.const (super: {
beam = super.beam_nox;
cairo = super.cairo.override { x11Support = false; };
dbus = super.dbus.override { x11Support = false; };
fastfetch = super.fastfetch.override { vulkanSupport = false; waylandSupport = false; x11Support = false; };
ffmpeg = super.ffmpeg.override { ffmpegVariant = "headless"; };
ffmpeg_4 = super.ffmpeg_4.override { ffmpegVariant = "headless"; };
ffmpeg_6 = super.ffmpeg_6.override { ffmpegVariant = "headless"; };
ffmpeg_7 = super.ffmpeg_7.override { ffmpegVariant = "headless"; };
# dep of graphviz, libXpm is optional for Xpm support
gd = super.gd.override { withXorg = false; };
ghostscript = super.ghostscript.override { cupsSupport = false; x11Support = false; };
gjs = (super.gjs.override { installTests = false; }).overrideAttrs { doCheck = false; }; # avoid test dependency on gtk3
gobject-introspection = super.gobject-introspection.override { x11Support = false; };
gpg-tui = super.gpg-tui.override { x11Support = false; };
gpsd = super.gpsd.override { guiSupport = false; };
graphviz = super.graphviz-nox;
gst_all_1 = super.gst_all_1 // {
gst-plugins-bad = super.gst_all_1.gst-plugins-bad.override { guiSupport = false; };
gst-plugins-base = super.gst_all_1.gst-plugins-base.override { enableGl = false; enableWayland = false; enableX11 = false; };
gst-plugins-good = super.gst_all_1.gst-plugins-good.override { enableWayland = false; enableX11 = false; gtkSupport = false; qt5Support = false; qt6Support = false; };
gst-plugins-rs = super.gst_all_1.gst-plugins-rs.override { withGtkPlugins = false; };
};
imagemagick = super.imagemagick.override { libX11Support = false; libXtSupport = false; };
imagemagickBig = super.imagemagickBig.override { libX11Support = false; libXtSupport = false; };
intel-vaapi-driver = super.intel-vaapi-driver.override { enableGui = false; };
libdevil = super.libdevil-nox;
libextractor = super.libextractor.override { gtkSupport = false; };
libplacebo = super.libplacebo.override { vulkanSupport = false; };
libva = super.libva-minimal;
limesuite = super.limesuite.override { withGui = false; };
mc = super.mc.override { x11Support = false; };
mpv-unwrapped = super.mpv-unwrapped.override { drmSupport = false; screenSaverSupport = false; sdl2Support = false; vulkanSupport = false; waylandSupport = false; x11Support = false; };
msmtp = super.msmtp.override { withKeyring = false; };
mupdf = super.mupdf.override { enableGL = false; enableX11 = false; };
neofetch = super.neofetch.override { x11Support = false; };
networkmanager-fortisslvpn = super.networkmanager-fortisslvpn.override { withGnome = false; };
networkmanager-iodine = super.networkmanager-iodine.override { withGnome = false; };
networkmanager-l2tp = super.networkmanager-l2tp.override { withGnome = false; };
networkmanager-openconnect = super.networkmanager-openconnect.override { withGnome = false; };
networkmanager-openvpn = super.networkmanager-openvpn.override { withGnome = false; };
networkmanager-sstp = super.networkmanager-vpnc.override { withGnome = false; };
networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
pango = super.pango.override { x11Support = false; };
pinentry-curses = super.pinentry-curses.override { withLibsecret = false; };
pinentry-tty = super.pinentry-tty.override { withLibsecret = false; };
pipewire = super.pipewire.override { vulkanSupport = false; x11Support = false; };
pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
(python-final: python-prev: {
# tk feature requires wayland which fails to compile
matplotlib = python-prev.matplotlib.override { enableTk = false; };
})
];
qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; };
qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; });
qt5 = super.qt5.overrideScope (lib.const (super': {
qtbase = super'.qtbase.override { withGtk3 = false; withQttranslation = false; };
}));
stoken = super.stoken.override { withGTK3 = false; };
# translateManpages -> perlPackages.po4a -> texlive-combined-basic -> texlive-core-big -> libX11
util-linux = super.util-linux.override { translateManpages = false; };
vim-full = super.vim-full.override { guiSupport = false; };
vte = super.vte.override { gtkVersion = null; };
zbar = super.zbar.override { enableVideo = false; withXorg = false; };
}));
};
}

View file

@ -12,7 +12,7 @@ let
# Forces 32bit pulseaudio and alsa-plugins to be built/supported for apps # Forces 32bit pulseaudio and alsa-plugins to be built/supported for apps
# using 32bit alsa on 64bit linux. # using 32bit alsa on 64bit linux.
enable32BitAlsaPlugins = cfg.support32Bit && pkgs.stdenv.isx86_64 && (pkgs.pkgsi686Linux.alsa-lib != null && pkgs.pkgsi686Linux.libpulseaudio != null); enable32BitAlsaPlugins = cfg.support32Bit && pkgs.stdenv.hostPlatform.isx86_64 && (pkgs.pkgsi686Linux.alsa-lib != null && pkgs.pkgsi686Linux.libpulseaudio != null);
myConfigFile = myConfigFile =

View file

@ -49,7 +49,7 @@ in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
environment.ldso = mkDefault stub-ld; environment.ldso = mkDefault stub-ld;
environment.ldso32 = mkIf pkgs.stdenv.isx86_64 (mkDefault stub-ld32); environment.ldso32 = mkIf pkgs.stdenv.hostPlatform.isx86_64 (mkDefault stub-ld32);
}; };
meta.maintainers = with lib.maintainers; [ tejing ]; meta.maintainers = with lib.maintainers; [ tejing ];

View file

@ -14,7 +14,7 @@ let
in in
{ {
imports = [ imports = [
(lib.mkRenamedOptionModule [ "services" "xserver" "vaapiDrivers" ] [ "hardware" "opengl" "extraPackages" ]) (lib.mkRenamedOptionModule [ "services" "xserver" "vaapiDrivers" ] [ "hardware" "graphics" "extraPackages" ])
(lib.mkRemovedOptionModule [ "hardware" "opengl" "s3tcSupport" ] "S3TC support is now always enabled in Mesa.") (lib.mkRemovedOptionModule [ "hardware" "opengl" "s3tcSupport" ] "S3TC support is now always enabled in Mesa.")
(lib.mkRemovedOptionModule [ "hardware" "opengl" "driSupport"] "The setting can be removed.") (lib.mkRemovedOptionModule [ "hardware" "opengl" "driSupport"] "The setting can be removed.")
@ -100,7 +100,7 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
assertions = [ assertions = [
{ {
assertion = cfg.enable32Bit -> pkgs.stdenv.isx86_64; assertion = cfg.enable32Bit -> pkgs.stdenv.hostPlatform.isx86_64;
message = "`hardware.graphics.enable32Bit` only makes sense on a 64-bit system."; message = "`hardware.graphics.enable32Bit` only makes sense on a 64-bit system.";
} }
{ {
@ -112,7 +112,7 @@ in
systemd.tmpfiles.settings.graphics-driver = { systemd.tmpfiles.settings.graphics-driver = {
"/run/opengl-driver"."L+".argument = toString driversEnv; "/run/opengl-driver"."L+".argument = toString driversEnv;
"/run/opengl-driver-32" = "/run/opengl-driver-32" =
if pkgs.stdenv.isi686 then if pkgs.stdenv.hostPlatform.isi686 then
{ "L+".argument = "opengl-driver"; } { "L+".argument = "opengl-driver"; }
else if cfg.enable32Bit then else if cfg.enable32Bit then
{ "L+".argument = toString driversEnv32; } { "L+".argument = toString driversEnv32; }

View file

@ -0,0 +1,78 @@
import json
import sys
store_verity_type = "@NIX_STORE_VERITY@" # replaced at import by Nix
def extract_uki_cmdline_params(ukify_json: dict) -> dict[str, str]:
"""
Return a dict of the parameters in the .cmdline section of the UKI
Exits early if "usrhash" is not included.
"""
cmdline = ukify_json.get(".cmdline", {}).get("text")
if cmdline is None:
print("Failed to get cmdline from ukify output")
params = {}
for param in cmdline.split():
key, val = param.partition("=")[::2]
params[key] = val
if "usrhash" not in params:
print(
f"UKI cmdline does not contain a usrhash:\n{cmdline}"
)
exit(1)
return params
def hashes_match(partition: dict[str, str], expected: str) -> bool:
"""
Checks if the value of the "roothash" key in the passed partition object matches `expected`.
"""
if partition.get("roothash") != expected:
pretty_part = json.dumps(partition, indent=2)
print(
f"hash mismatch, expected to find roothash {expected} in:\n{pretty_part}"
)
return False
else:
return True
def check_partitions(
partitions: list[dict], uki_params: dict[str, str]
) -> bool:
"""
Checks if the usrhash from `uki_params` has a matching roothash
for the corresponding partition in `partitions`.
"""
for part in partitions:
if part.get("type") == store_verity_type:
expected = uki_params["usrhash"]
return hashes_match(part, expected)
return False
def main() -> None:
ukify_json = json.load(sys.stdin)
repart_json_output = sys.argv[1]
with open(repart_json_output, "r") as r:
repart_json = json.load(r)
uki_params = extract_uki_cmdline_params(ukify_json)
if check_partitions(repart_json, uki_params):
print("UKI and repart verity hashes match")
else:
print("Compatibility check for UKI and image failed!")
print(f"UKI cmdline parameters:\n{uki_params}")
print(f"repart config: {repart_json_output}")
exit(1)
if __name__ == "__main__":
main()

View file

@ -0,0 +1,209 @@
# opinionated module that can be used to build nixos images with
# a dm-verity protected nix store
{
config,
pkgs,
lib,
...
}:
let
cfg = config.image.repart.verityStore;
verityMatchKey = "store";
# TODO: make these and other arch mappings available from systemd-lib for example
partitionTypes = {
usr =
{
"x86_64" = "usr-x86-64";
"arm64" = "usr-arm64";
}
."${pkgs.stdenv.hostPlatform.linuxArch}";
usr-verity =
{
"x86_64" = "usr-x86-64-verity";
"arm64" = "usr-arm64-verity";
}
."${pkgs.stdenv.hostPlatform.linuxArch}";
};
verityHashCheck =
pkgs.buildPackages.writers.writePython3Bin "assert_uki_repart_match.py"
{
flakeIgnore = [ "E501" ]; # ignores PEP8's line length limit of 79 (black defaults to 88 characters)
}
(
builtins.replaceStrings [ "@NIX_STORE_VERITY@" ] [
partitionTypes.usr-verity
] (builtins.readFile ./assert_uki_repart_match.py)
);
in
{
options.image.repart.verityStore = {
enable = lib.mkEnableOption "building images with a dm-verity protected nix store";
ukiPath = lib.mkOption {
type = lib.types.str;
default = "/EFI/Linux/${config.system.boot.loader.ukiFile}";
defaultText = "/EFI/Linux/\${config.system.boot.loader.ukiFile}";
description = ''
Specify the location on the ESP where the UKI is placed.
'';
};
partitionIds = {
esp = lib.mkOption {
type = lib.types.str;
default = "00-esp";
description = ''
Specify the attribute name of the ESP.
'';
};
store-verity = lib.mkOption {
type = lib.types.str;
default = "10-store-verity";
description = ''
Specify the attribute name of the store's dm-verity hash partition.
'';
};
store = lib.mkOption {
type = lib.types.str;
default = "20-store";
description = ''
Specify the attribute name of the store partition.
'';
};
};
};
config = lib.mkIf cfg.enable {
boot.initrd.systemd.dmVerity.enable = true;
image.repart.partitions = {
# dm-verity hash partition
${cfg.partitionIds.store-verity}.repartConfig = {
Type = partitionTypes.usr-verity;
Verity = "hash";
VerityMatchKey = lib.mkDefault verityMatchKey;
Label = lib.mkDefault "store-verity";
};
# dm-verity data partition that contains the nix store
${cfg.partitionIds.store} = {
storePaths = [ config.system.build.toplevel ];
repartConfig = {
Type = partitionTypes.usr;
Verity = "data";
Format = lib.mkDefault "erofs";
VerityMatchKey = lib.mkDefault verityMatchKey;
Label = lib.mkDefault "store";
};
};
};
system.build = {
# intermediate system image without ESP
intermediateImage =
(config.system.build.image.override {
# always disable compression for the intermediate image
compression.enable = false;
}).overrideAttrs
(
_: previousAttrs: {
# make it easier to identify the intermediate image in build logs
pname = "${previousAttrs.pname}-intermediate";
# do not prepare the ESP, this is done in the final image
systemdRepartFlags = previousAttrs.systemdRepartFlags ++ [ "--defer-partitions=esp" ];
# the image will be self-contained so we can drop references
# to the closure that was used to build it
unsafeDiscardReferences.out = true;
}
);
# UKI with embedded usrhash from intermediateImage
uki =
let
inherit (config.system.boot.loader) ukiFile;
cmdline = "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}";
in
# override the default UKI
lib.mkOverride 99 (
pkgs.runCommand ukiFile
{
nativeBuildInputs = [
pkgs.jq
pkgs.systemdUkify
];
}
''
mkdir -p $out
# Extract the usrhash from the output of the systemd-repart invocation for the intermediate image.
usrhash=$(jq -r \
'.[] | select(.type=="${partitionTypes.usr-verity}") | .roothash' \
${config.system.build.intermediateImage}/repart-output.json
)
# Build UKI with the embedded usrhash.
ukify build \
--config=${config.boot.uki.configFile} \
--cmdline="${cmdline} usrhash=$usrhash" \
--output="$out/${ukiFile}"
''
);
# final system image that is created from the intermediate image by injecting the UKI from above
finalImage =
(config.system.build.image.override {
# continue building with existing intermediate image
createEmpty = false;
}).overrideAttrs
(
finalAttrs: previousAttrs:
let
copyUki = "CopyFiles=${config.system.build.uki}/${config.system.boot.loader.ukiFile}:${cfg.ukiPath}";
in
{
nativeBuildInputs = previousAttrs.nativeBuildInputs ++ [
pkgs.systemdUkify
verityHashCheck
];
postPatch = ''
# add entry to inject UKI into ESP
echo '${copyUki}' >> $finalRepartDefinitions/${cfg.partitionIds.esp}.conf
'';
preBuild = ''
# check that we build the final image with the same intermediate image for
# which the injected UKI was built by comparing the UKI cmdline with the repart output
# of the intermediate image
#
# This is necessary to notice incompatible substitutions of
# non-reproducible store paths, for example when working with distributed
# builds, or when offline-signing the UKI.
ukify --json=short inspect ${config.system.build.uki}/${config.system.boot.loader.ukiFile} \
| assert_uki_repart_match.py "${config.system.build.intermediateImage}/repart-output.json"
# copy the uncompressed intermediate image, so that systemd-repart picks it up
cp -v ${config.system.build.intermediateImage}/${config.image.repart.imageFileBasename}.raw .
chmod +w ${config.image.repart.imageFileBasename}.raw
'';
# the image will be self-contained so we can drop references
# to the closure that was used to build it
unsafeDiscardReferences.out = true;
}
);
};
};
meta.maintainers = with lib.maintainers; [
nikstur
willibutz
];
}

View file

@ -69,6 +69,10 @@ let
}) opts; }) opts;
in in
{ {
imports = [
./repart-verity-store.nix
];
options.image.repart = { options.image.repart = {
name = lib.mkOption { name = lib.mkOption {

View file

@ -150,6 +150,15 @@ in
Whether to configure the sd image to expand it's partition on boot. Whether to configure the sd image to expand it's partition on boot.
''; '';
}; };
nixPathRegistrationFile = mkOption {
type = types.str;
default = "/nix-path-registration";
description = ''
Location of the file containing the input for nix-store --load-db once the machine has booted.
If overriding fileSystems."/" then you should to set this to the root mount + /nix-path-registration
'';
};
}; };
config = { config = {
@ -255,11 +264,8 @@ in
''; '';
}) {}; }) {};
boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot '' boot.postBootCommands = let
# On the first boot do some maintenance tasks expandOnBoot = lib.optionalString config.sdImage.expandOnBoot ''
if [ -f /nix-path-registration ]; then
set -euo pipefail
set -x
# Figure out device names for the boot device and root filesystem. # Figure out device names for the boot device and root filesystem.
rootPart=$(${pkgs.util-linux}/bin/findmnt -n -o SOURCE /) rootPart=$(${pkgs.util-linux}/bin/findmnt -n -o SOURCE /)
bootDevice=$(lsblk -npo PKNAME $rootPart) bootDevice=$(lsblk -npo PKNAME $rootPart)
@ -269,16 +275,25 @@ in
echo ",+," | sfdisk -N$partNum --no-reread $bootDevice echo ",+," | sfdisk -N$partNum --no-reread $bootDevice
${pkgs.parted}/bin/partprobe ${pkgs.parted}/bin/partprobe
${pkgs.e2fsprogs}/bin/resize2fs $rootPart ${pkgs.e2fsprogs}/bin/resize2fs $rootPart
'';
nixPathRegistrationFile = config.sdImage.nixPathRegistrationFile;
in ''
# On the first boot do some maintenance tasks
if [ -f ${nixPathRegistrationFile} ]; then
set -euo pipefail
set -x
${expandOnBoot}
# Register the contents of the initial Nix store # Register the contents of the initial Nix store
${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration ${config.nix.package.out}/bin/nix-store --load-db < ${nixPathRegistrationFile}
# nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag. # nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
touch /etc/NIXOS touch /etc/NIXOS
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
# Prevents this from running on later boots. # Prevents this from running on later boots.
rm -f /nix-path-registration rm -f ${nixPathRegistrationFile}
fi fi
''; '';
}; };

View file

@ -1,23 +0,0 @@
getVersion() {
local dir="$1"
rev=
gitDir="$dir/.git"
if [ -e "$gitDir" ]; then
if [ -z "$(type -P git)" ]; then
echo "warning: Git not found; cannot figure out revision of $dir" >&2
return
fi
cd "$dir"
rev=$(git --git-dir="$gitDir" rev-parse --short HEAD)
if git --git-dir="$gitDir" describe --always --dirty | grep -q dirty; then
rev+=M
fi
fi
}
if nixpkgs=$(nix-instantiate --find-file nixpkgs "$@"); then
getVersion $nixpkgs
if [ -n "$rev" ]; then
echo ".git.$rev"
fi
fi

View file

@ -1,7 +1,7 @@
{ {
x86_64-linux = "/nix/store/f409bhlpp0xkzvdz95qr2yvfjfi8r9jc-nix-2.18.5"; x86_64-linux = "/nix/store/mczjdfprd67mdn90488854bf6b3nkp8j-nix-2.18.7";
i686-linux = "/nix/store/ra39jzrxq3bcpf55aahwv5037akvylf5-nix-2.18.5"; i686-linux = "/nix/store/qqll8zrx7ibdx34ry1ijanqdpdpnibbc-nix-2.18.7";
aarch64-linux = "/nix/store/xiw8a4jbnw18svgdb04hyqzg5bsjspqf-nix-2.18.5"; aarch64-linux = "/nix/store/lwysvjn745fwsz8nv13zzsfq0dhiyxlp-nix-2.18.7";
x86_64-darwin = "/nix/store/k2gzx7i90x3h2c8g6xdi1jkwbl6ic895-nix-2.18.5"; x86_64-darwin = "/nix/store/frzvlvzzj7hwvg8p0y0ivl27430nxhfy-nix-2.18.7";
aarch64-darwin = "/nix/store/rqwymbndaqxma6p8s5brcl9k32n5xx54-nix-2.18.5"; aarch64-darwin = "/nix/store/43dp3pl3k95gszp1hl9sjm22gly65sxi-nix-2.18.7";
} }

View file

@ -3,8 +3,6 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
makeProg = args: pkgs.substituteAll (args // { makeProg = args: pkgs.substituteAll (args // {
dir = "bin"; dir = "bin";
@ -17,28 +15,6 @@ let
''; '';
}); });
nixos-build-vms = makeProg {
name = "nixos-build-vms";
src = ./nixos-build-vms/nixos-build-vms.sh;
inherit (pkgs) runtimeShell;
manPage = ./manpages/nixos-build-vms.8;
};
nixos-install = makeProg {
name = "nixos-install";
src = ./nixos-install.sh;
inherit (pkgs) runtimeShell;
nix = config.nix.package.out;
path = makeBinPath [
pkgs.jq
nixos-enter
pkgs.util-linuxMinimal
];
manPage = ./manpages/nixos-install.8;
};
nixos-rebuild = pkgs.nixos-rebuild.override { nix = config.nix.package.out; };
nixos-generate-config = makeProg { nixos-generate-config = makeProg {
name = "nixos-generate-config"; name = "nixos-generate-config";
src = ./nixos-generate-config.pl; src = ./nixos-generate-config.pl;
@ -51,8 +27,6 @@ let
manPage = ./manpages/nixos-generate-config.8; manPage = ./manpages/nixos-generate-config.8;
}; };
inherit (pkgs) nixos-option;
nixos-version = makeProg { nixos-version = makeProg {
name = "nixos-version"; name = "nixos-version";
src = ./nixos-version.sh; src = ./nixos-version.sh;
@ -61,32 +35,141 @@ let
inherit (config.system) configurationRevision; inherit (config.system) configurationRevision;
json = builtins.toJSON ({ json = builtins.toJSON ({
nixosVersion = config.system.nixos.version; nixosVersion = config.system.nixos.version;
} // optionalAttrs (config.system.nixos.revision != null) { } // lib.optionalAttrs (config.system.nixos.revision != null) {
nixpkgsRevision = config.system.nixos.revision; nixpkgsRevision = config.system.nixos.revision;
} // optionalAttrs (config.system.configurationRevision != null) { } // lib.optionalAttrs (config.system.configurationRevision != null) {
configurationRevision = config.system.configurationRevision; configurationRevision = config.system.configurationRevision;
}); });
manPage = ./manpages/nixos-version.8; manPage = ./manpages/nixos-version.8;
}; };
nixos-enter = makeProg { nixos-install = pkgs.nixos-install.override { nix = config.nix.package; };
name = "nixos-enter"; nixos-rebuild = pkgs.nixos-rebuild.override { nix = config.nix.package; };
src = ./nixos-enter.sh;
inherit (pkgs) runtimeShell;
path = makeBinPath [
pkgs.util-linuxMinimal
];
manPage = ./manpages/nixos-enter.8;
};
defaultConfigTemplate = ''
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
$bootLoaderConfig
# networking.hostName = "nixos"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password\@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
# i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
$xserverConfig
$desktopConfiguration
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# services.pipewire = {
# enable = true;
# pulse.enable = true;
# };
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# users.users.alice = {
# isNormalUser = true;
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = with pkgs; [
# firefox
# tree
# ];
# };
# List packages installed in system profile. To search, run:
# \$ nix search wget
# environment.systemPackages = with pkgs; [
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
# ];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "${config.system.nixos.release}"; # Did you read the comment?
}
'';
in in
{ {
options.system.nixos-generate-config = { options.system.nixos-generate-config = {
configuration = mkOption { configuration = lib.mkOption {
internal = true; internal = true;
type = types.str; type = lib.types.str;
default = defaultConfigTemplate;
description = '' description = ''
The NixOS module that `nixos-generate-config` The NixOS module that `nixos-generate-config`
saves to `/etc/nixos/configuration.nix`. saves to `/etc/nixos/configuration.nix`.
@ -100,9 +183,9 @@ in
''; '';
}; };
desktopConfiguration = mkOption { desktopConfiguration = lib.mkOption {
internal = true; internal = true;
type = types.listOf types.lines; type = lib.types.listOf lib.types.lines;
default = []; default = [];
description = '' description = ''
Text to preseed the desktop configuration that `nixos-generate-config` Text to preseed the desktop configuration that `nixos-generate-config`
@ -118,9 +201,9 @@ in
}; };
}; };
options.system.disableInstallerTools = mkOption { options.system.disableInstallerTools = lib.mkOption {
internal = true; internal = true;
type = types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Disable nixos-rebuild, nixos-generate-config, nixos-installer Disable nixos-rebuild, nixos-generate-config, nixos-installer
@ -130,145 +213,48 @@ in
''; '';
}; };
config = lib.mkMerge [ (lib.mkIf (config.nix.enable && !config.system.disableInstallerTools) { imports = let
mkToolModule = { name, package ? pkgs.${name} }: { config, ... }: {
options.system.tools.${name}.enable = lib.mkEnableOption "${name} script" // {
default = config.nix.enable;
internal = true;
};
system.nixos-generate-config.configuration = mkDefault '' config = lib.mkIf config.system.tools.${name}.enable {
# Edit this configuration file to define what should be installed on environment.systemPackages = [ package ];
# your system. Help is available in the configuration.nix(5) man page, on };
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
$bootLoaderConfig
# networking.hostName = "nixos"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password\@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
# i18n.defaultLocale = "en_US.UTF-8";
# console = {
# font = "Lat2-Terminus16";
# keyMap = "us";
# useXkbConfig = true; # use xkb.options in tty.
# };
$xserverConfig
$desktopConfiguration
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
# hardware.pulseaudio.enable = true;
# OR
# services.pipewire = {
# enable = true;
# pulse.enable = true;
# };
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
# users.users.alice = {
# isNormalUser = true;
# extraGroups = [ "wheel" ]; # Enable sudo for the user.
# packages = with pkgs; [
# firefox
# tree
# ];
# };
# List packages installed in system profile. To search, run:
# \$ nix search wget
# environment.systemPackages = with pkgs; [
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
# ];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
# system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "${config.system.nixos.release}"; # Did you read the comment?
}
'';
environment.systemPackages =
[ nixos-build-vms
nixos-install
nixos-rebuild
nixos-generate-config
nixos-option
nixos-version
nixos-enter
];
documentation.man.man-db.skipPackages = [ nixos-version ];
})
# These may be used in auxiliary scripts (ie not part of toplevel), so they are defined unconditionally.
({
system.build = {
inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter;
}; };
})]; in [
(mkToolModule { name = "nixos-build-vms"; })
(mkToolModule { name = "nixos-enter"; })
(mkToolModule { name = "nixos-generate-config"; package = nixos-generate-config; })
(mkToolModule { name = "nixos-install"; package = nixos-install; })
(mkToolModule { name = "nixos-option"; })
(mkToolModule { name = "nixos-rebuild"; package = nixos-rebuild; })
(mkToolModule { name = "nixos-version"; package = nixos-version; })
];
config = lib.mkMerge [
(lib.mkIf config.system.disableInstallerTools {
system.tools = {
nixos-build-vms.enable = false;
nixos-enter.enable = false;
nixos-generate-config.enable = false;
nixos-install.enable = false;
nixos-option.enable = false;
nixos-rebuild.enable = false;
nixos-version.enable = false;
};
})
{
documentation.man.man-db.skipPackages = [ nixos-version ];
# These may be used in auxiliary scripts (ie not part of toplevel), so they are defined unconditionally.
system.build = {
inherit nixos-generate-config nixos-install nixos-rebuild;
nixos-option = lib.warn "Accessing nixos-option through `config.system.build` is deprecated, use `pkgs.nixos-option` instead." pkgs.nixos-option;
nixos-enter = lib.warn "Accessing nixos-enter through `config.system.build` is deprecated, use `pkgs.nixos-enter` instead." pkgs.nixos-enter;
};
}
];
} }

View file

@ -386,7 +386,10 @@ in
`nixpkgs.config` options should be passed when creating the instance instead. `nixpkgs.config` options should be passed when creating the instance instead.
Current value: Current value:
${lib.generators.toPretty { multiline = true; } opt.config} ${lib.generators.toPretty { multiline = true; } cfg.config}
Defined in:
${lib.concatMapStringsSep "\n" (file: " - ${file}") opt.config.files}
''; '';
} }
]; ];

View file

@ -16,6 +16,11 @@ let
nixpkgs.hostPlatform = "aarch64-linux"; nixpkgs.hostPlatform = "aarch64-linux";
nixpkgs.buildPlatform = "aarch64-linux"; nixpkgs.buildPlatform = "aarch64-linux";
}; };
externalPkgsWithConfig = {
_file = "ext-pkgs-config.nix";
nixpkgs.pkgs = pkgs;
nixpkgs.config.allowUnfree = true;
};
ambiguous = { ambiguous = {
_file = "ambiguous.nix"; _file = "ambiguous.nix";
nixpkgs.hostPlatform = "aarch64-linux"; nixpkgs.hostPlatform = "aarch64-linux";
@ -108,6 +113,20 @@ lib.recurseIntoAttrs {
For a future proof system configuration, we recommend to remove For a future proof system configuration, we recommend to remove
the legacy definitions. the legacy definitions.
'']; ''];
assert builtins.trace (lib.head (getErrors externalPkgsWithConfig))
getErrors externalPkgsWithConfig ==
[''
Your system configures nixpkgs with an externally created instance.
`nixpkgs.config` options should be passed when creating the instance instead.
Current value:
{
allowUnfree = true;
}
Defined in:
- ext-pkgs-config.nix
''];
assert getErrors { assert getErrors {
nixpkgs.localSystem = pkgs.stdenv.hostPlatform; nixpkgs.localSystem = pkgs.stdenv.hostPlatform;
nixpkgs.hostPlatform = pkgs.stdenv.hostPlatform; nixpkgs.hostPlatform = pkgs.stdenv.hostPlatform;

View file

@ -20,7 +20,6 @@
./config/nix-channel.nix ./config/nix-channel.nix
./config/nix-flakes.nix ./config/nix-flakes.nix
./config/nix-remote-build.nix ./config/nix-remote-build.nix
./config/no-x-libs.nix
./config/nsswitch.nix ./config/nsswitch.nix
./config/power-management.nix ./config/power-management.nix
./config/pulseaudio.nix ./config/pulseaudio.nix
@ -858,6 +857,7 @@
./services/misc/tautulli.nix ./services/misc/tautulli.nix
./services/misc/tiddlywiki.nix ./services/misc/tiddlywiki.nix
./services/misc/tp-auto-kbbl.nix ./services/misc/tp-auto-kbbl.nix
./services/misc/turn-rs.nix
./services/misc/tuxclocker.nix ./services/misc/tuxclocker.nix
./services/misc/transfer-sh.nix ./services/misc/transfer-sh.nix
./services/misc/tzupdate.nix ./services/misc/tzupdate.nix
@ -1044,7 +1044,6 @@
./services/networking/gdomap.nix ./services/networking/gdomap.nix
./services/networking/ghostunnel.nix ./services/networking/ghostunnel.nix
./services/networking/git-daemon.nix ./services/networking/git-daemon.nix
./services/networking/globalprotect-vpn.nix
./services/networking/gns3-server.nix ./services/networking/gns3-server.nix
./services/networking/gnunet.nix ./services/networking/gnunet.nix
./services/networking/go-autoconfig.nix ./services/networking/go-autoconfig.nix
@ -1193,6 +1192,7 @@
./services/networking/scion/scion-daemon.nix ./services/networking/scion/scion-daemon.nix
./services/networking/scion/scion-dispatcher.nix ./services/networking/scion/scion-dispatcher.nix
./services/networking/scion/scion-router.nix ./services/networking/scion/scion-router.nix
./services/networking/scion/scion-ip-gateway.nix
./services/networking/seafile.nix ./services/networking/seafile.nix
./services/networking/searx.nix ./services/networking/searx.nix
./services/networking/shadowsocks.nix ./services/networking/shadowsocks.nix
@ -1397,6 +1397,7 @@
./services/web-apps/crabfit.nix ./services/web-apps/crabfit.nix
./services/web-apps/davis.nix ./services/web-apps/davis.nix
./services/web-apps/cryptpad.nix ./services/web-apps/cryptpad.nix
./services/web-apps/dependency-track.nix
./services/web-apps/dex.nix ./services/web-apps/dex.nix
./services/web-apps/discourse.nix ./services/web-apps/discourse.nix
./services/web-apps/documize.nix ./services/web-apps/documize.nix
@ -1430,6 +1431,7 @@
./services/web-apps/icingaweb2/icingaweb2.nix ./services/web-apps/icingaweb2/icingaweb2.nix
./services/web-apps/icingaweb2/module-monitoring.nix ./services/web-apps/icingaweb2/module-monitoring.nix
./services/web-apps/ifm.nix ./services/web-apps/ifm.nix
./services/web-apps/immich.nix
./services/web-apps/invidious.nix ./services/web-apps/invidious.nix
./services/web-apps/invoiceplane.nix ./services/web-apps/invoiceplane.nix
./services/web-apps/isso.nix ./services/web-apps/isso.nix
@ -1624,6 +1626,7 @@
./system/boot/stage-2.nix ./system/boot/stage-2.nix
./system/boot/systemd.nix ./system/boot/systemd.nix
./system/boot/systemd/coredump.nix ./system/boot/systemd/coredump.nix
./system/boot/systemd/dm-verity.nix
./system/boot/systemd/initrd-secrets.nix ./system/boot/systemd/initrd-secrets.nix
./system/boot/systemd/initrd.nix ./system/boot/systemd/initrd.nix
./system/boot/systemd/journald.nix ./system/boot/systemd/journald.nix
@ -1638,6 +1641,7 @@
./system/boot/systemd/sysupdate.nix ./system/boot/systemd/sysupdate.nix
./system/boot/systemd/sysusers.nix ./system/boot/systemd/sysusers.nix
./system/boot/systemd/tmpfiles.nix ./system/boot/systemd/tmpfiles.nix
./system/boot/systemd/tpm2.nix
./system/boot/systemd/user.nix ./system/boot/systemd/user.nix
./system/boot/systemd/userdbd.nix ./system/boot/systemd/userdbd.nix
./system/boot/systemd/homed.nix ./system/boot/systemd/homed.nix

View file

@ -52,7 +52,7 @@ in
# VMware support. # VMware support.
"mptspi" "vmxnet3" "vsock" "mptspi" "vmxnet3" "vsock"
] ++ lib.optional platform.isx86 "vmw_balloon" ] ++ lib.optional platform.isx86 "vmw_balloon"
++ lib.optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [ ++ lib.optionals (pkgs.stdenv.hostPlatform.isi686 || pkgs.stdenv.hostPlatform.isx86_64) [
"vmw_vmci" "vmwgfx" "vmw_vsock_vmci_transport" "vmw_vmci" "vmwgfx" "vmw_vsock_vmci_transport"
# Hyper-V support. # Hyper-V support.
@ -68,7 +68,7 @@ in
# Broadcom # Broadcom
"vc4" "vc4"
] ++ lib.optionals pkgs.stdenv.isAarch64 [ ] ++ lib.optionals pkgs.stdenv.hostPlatform.isAarch64 [
# Most of the following falls into two categories: # Most of the following falls into two categories:
# - early KMS / early display # - early KMS / early display
# - early storage (e.g. USB) support # - early storage (e.g. USB) support

View file

@ -19,13 +19,7 @@
pkgs.cryptsetup # needed for dm-crypt volumes pkgs.cryptsetup # needed for dm-crypt volumes
# Some text editors. # Some text editors.
(pkgs.vim.customize { pkgs.vim
name = "vim";
vimrcConfig.packages.default = {
start = [ pkgs.vimPlugins.vim-nix ];
};
vimrcConfig.customRC = "syntax on";
})
# Some networking tools. # Some networking tools.
pkgs.fuse pkgs.fuse

View file

@ -19,7 +19,7 @@ with lib;
# Perl is a default package. # Perl is a default package.
environment.defaultPackages = mkDefault [ ]; environment.defaultPackages = mkDefault [ ];
environment.stub-ld.enable = false; environment.stub-ld.enable = mkDefault false;
# The lessopen package pulls in Perl. # The lessopen package pulls in Perl.
programs.less.lessopen = mkDefault null; programs.less.lessopen = mkDefault null;
@ -29,6 +29,8 @@ with lib;
programs.command-not-found.enable = mkDefault false; programs.command-not-found.enable = mkDefault false;
programs.ssh.setXAuthLocation = mkDefault false;
services.logrotate.enable = mkDefault false; services.logrotate.enable = mkDefault false;
services.udisks2.enable = mkDefault false; services.udisks2.enable = mkDefault false;

View file

@ -1,9 +1,22 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
options.programs.clash-verge = { options.programs.clash-verge = {
enable = lib.mkEnableOption "Clash Verge"; enable = lib.mkEnableOption "Clash Verge";
package = lib.mkPackageOption pkgs "clash-verge" {}; package = lib.mkOption {
type = lib.types.package;
description = ''
The clash-verge package to use. Available options are
clash-verge-rev and clash-nyanpasu, both are forks of
the original clash-verge project.
'';
example = "pkgs.clash-verge-rev";
};
autoStart = lib.mkEnableOption "Clash Verge auto launch"; autoStart = lib.mkEnableOption "Clash Verge auto launch";
tunMode = lib.mkEnableOption "Clash Verge TUN mode"; tunMode = lib.mkEnableOption "Clash Verge TUN mode";
}; };
@ -16,10 +29,12 @@
environment.systemPackages = [ environment.systemPackages = [
cfg.package cfg.package
(lib.mkIf cfg.autoStart (pkgs.makeAutostartItem { (lib.mkIf cfg.autoStart (
name = "clash-verge"; pkgs.makeAutostartItem {
package = cfg.package; name = "clash-verge";
})) package = cfg.package;
}
))
]; ];
security.wrappers.clash-verge = lib.mkIf cfg.tunMode { security.wrappers.clash-verge = lib.mkIf cfg.tunMode {

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
cfg = config.programs.nautilus-open-any-terminal; cfg = config.programs.nautilus-open-any-terminal;
@ -23,20 +28,28 @@ in
nautilus-open-any-terminal nautilus-open-any-terminal
]; ];
environment.sessionVariables.NAUTILUS_4_EXTENSION_DIR = "${pkgs.nautilus-python}/lib/nautilus/extensions-4"; environment.sessionVariables = lib.mkIf (!config.services.xserver.desktopManager.gnome.enable) {
NAUTILUS_4_EXTENSION_DIR = "${pkgs.nautilus-python}/lib/nautilus/extensions-4";
};
environment.pathsToLink = [ environment.pathsToLink = [
"/share/nautilus-python/extensions" "/share/nautilus-python/extensions"
]; ];
programs.dconf = lib.optionalAttrs (cfg.terminal != null) { programs.dconf = lib.optionalAttrs (cfg.terminal != null) {
enable = true; enable = true;
profiles.user.databases = [{ profiles.user.databases = [
settings."com/github/stunkymonkey/nautilus-open-any-terminal".terminal = cfg.terminal; {
lockAll = true; settings."com/github/stunkymonkey/nautilus-open-any-terminal".terminal = cfg.terminal;
}]; lockAll = true;
}
];
}; };
}; };
meta = { meta = {
maintainers = with lib.maintainers; [ stunkymonkey linsui ]; maintainers = with lib.maintainers; [
stunkymonkey
linsui
];
}; };
} }

View file

@ -1,4 +1,9 @@
{ lib, pkgs, config, ... }: {
lib,
pkgs,
config,
...
}:
let let
cfg = config.programs.waybar; cfg = config.programs.waybar;
@ -11,11 +16,9 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
systemd.user.services.waybar = { systemd = {
description = "Waybar as systemd service"; packages = [ cfg.package ];
wantedBy = [ "graphical-session.target" ]; user.services.waybar.wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
script = "${cfg.package}/bin/waybar";
}; };
}; };

View file

@ -21,6 +21,10 @@ in
# Completely removed modules # Completely removed modules
(mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed") (mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
(mkRemovedOptionModule [ "environment" "noXlibs" ] ''
The environment.noXlibs option was removed, as it often caused surprising breakages for new users.
If you need its functionality, you can apply similar overlays in your own config.
'')
(mkRemovedOptionModule [ "fonts" "fontconfig" "penultimate" ] "The corresponding package has removed from nixpkgs.") (mkRemovedOptionModule [ "fonts" "fontconfig" "penultimate" ] "The corresponding package has removed from nixpkgs.")
(mkRemovedOptionModule [ "hardware" "brightnessctl" ] '' (mkRemovedOptionModule [ "hardware" "brightnessctl" ] ''
The brightnessctl module was removed because newer versions of The brightnessctl module was removed because newer versions of
@ -74,6 +78,7 @@ in
(mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed") (mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
(mkRemovedOptionModule [ "services" "fprot" ] "The corresponding package was removed from nixpkgs.") (mkRemovedOptionModule [ "services" "fprot" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "frab" ] "The frab module has been removed") (mkRemovedOptionModule [ "services" "frab" ] "The frab module has been removed")
(mkRemovedOptionModule [ "services" "globalprotect"] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "homeassistant-satellite"] "The `services.homeassistant-satellite` module has been replaced by `services.wyoming-satellite`.") (mkRemovedOptionModule [ "services" "homeassistant-satellite"] "The `services.homeassistant-satellite` module has been replaced by `services.wyoming-satellite`.")
(mkRemovedOptionModule [ "services" "hydron" ] "The `services.hydron` module has been removed as the project has been archived upstream since 2022 and is affected by a severe remote code execution vulnerability.") (mkRemovedOptionModule [ "services" "hydron" ] "The `services.hydron` module has been removed as the project has been archived upstream since 2022 and is affected by a severe remote code execution vulnerability.")
(mkRemovedOptionModule [ "services" "ihatemoney" ] "The ihatemoney module has been removed for lack of downstream maintainer") (mkRemovedOptionModule [ "services" "ihatemoney" ] "The ihatemoney module has been removed for lack of downstream maintainer")

View file

@ -8,7 +8,7 @@ let
pcmPlugin = cfg.jackd.enable && cfg.alsa.enable; pcmPlugin = cfg.jackd.enable && cfg.alsa.enable;
loopback = cfg.jackd.enable && cfg.loopback.enable; loopback = cfg.jackd.enable && cfg.loopback.enable;
enable32BitAlsaPlugins = cfg.alsa.support32Bit && pkgs.stdenv.isx86_64 && pkgs.pkgsi686Linux.alsa-lib != null; enable32BitAlsaPlugins = cfg.alsa.support32Bit && pkgs.stdenv.hostPlatform.isx86_64 && pkgs.pkgsi686Linux.alsa-lib != null;
umaskNeeded = versionOlder cfg.jackd.package.version "1.9.12"; umaskNeeded = versionOlder cfg.jackd.package.version "1.9.12";
bridgeNeeded = versionAtLeast cfg.jackd.package.version "1.9.12"; bridgeNeeded = versionAtLeast cfg.jackd.package.version "1.9.12";

View file

@ -30,12 +30,12 @@ let
lib.optionalString (val != null) "${val}"; lib.optionalString (val != null) "${val}";
os' = prefix: val: os' = prefix: val:
lib.optionalString (val != null) (prefix + "${val}"); lib.optionalString (val != null) (prefix + "${val}");
flatten = key: value: toQueryString = key: value:
"&${key}=${value}"; "&${key}=${value}";
in in
"--stream.stream=\"${opt.type}://" + os opt.location + "?" + os' "name=" name "--stream.stream=\"${opt.type}://" + os opt.location + "?" + os' "name=" name
+ os' "&sampleformat=" opt.sampleFormat + os' "&codec=" opt.codec + os' "&sampleformat=" opt.sampleFormat + os' "&codec=" opt.codec
+ lib.concatStrings (lib.mapAttrsToList lib.flatten opt.query) + "\""; + lib.concatStrings (lib.mapAttrsToList toQueryString opt.query) + "\"";
optionalNull = val: ret: optionalNull = val: ret:
lib.optional (val != null) ret; lib.optional (val != null) ret;

View file

@ -118,15 +118,6 @@ in
name = user; name = user;
ensurePermissions = { ensurePermissions = {
"*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT"; "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT";
# https://forums.mysql.com/read.php?10,668311,668315#msg-668315
"function sys.extract_table_from_file_name" = "execute";
"function sys.format_path" = "execute";
"function sys.format_statement" = "execute";
"function sys.extract_schema_from_file_name" = "execute";
"function sys.ps_thread_account" = "execute";
"function sys.format_time" = "execute";
"function sys.format_bytes" = "execute";
}; };
}; };

View file

@ -656,6 +656,11 @@ in {
}; };
config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) { config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) {
systemd.slices.system-bacula = {
description = "Bacula Slice";
documentation = [ "man:bacula(8)" "https://www.bacula.org/" ];
};
systemd.services.bacula-fd = mkIf fd_cfg.enable { systemd.services.bacula-fd = mkIf fd_cfg.enable {
after = [ "network.target" ]; after = [ "network.target" ];
description = "Bacula File Daemon"; description = "Bacula File Daemon";
@ -666,6 +671,7 @@ in {
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
LogsDirectory = "bacula"; LogsDirectory = "bacula";
StateDirectory = "bacula"; StateDirectory = "bacula";
Slice = "system-bacula.slice";
}; };
}; };
@ -679,6 +685,7 @@ in {
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
LogsDirectory = "bacula"; LogsDirectory = "bacula";
StateDirectory = "bacula"; StateDirectory = "bacula";
Slice = "system-bacula.slice";
}; };
}; };
@ -694,6 +701,7 @@ in {
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
LogsDirectory = "bacula"; LogsDirectory = "bacula";
StateDirectory = "bacula"; StateDirectory = "bacula";
Slice = "system-bacula.slice";
}; };
preStart = '' preStart = ''
if ! test -e "${libDir}/db-created"; then if ! test -e "${libDir}/db-created"; then

View file

@ -515,10 +515,12 @@ in
'' ''
set -eou pipefail set -eou pipefail
compression=$(sed -nr 's/compress_build_logs_compression = ()/\1/p' ${baseDir}/hydra.conf) compression=$(sed -nr 's/compress_build_logs_compression = ()/\1/p' ${baseDir}/hydra.conf)
if [[ $compression == zstd ]]; then if [[ $compression == "" ]]; then
compression="bzip2"
elif [[ $compression == zstd ]]; then
compression="zstd --rm" compression="zstd --rm"
fi fi
find ${baseDir}/build-logs -type f -name "*.drv" -mtime +3 -size +0c | xargs -r $compression --force --quiet find ${baseDir}/build-logs -type f -name "*.drv" -mtime +3 -size +0c | xargs -r "$compression" --force --quiet
''; '';
startAt = "Sun 01:45"; startAt = "Sun 01:45";
serviceConfig.Slice = "system-hydra.slice"; serviceConfig.Slice = "system-hydra.slice";

View file

@ -67,16 +67,16 @@ let
inherit (cfg.provision) organizations users; inherit (cfg.provision) organizations users;
}); });
provisioningScript = pkgs.writeShellScript "post-start-provision" '' influxHost = "http://${escapeShellArg (
set -euo pipefail
export INFLUX_HOST="http://"${escapeShellArg (
if ! hasAttr "http-bind-address" cfg.settings if ! hasAttr "http-bind-address" cfg.settings
|| hasInfix "0.0.0.0" cfg.settings.http-bind-address || hasInfix "0.0.0.0" cfg.settings.http-bind-address
then "localhost:8086" then "localhost:8086"
else cfg.settings.http-bind-address else cfg.settings.http-bind-address
)} )}";
# Wait for the influxdb server to come online waitUntilServiceIsReady = pkgs.writeShellScript "wait-until-service-is-ready" ''
set -euo pipefail
export INFLUX_HOST=${influxHost}
count=0 count=0
while ! influx ping &>/dev/null; do while ! influx ping &>/dev/null; do
if [ "$count" -eq 300 ]; then if [ "$count" -eq 300 ]; then
@ -92,6 +92,11 @@ let
sleep 0.1 sleep 0.1
count=$((count++)) count=$((count++))
done done
'';
provisioningScript = pkgs.writeShellScript "post-start-provision" ''
set -euo pipefail
export INFLUX_HOST=${influxHost}
# Do the initial database setup. Pass /dev/null as configs-path to # Do the initial database setup. Pass /dev/null as configs-path to
# avoid saving the token as the active config. # avoid saving the token as the active config.
@ -447,11 +452,13 @@ in
"admin-token:${cfg.provision.initialSetup.tokenFile}" "admin-token:${cfg.provision.initialSetup.tokenFile}"
]; ];
ExecStartPost = mkIf cfg.provision.enable ( ExecStartPost = [
waitUntilServiceIsReady
] ++ (lib.optionals cfg.provision.enable (
[provisioningScript] ++ [provisioningScript] ++
# Only the restarter runs with elevated privileges # Only the restarter runs with elevated privileges
optional anyAuthDefined "+${restarterScript}" optional anyAuthDefined "+${restarterScript}"
); ));
}; };
path = [ path = [

View file

@ -35,3 +35,10 @@ Note that the TigerBeetle module won't open any firewall ports automatically, so
A complete list of options for TigerBeetle can be found [here](#opt-services.tigerbeetle.enable). A complete list of options for TigerBeetle can be found [here](#opt-services.tigerbeetle.enable).
## Upgrading {#module-services-tigerbeetle-upgrading}
Usually, TigerBeetle's [upgrade process](https://docs.tigerbeetle.com/operating/upgrading) only requires replacing the binary used for the servers.
This is not directly possible with NixOS since the new binary will be located at a different place in the Nix store.
However, since TigerBeetle is managed through systemd on NixOS, the only action you need to take when upgrading is to make sure the version of TigerBeetle you're upgrading to supports upgrades from the version you're currently running.
This information will be on the [release notes](https://github.com/tigerbeetle/tigerbeetle/releases) for the version you're upgrading to.

View file

@ -42,8 +42,8 @@ in
}; };
cacheGridSize = mkOption { cacheGridSize = mkOption {
type = types.strMatching "[0-9]+(K|M|G)B"; type = types.strMatching "[0-9]+(K|M|G)iB";
default = "1GB"; default = "1GiB";
description = '' description = ''
The grid cache size. The grid cache size.
The grid cache acts like a page cache for TigerBeetle. The grid cache acts like a page cache for TigerBeetle.
@ -97,16 +97,26 @@ in
''; '';
serviceConfig = { serviceConfig = {
Type = "exec";
DynamicUser = true;
ProtectHome = true;
DevicePolicy = "closed"; DevicePolicy = "closed";
DynamicUser = true;
ExecStart = "${lib.getExe cfg.package} start --cache-grid=${cfg.cacheGridSize} --addresses=${lib.escapeShellArg (builtins.concatStringsSep "," cfg.addresses)} ${replicaDataPath}";
LockPersonality = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "noaccess";
ProtectSystem = "strict";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
StateDirectory = "tigerbeetle"; StateDirectory = "tigerbeetle";
StateDirectoryMode = 700; StateDirectoryMode = 700;
Type = "exec";
ExecStart = "${lib.getExe cfg.package} start --cache-grid=${cfg.cacheGridSize} --addresses=${lib.escapeShellArg (builtins.concatStringsSep "," cfg.addresses)} ${replicaDataPath}";
}; };
}; };

View file

@ -19,7 +19,7 @@ let
''; '';
cfg = config.services.pipewire; cfg = config.services.pipewire;
enable32BitAlsaPlugins = cfg.alsa.support32Bit enable32BitAlsaPlugins = cfg.alsa.support32Bit
&& pkgs.stdenv.isx86_64 && pkgs.stdenv.hostPlatform.isx86_64
&& pkgs.pkgsi686Linux.pipewire != null; && pkgs.pkgsi686Linux.pipewire != null;
# The package doesn't output to $out/lib/pipewire directly so that the # The package doesn't output to $out/lib/pipewire directly so that the

View file

@ -18,15 +18,15 @@ in {
type = lib.types.submodule { type = lib.types.submodule {
freeformType = format.type; freeformType = format.type;
options = { options = {
Touch = { Touchscreen = {
DisableOnPalm = lib.mkOption { DisableOnPalm = lib.mkOption {
default = false; default = false;
description = "Ignore all touch inputs if a palm was registered on the display."; description = "Ignore all touchscreen inputs if a palm was registered on the display.";
type = lib.types.bool; type = lib.types.bool;
}; };
DisableOnStylus = lib.mkOption { DisableOnStylus = lib.mkOption {
default = false; default = false;
description = "Ignore all touch inputs if a stylus is in proximity."; description = "Ignore all touchscreen inputs if a stylus is in proximity.";
type = lib.types.bool; type = lib.types.bool;
}; };
}; };
@ -43,6 +43,10 @@ in {
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
warnings = lib.optional (lib.hasAttr "Touch" cfg.config) ''
The option `services.iptsd.config.Touch` has been renamed to `services.iptsd.config.Touchscreen`.
'';
systemd.packages = [ pkgs.iptsd ]; systemd.packages = [ pkgs.iptsd ];
environment.etc."iptsd.conf".source = configFile; environment.etc."iptsd.conf".source = configFile;
systemd.services."iptsd@".restartTriggers = [ configFile ]; systemd.services."iptsd@".restartTriggers = [ configFile ];

View file

@ -434,7 +434,7 @@ in
''; '';
systemd.services.systemd-udevd = systemd.services.systemd-udevd =
{ restartTriggers = cfg.packages; { restartTriggers = [ config.environment.etc."udev/rules.d".source ];
}; };
}; };

View file

@ -97,6 +97,8 @@ in
defaultText = lib.literalExpression "cfg.settings != {}"; defaultText = lib.literalExpression "cfg.settings != {}";
}; };
allowNetworking = lib.mkEnableOption "network access for logrotate";
settings = lib.mkOption { settings = lib.mkOption {
default = { }; default = { };
description = '' description = ''
@ -240,12 +242,55 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.logrotate = { systemd.services.logrotate = {
description = "Logrotate Service"; description = "Logrotate Service";
documentation = [
"man:logrotate(8)"
"man:logrotate(5)"
];
startAt = "hourly"; startAt = "hourly";
serviceConfig = { serviceConfig = {
Restart = "no"; Type = "oneshot";
User = "root"; ExecStart = "${lib.getExe pkgs.logrotate} ${utils.escapeSystemdExecArgs cfg.extraArgs} ${mailOption} ${cfg.configFile}";
ExecStart = "${pkgs.logrotate}/sbin/logrotate ${utils.escapeSystemdExecArgs cfg.extraArgs} ${mailOption} ${cfg.configFile}";
# performance
Nice = 19;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
# hardening
CapabilityBoundingSet = [
"CAP_CHOWN"
"CAP_SETGID"
];
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "full";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged @resources"
"@chown"
];
UMask = "0027";
} // lib.optionalAttrs (!cfg.allowNetworking) {
PrivateNetwork = true;
RestrictAddressFamilies = "none";
}; };
}; };
systemd.services.logrotate-checkconf = { systemd.services.logrotate-checkconf = {

View file

@ -80,7 +80,7 @@ in {
PrivateUsers = true; PrivateUsers = true;
SupplementaryGroups = lib.optional (allowSystemdJournal) "systemd-journal"; SupplementaryGroups = lib.optional (allowSystemdJournal) "systemd-journal";
} // (optionalAttrs (!pkgs.stdenv.isAarch64) { # FIXME: figure out why this breaks on aarch64 } // (optionalAttrs (!pkgs.stdenv.hostPlatform.isAarch64) { # FIXME: figure out why this breaks on aarch64
SystemCallFilter = "@system-service"; SystemCallFilter = "@system-service";
}); });
}; };

View file

@ -30,6 +30,10 @@ let
ENGINE = "haystack.backends.whoosh_backend.WhooshEngine"; ENGINE = "haystack.backends.whoosh_backend.WhooshEngine";
PATH = "/var/lib/mailman-web/fulltext-index"; PATH = "/var/lib/mailman-web/fulltext-index";
}; };
} // lib.optionalAttrs cfg.enablePostfix {
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend";
EMAIL_HOST = "127.0.0.1";
EMAIL_PORT = 25;
} // cfg.webSettings; } // cfg.webSettings;
webSettingsJSON = pkgs.writeText "settings.json" (builtins.toJSON webSettings); webSettingsJSON = pkgs.writeText "settings.json" (builtins.toJSON webSettings);

View file

@ -1,7 +1,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
cfg = config.services.mame; cfg = config.services.mame;
mame = "mame${lib.optionalString pkgs.stdenv.is64bit "64"}"; mame = "mame${lib.optionalString pkgs.stdenv.hostPlatform.is64bit "64"}";
in in
{ {
options = { options = {

View file

@ -448,4 +448,5 @@ in
}; };
meta.maintainers = with lib.maintainers; [ felixsinger ];
} }

View file

@ -71,7 +71,7 @@ in
- nixpkgs.config.cudaSupport - nixpkgs.config.cudaSupport
- nixpkgs.config.rocmSupport - nixpkgs.config.rocmSupport
- if stdenv.isDarwin && stdenv.isAarch64 - if stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64
IFF multiple acceleration methods are found to be enabled or if you IFF multiple acceleration methods are found to be enabled or if you
haven't set either `cudaSupport or rocmSupport` you will have to haven't set either `cudaSupport or rocmSupport` you will have to

View file

@ -0,0 +1,86 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.turn-rs;
format = pkgs.formats.toml { };
in
{
options.services.turn-rs = {
enable = lib.mkEnableOption "turn-rs server";
package = lib.mkPackageOption pkgs "turn-rs" { };
secretFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
example = "/run/keys/turn-rs.env";
description = ''
Environment variables from this file will be interpolated into the
final config file using envsubst with this syntax: `$ENVIRONMENT` or
`''${VARIABLE}`.
The file should contain lines formatted as `SECRET_VAR=SECRET_VALUE`.
This is useful to avoid putting secrets into the nix store.
'';
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = format.type;
};
description = "Turn-rs server config file";
default = { };
example = {
turn = {
realm = "localhost";
interfaces = [
{
transport = "udp";
bind = "127.0.0.1:3478";
external = "127.0.0.1:3478";
}
{
transport = "tcp";
bind = "127.0.0.1:3478";
external = "127.0.0.1:3478";
}
];
};
auth.static_credentials = {
user1 = "test";
user2 = "test";
};
};
};
};
config = lib.mkIf cfg.enable {
services.turn-rs.settings = {
api.bind = lib.mkDefault "127.0.0.1:3000";
log.level = lib.mkDefault "info";
};
systemd.services.turn-rs = {
enable = true;
wantedBy = [ "multi-user.target" ];
description = "Turn-rs Server Daemon";
preStart =
let
configFile = format.generate "turn-rs-config.toml" cfg.settings;
in
''
${lib.getExe pkgs.envsubst} -i "${configFile}" -o /run/turn-rs/config.toml
'';
serviceConfig = {
RuntimeDirectory = "turn-rs";
EnvironmentFile = lib.optional (cfg.secretFile != null) cfg.secretFile;
ExecStart = "${lib.getExe cfg.package} --config=/run/turn-rs/config.toml";
DynamicUser = true;
};
};
};
}

View file

@ -236,9 +236,17 @@ let
isSystemUser = true; isSystemUser = true;
inherit (conf) group; inherit (conf) group;
}); });
users.groups = (mkIf (conf.group == "${name}-exporter" && !enableDynamicUser) { users.groups = mkMerge [
"${name}-exporter" = {}; (mkIf (conf.group == "${name}-exporter" && !enableDynamicUser) {
}); "${name}-exporter" = {};
})
(mkIf (name == "smartctl") {
"smartctl-exporter-access" = {};
})
];
services.udev.extraRules = mkIf (name == "smartctl") ''
ACTION=="add", SUBSYSTEM=="nvme", KERNEL=="nvme[0-9]*", RUN+="${pkgs.acl}/bin/setfacl -m g:smartctl-exporter-access:rw /dev/$kernel"
'';
networking.firewall.extraCommands = mkIf (conf.openFirewall && !nftables) (concatStrings [ networking.firewall.extraCommands = mkIf (conf.openFirewall && !nftables) (concatStrings [
"ip46tables -A nixos-fw ${conf.firewallFilter} " "ip46tables -A nixos-fw ${conf.firewallFilter} "
"-m comment --comment ${name}-exporter -j nixos-fw-accept" "-m comment --comment ${name}-exporter -j nixos-fw-accept"

View file

@ -58,7 +58,7 @@ in
PrivateDevices = lib.mkForce false; PrivateDevices = lib.mkForce false;
ProtectProc = "invisible"; ProtectProc = "invisible";
ProcSubset = "pid"; ProcSubset = "pid";
SupplementaryGroups = [ "disk" ]; SupplementaryGroups = [ "disk" "smartctl-exporter-access" ];
SystemCallFilter = [ "@system-service" "~@privileged" ]; SystemCallFilter = [ "@system-service" "~@privileged" ];
}; };
}; };

View file

@ -269,7 +269,10 @@ in
systemd.services.smartd = { systemd.services.smartd = {
description = "S.M.A.R.T. Daemon"; description = "S.M.A.R.T. Daemon";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}"; serviceConfig = {
Type = "notify";
ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}";
};
}; };
services.systembus-notify.enable = mkDefault ns.enable; services.systembus-notify.enable = mkDefault ns.enable;

View file

@ -509,6 +509,11 @@ in
else lib.unique (lib.forEach cfg.upsd.listen (listen: listen.port)); else lib.unique (lib.forEach cfg.upsd.listen (listen: listen.port));
}; };
systemd.slices.system-ups = {
description = "Network UPS Tools (NUT) Slice";
documentation = [ "https://networkupstools.org/" ];
};
systemd.services.upsmon = let systemd.services.upsmon = let
secrets = lib.mapAttrsToList (name: monitor: "upsmon_password_${name}") cfg.upsmon.monitor; secrets = lib.mapAttrsToList (name: monitor: "upsmon_password_${name}") cfg.upsmon.monitor;
createUpsmonConf = installSecrets upsmonConf "/run/nut/upsmon.conf" secrets; createUpsmonConf = installSecrets upsmonConf "/run/nut/upsmon.conf" secrets;
@ -523,6 +528,7 @@ in
ExecStart = "${pkgs.nut}/sbin/upsmon"; ExecStart = "${pkgs.nut}/sbin/upsmon";
ExecReload = "${pkgs.nut}/sbin/upsmon -c reload"; ExecReload = "${pkgs.nut}/sbin/upsmon -c reload";
LoadCredential = lib.mapAttrsToList (name: monitor: "upsmon_password_${name}:${monitor.passwordFile}") cfg.upsmon.monitor; LoadCredential = lib.mapAttrsToList (name: monitor: "upsmon_password_${name}:${monitor.passwordFile}") cfg.upsmon.monitor;
Slice = "system-ups.slice";
}; };
environment = envVars; environment = envVars;
}; };
@ -542,6 +548,7 @@ in
ExecStart = "${pkgs.nut}/sbin/upsd -u root"; ExecStart = "${pkgs.nut}/sbin/upsd -u root";
ExecReload = "${pkgs.nut}/sbin/upsd -c reload"; ExecReload = "${pkgs.nut}/sbin/upsd -c reload";
LoadCredential = lib.mapAttrsToList (name: user: "upsdusers_password_${name}:${user.passwordFile}") cfg.users; LoadCredential = lib.mapAttrsToList (name: user: "upsdusers_password_${name}:${user.passwordFile}") cfg.users;
Slice = "system-ups.slice";
}; };
environment = envVars; environment = envVars;
restartTriggers = [ restartTriggers = [
@ -559,6 +566,7 @@ in
RemainAfterExit = true; RemainAfterExit = true;
# TODO: replace 'root' by another username. # TODO: replace 'root' by another username.
ExecStart = "${pkgs.nut}/bin/upsdrvctl -u root start"; ExecStart = "${pkgs.nut}/bin/upsdrvctl -u root start";
Slice = "system-ups.slice";
}; };
environment = envVars; environment = envVars;
restartTriggers = [ restartTriggers = [

View file

@ -274,7 +274,7 @@ in
CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID"; CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID";
ProtectSystem = true; ProtectSystem = true;
# Doesn't work on i686, causing service to fail # Doesn't work on i686, causing service to fail
MemoryDenyWriteExecute = !pkgs.stdenv.isi686; MemoryDenyWriteExecute = !pkgs.stdenv.hostPlatform.isi686;
ProtectHome = true; ProtectHome = true;
PrivateTmp = true; PrivateTmp = true;
}; };

View file

@ -20,13 +20,7 @@ let
listsAsDuplicateKeys = true; listsAsDuplicateKeys = true;
}; };
# Because formats.generate is outputting a file, we use of conf-file. Once dnsmasqConf = settingsFormat.generate "dnsmasq.conf" cfg.settings;
# `extraConfig` is deprecated we can just use
# `dnsmasqConf = format.generate "dnsmasq.conf" cfg.settings`
dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
conf-file=${settingsFormat.generate "dnsmasq.conf" cfg.settings}
${cfg.extraConfig}
'';
in in
@ -34,6 +28,7 @@ in
imports = [ imports = [
(lib.mkRenamedOptionModule [ "services" "dnsmasq" "servers" ] [ "services" "dnsmasq" "settings" "server" ]) (lib.mkRenamedOptionModule [ "services" "dnsmasq" "servers" ] [ "services" "dnsmasq" "settings" "server" ])
(lib.mkRemovedOptionModule [ "services" "dnsmasq" "extraConfig" ] "This option has been replaced by `services.dnsmasq.settings`")
]; ];
###### interface ###### interface
@ -104,17 +99,6 @@ in
''; '';
}; };
extraConfig = lib.mkOption {
type = lib.types.lines;
default = "";
description = ''
Extra configuration directives that should be added to
`dnsmasq.conf`.
This option is deprecated, please use {option}`settings` instead.
'';
};
}; };
}; };
@ -124,8 +108,6 @@ in
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
warnings = lib.optional (cfg.extraConfig != "") "Text based config is deprecated, dnsmasq now supports `services.dnsmasq.settings` for an attribute-set based config";
services.dnsmasq.settings = { services.dnsmasq.settings = {
dhcp-leasefile = lib.mkDefault "${stateDir}/dnsmasq.leases"; dhcp-leasefile = lib.mkDefault "${stateDir}/dnsmasq.leases";
conf-file = lib.mkDefault (lib.optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf"); conf-file = lib.mkDefault (lib.optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf");

View file

@ -1,57 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.globalprotect;
execStart =
if cfg.csdWrapper == null then
"${pkgs.globalprotect-openconnect}/bin/gpservice"
else
"${pkgs.globalprotect-openconnect}/bin/gpservice --csd-wrapper=${cfg.csdWrapper}";
in
{
options.services.globalprotect = {
enable = lib.mkEnableOption "globalprotect";
settings = lib.mkOption {
description = ''
GlobalProtect-openconnect configuration. For more information, visit
<https://github.com/yuezk/GlobalProtect-openconnect/wiki/Configuration>.
'';
default = { };
example = {
"vpn1.company.com" = {
openconnect-args = "--script=/path/to/vpnc-script";
};
};
type = lib.types.attrs;
};
csdWrapper = lib.mkOption {
description = ''
A script that will produce a Host Integrity Protection (HIP) report,
as described at <https://www.infradead.org/openconnect/hip.html>
'';
default = null;
example = lib.literalExpression ''"''${pkgs.openconnect}/libexec/openconnect/hipreport.sh"'';
type = lib.types.nullOr lib.types.path;
};
};
config = lib.mkIf cfg.enable {
services.dbus.packages = [ pkgs.globalprotect-openconnect ];
environment.etc."gpservice/gp.conf".text = lib.generators.toINI { } cfg.settings;
systemd.services.gpservice = {
description = "GlobalProtect openconnect DBus service";
serviceConfig = {
Type = "dbus";
BusName = "com.yuezk.qt.GPService";
ExecStart = execStart;
};
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
};
};
}

View file

@ -406,4 +406,6 @@ in
} }
''; '';
}; };
meta.maintainers = with lib.maintainers; [ felixsinger ];
} }

View file

@ -1,18 +1,18 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
with lib;
let let
inherit (lib) mkOption types;
cfg = config.services.nar-serve; cfg = config.services.nar-serve;
in in
{ {
meta = { meta = {
maintainers = [ maintainers.rizary maintainers.zimbatm ]; maintainers = with lib.maintainers; [ rizary zimbatm ];
}; };
options = { options = {
services.nar-serve = { services.nar-serve = {
enable = mkEnableOption "serving NAR file contents via HTTP"; enable = lib.mkEnableOption "serving NAR file contents via HTTP";
package = mkPackageOption pkgs "nar-serve" { }; package = lib.mkPackageOption pkgs "nar-serve" { };
port = mkOption { port = mkOption {
type = types.port; type = types.port;
@ -48,7 +48,7 @@ in
}; };
}; };
config = mkIf cfg.enable { config = lib.mkIf cfg.enable {
systemd.services.nar-serve = { systemd.services.nar-serve = {
description = "NAR server"; description = "NAR server";
after = [ "network.target" ]; after = [ "network.target" ];

View file

@ -68,10 +68,10 @@ in
servers = [ servers = [
"/${cfg.domain}/127.0.0.1#5300" "/${cfg.domain}/127.0.0.1#5300"
]; ];
extraConfig = '' settings = {
bind-interfaces bind-interfaces = true;
listen-address=127.0.0.1 listen-address = "127.0.0.1";
''; };
}; };
}; };

View file

@ -603,8 +603,8 @@ in
reuseport = mkOption { reuseport = mkOption {
type = types.bool; type = types.bool;
default = pkgs.stdenv.isLinux; default = pkgs.stdenv.hostPlatform.isLinux;
defaultText = literalExpression "pkgs.stdenv.isLinux"; defaultText = literalExpression "pkgs.stdenv.hostPlatform.isLinux";
description = '' description = ''
Whether to enable SO_REUSEPORT on all used sockets. This lets multiple Whether to enable SO_REUSEPORT on all used sockets. This lets multiple
processes bind to the same port. This speeds up operation especially processes bind to the same port. This speeds up operation especially

View file

@ -0,0 +1,92 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
globalCfg = config.services.scion;
cfg = config.services.scion.scion-ip-gateway;
toml = pkgs.formats.toml { };
json = pkgs.formats.json { };
connectionDir = if globalCfg.stateless then "/run" else "/var/lib";
defaultConfig = {
tunnel = { };
gateway = {
traffic_policy_file = "${trafficConfigFile}";
};
};
defaultTrafficConfig = {
ASes = { };
ConfigVersion = 9001;
};
configFile = toml.generate "scion-ip-gateway.toml" (recursiveUpdate defaultConfig cfg.config);
trafficConfigFile = json.generate "scion-ip-gateway-traffic.json" (
recursiveUpdate defaultTrafficConfig cfg.trafficConfig
);
in
{
options.services.scion.scion-ip-gateway = {
enable = mkEnableOption "the scion-ip-gateway service";
config = mkOption {
default = { };
type = toml.type;
example = literalExpression ''
{
tunnel = {
src_ipv4 = "172.16.100.1";
};
}
'';
description = ''
scion-ip-gateway daemon configuration
'';
};
trafficConfig = mkOption {
default = { };
type = json.type;
example = literalExpression ''
{
ASes = {
"2-ffaa:0:b" = {
Nets = [
"172.16.1.0/24"
];
};
};
ConfigVersion = 9001;
}
'';
description = ''
scion-ip-gateway traffic configuration
'';
};
};
config = mkIf cfg.enable {
systemd.services.scion-ip-gateway = {
description = "SCION IP Gateway Service";
after = [
"network-online.target"
"scion-dispatcher.service"
];
wants = [
"network-online.target"
"scion-dispatcher.service"
];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
Group = if (config.services.scion.scion-dispatcher.enable == true) then "scion" else null;
ExecStart = "${globalCfg.package}/bin/scion-ip-gateway --config ${configFile}";
DynamicUser = true;
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
Restart = "on-failure";
KillMode = "control-group";
RemainAfterExit = false;
};
};
};
}

View file

@ -42,6 +42,7 @@ in
scion-daemon.enable = true; scion-daemon.enable = true;
scion-router.enable = true; scion-router.enable = true;
scion-control.enable = true; scion-control.enable = true;
scion-ip-gateway.enable = true;
}; };
assertions = [ assertions = [
{ assertion = cfg.bypassBootstrapWarning == true; { assertion = cfg.bypassBootstrapWarning == true;

View file

@ -121,10 +121,16 @@ in {
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
}; };
script = '' # https://github.com/tailscale/tailscale/blob/v1.72.1/ipn/backend.go#L24-L32
status=$(${config.systemd.package}/bin/systemctl show -P StatusText tailscaled.service) script = let
if [[ $status != Connected* ]]; then statusCommand = "${lib.getExe cfg.package} status --json --peers=false | ${lib.getExe pkgs.jq} -r '.BackendState'";
${cfg.package}/bin/tailscale up --auth-key 'file:${cfg.authKeyFile}' ${escapeShellArgs cfg.extraUpFlags} in ''
while [[ "$(${statusCommand})" == "NoState" ]]; do
sleep 0.5
done
status=$(${statusCommand})
if [[ "$status" == "NeedsLogin" || "$status" == "NeedsMachineAuth" ]]; then
${lib.getExe cfg.package} up --auth-key 'file:${cfg.authKeyFile}' ${escapeShellArgs cfg.extraUpFlags}
fi fi
''; '';
}; };
@ -137,7 +143,7 @@ in {
Type = "oneshot"; Type = "oneshot";
}; };
script = '' script = ''
${cfg.package}/bin/tailscale set ${escapeShellArgs cfg.extraSetFlags} ${lib.getExe cfg.package} set ${escapeShellArgs cfg.extraSetFlags}
''; '';
}; };

View file

@ -50,6 +50,15 @@ let
++ optional cfg.scanOnLowSignal ''bgscan="simple:30:-70:3600"'' ++ optional cfg.scanOnLowSignal ''bgscan="simple:30:-70:3600"''
++ optional (cfg.extraConfig != "") cfg.extraConfig); ++ optional (cfg.extraConfig != "") cfg.extraConfig);
configIsGenerated = with cfg;
networks != {} || extraConfig != "" || userControlled.enable;
# the original configuration file
configFile =
if configIsGenerated
then pkgs.writeText "wpa_supplicant.conf" generatedConfig
else "/etc/wpa_supplicant.conf";
# Creates a network block for wpa_supplicant.conf # Creates a network block for wpa_supplicant.conf
mkNetwork = opts: mkNetwork = opts:
let let
@ -81,8 +90,8 @@ let
let let
deviceUnit = optional (iface != null) "sys-subsystem-net-devices-${utils.escapeSystemdPath iface}.device"; deviceUnit = optional (iface != null) "sys-subsystem-net-devices-${utils.escapeSystemdPath iface}.device";
configStr = if cfg.allowAuxiliaryImperativeNetworks configStr = if cfg.allowAuxiliaryImperativeNetworks
then "-c /etc/wpa_supplicant.conf -I ${pkgs.writeText "wpa_supplicant.conf" generatedConfig}" then "-c /etc/wpa_supplicant.conf -I ${configFile}"
else "-c /etc/wpa_supplicant.conf"; else "-c ${configFile}";
in { in {
description = "WPA Supplicant instance" + optionalString (iface != null) " for interface ${iface}"; description = "WPA Supplicant instance" + optionalString (iface != null) " for interface ${iface}";
@ -103,6 +112,12 @@ let
script = script =
'' ''
${optionalString (configIsGenerated && !cfg.allowAuxiliaryImperativeNetworks) ''
if [ -f /etc/wpa_supplicant.conf ]; then
echo >&2 "<3>/etc/wpa_supplicant.conf present but ignored. Generated ${configFile} is used instead."
fi
''}
# ensure wpa_supplicant.conf exists, or the daemon will fail to start # ensure wpa_supplicant.conf exists, or the daemon will fail to start
${optionalString cfg.allowAuxiliaryImperativeNetworks '' ${optionalString cfg.allowAuxiliaryImperativeNetworks ''
touch /etc/wpa_supplicant.conf touch /etc/wpa_supplicant.conf
@ -516,9 +531,6 @@ in {
hardware.wirelessRegulatoryDatabase = true; hardware.wirelessRegulatoryDatabase = true;
environment.etc."wpa_supplicant.conf" =
lib.mkIf (!cfg.allowAuxiliaryImperativeNetworks) { text = generatedConfig; };
environment.systemPackages = [ pkgs.wpa_supplicant ]; environment.systemPackages = [ pkgs.wpa_supplicant ];
services.dbus.packages = optional cfg.dbusControlled pkgs.wpa_supplicant; services.dbus.packages = optional cfg.dbusControlled pkgs.wpa_supplicant;

View file

@ -1,6 +1,8 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
inherit (lib) mkIf mkOption;
inherit (lib.types) nullOr path bool listOf str;
keysPath = "/var/lib/yggdrasil/keys.json"; keysPath = "/var/lib/yggdrasil/keys.json";
cfg = config.services.yggdrasil; cfg = config.services.yggdrasil;
@ -11,14 +13,14 @@ let
in in
{ {
imports = [ imports = [
(mkRenamedOptionModule (lib.mkRenamedOptionModule
[ "services" "yggdrasil" "config" ] [ "services" "yggdrasil" "config" ]
[ "services" "yggdrasil" "settings" ]) [ "services" "yggdrasil" "settings" ])
]; ];
options = with types; { options = {
services.yggdrasil = { services.yggdrasil = {
enable = mkEnableOption "the yggdrasil system service"; enable = lib.mkEnableOption "the yggdrasil system service";
settings = mkOption { settings = mkOption {
type = format.type; type = format.type;
@ -73,7 +75,7 @@ in
}; };
group = mkOption { group = mkOption {
type = types.nullOr types.str; type = nullOr str;
default = null; default = null;
example = "wheel"; example = "wheel";
description = "Group to grant access to the Yggdrasil control socket. If `null`, only root can access the socket."; description = "Group to grant access to the Yggdrasil control socket. If `null`, only root can access the socket.";
@ -108,9 +110,9 @@ in
''; '';
}; };
package = mkPackageOption pkgs "yggdrasil" { }; package = lib.mkPackageOption pkgs "yggdrasil" { };
persistentKeys = mkEnableOption '' persistentKeys = lib.mkEnableOption ''
persistent keys. If enabled then keys will be generated once and Yggdrasil persistent keys. If enabled then keys will be generated once and Yggdrasil
will retain the same IPv6 address when the service is will retain the same IPv6 address when the service is
restarted. Keys are stored at ${keysPath} restarted. Keys are stored at ${keysPath}
@ -232,6 +234,6 @@ in
); );
meta = { meta = {
doc = ./yggdrasil.md; doc = ./yggdrasil.md;
maintainers = with lib.maintainers; [ gazally ehmry ]; maintainers = with lib.maintainers; [ gazally ehmry nagy ];
}; };
} }

View file

@ -339,7 +339,7 @@ in
services.dbus.packages = [ cups.out ] ++ optional polkitEnabled cups-pk-helper; services.dbus.packages = [ cups.out ] ++ optional polkitEnabled cups-pk-helper;
services.udev.packages = cfg.drivers; services.udev.packages = cfg.drivers;
# Allow asswordless printer admin for members of wheel group # Allow passwordless printer admin for members of wheel group
security.polkit.extraConfig = mkIf polkitEnabled '' security.polkit.extraConfig = mkIf polkitEnabled ''
polkit.addRule(function(action, subject) { polkit.addRule(function(action, subject) {
if (action.id == "org.opensuse.cupspkhelper.mechanism.all-edit" && if (action.id == "org.opensuse.cupspkhelper.mechanism.all-edit" &&

View file

@ -518,7 +518,7 @@ in
libva-utils libva-utils
procps procps
radeontop radeontop
] ++ lib.optionals (!stdenv.isAarch64) [ ] ++ lib.optionals (!stdenv.hostPlatform.isAarch64) [
# not available on aarch64-linux # not available on aarch64-linux
intel-gpu-tools intel-gpu-tools
]; ];

View file

@ -493,7 +493,7 @@ in
}; };
"~* ^/.well-known/(caldav|carddav)$" = { "~* ^/.well-known/(caldav|carddav)$" = {
extraConfig = '' extraConfig = ''
return 302 $http_x_forwarded_proto://$host/dav/; return 302 https://$host/dav/;
''; '';
}; };
"~ ^(.+\.php)(.*)$" = { "~ ^(.+\.php)(.*)$" = {
@ -505,7 +505,7 @@ in
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param X-Forwarded-Proto $http_x_forwarded_proto; fastcgi_param X-Forwarded-Proto https;
fastcgi_param X-Forwarded-Port $http_x_forwarded_port; fastcgi_param X-Forwarded-Port $http_x_forwarded_port;
''; '';
}; };

View file

@ -0,0 +1,608 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.dependency-track;
settingsFormat = pkgs.formats.javaProperties { };
frontendConfigFormat = pkgs.formats.json { };
frontendConfigFile = frontendConfigFormat.generate "config.json" {
API_BASE_URL = cfg.frontend.baseUrl;
OIDC_ISSUER = cfg.oidc.issuer;
OIDC_CLIENT_ID = cfg.oidc.clientId;
OIDC_SCOPE = cfg.oidc.scope;
OIDC_FLOW = cfg.oidc.flow;
OIDC_LOGIN_BUTTON_TEXT = cfg.oidc.loginButtonText;
};
sslEnabled =
config.services.nginx.virtualHosts.${cfg.nginx.domain}.addSSL
|| config.services.nginx.virtualHosts.${cfg.nginx.domain}.forceSSL
|| config.services.nginx.virtualHosts.${cfg.nginx.domain}.onlySSL
|| config.services.nginx.virtualHosts.${cfg.nginx.domain}.enableACME;
assertStringPath =
optionName: value:
if lib.isPath value then
throw ''
services.dependency-track.${optionName}:
${toString value}
is a Nix path, but should be a string, since Nix
paths are copied into the world-readable Nix store.
''
else
value;
filterNull = lib.filterAttrs (_: v: v != null);
renderSettings =
settings:
lib.mapAttrs' (
n: v:
lib.nameValuePair (lib.toUpper (lib.replaceStrings [ "." ] [ "_" ] n)) (
if lib.isBool v then lib.boolToString v else v
)
) (filterNull settings);
in
{
options.services.dependency-track = {
enable = lib.mkEnableOption "dependency-track";
package = lib.mkPackageOption pkgs "dependency-track" { };
logLevel = lib.mkOption {
type = lib.types.enum [
"INFO"
"WARN"
"ERROR"
"DEBUG"
"TRACE"
];
default = "INFO";
description = "Log level for dependency-track";
};
port = lib.mkOption {
type = lib.types.port;
default = 8080;
description = ''
On which port dependency-track should listen for new HTTP connections.
'';
};
javaArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "-Xmx4G" ];
description = "Java options passed to JVM";
};
database = {
type = lib.mkOption {
type = lib.types.enum [
"h2"
"postgresql"
"manual"
];
default = "postgresql";
description = ''
`h2` database is not recommended for a production setup.
`postgresql` this settings it recommended for production setups.
`manual` the module doesn't handle database settings.
'';
};
createLocally = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether a database should be automatically created on the
local host. Set this to false if you plan on provisioning a
local database yourself.
'';
};
databaseName = lib.mkOption {
type = lib.types.str;
default = "dependency-track";
description = ''
Database name to use when connecting to an external or
manually provisioned database; has no effect when a local
database is automatically provisioned.
To use this with a local database, set {option}`services.dependency-track.database.createLocally`
to `false` and create the database and user.
'';
};
username = lib.mkOption {
type = lib.types.str;
default = "dependency-track";
description = ''
Username to use when connecting to an external or manually
provisioned database; has no effect when a local database is
automatically provisioned.
To use this with a local database, set {option}`services.dependency-track.database.createLocally`
to `false` and create the database and user.
'';
};
passwordFile = lib.mkOption {
type = lib.types.path;
example = "/run/keys/db_password";
apply = assertStringPath "passwordFile";
description = ''
The path to a file containing the database password.
'';
};
};
ldap.bindPasswordFile = lib.mkOption {
type = lib.types.path;
example = "/run/keys/ldap_bind_password";
apply = assertStringPath "bindPasswordFile";
description = ''
The path to a file containing the LDAP bind password.
'';
};
frontend = {
baseUrl = lib.mkOption {
type = lib.types.str;
default = lib.optionalString cfg.nginx.enable "${
if sslEnabled then "https" else "http"
}://${cfg.nginx.domain}";
defaultText = lib.literalExpression ''
lib.optionalString config.services.dependency-track.nginx.enable "''${
if sslEnabled then "https" else "http"
}://''${config.services.dependency-track.nginx.domain}";
'';
description = ''
The base URL of the API server.
NOTE:
* This URL must be reachable by the browsers of your users.
* The frontend container itself does NOT communicate with the API server directly, it just serves static files.
* When deploying to dedicated servers, please use the external IP or domain of the API server.
'';
};
};
oidc = {
enable = lib.mkEnableOption "oidc support";
issuer = lib.mkOption {
type = lib.types.str;
default = "";
description = ''
Defines the issuer URL to be used for OpenID Connect.
See alpine.oidc.issuer property of the API server.
'';
};
clientId = lib.mkOption {
type = lib.types.str;
default = "";
description = ''
Defines the client ID for OpenID Connect.
'';
};
scope = lib.mkOption {
type = lib.types.str;
default = "openid profile email";
description = ''
Defines the scopes to request for OpenID Connect.
See also: https://openid.net/specs/openid-connect-basic-1_0.html#Scopes
'';
};
flow = lib.mkOption {
type = lib.types.enum [
"code"
"implicit"
];
default = "code";
description = ''
Specifies the OpenID Connect flow to use.
Values other than "implicit" will result in the Code+PKCE flow to be used.
Usage of the implicit flow is strongly discouraged, but may be necessary when
the IdP of choice does not support the Code+PKCE flow.
See also:
- https://oauth.net/2/grant-types/implicit/
- https://oauth.net/2/pkce/
'';
};
loginButtonText = lib.mkOption {
type = lib.types.str;
default = "Login with OpenID Connect";
description = ''
Defines the scopes to request for OpenID Connect.
See also: https://openid.net/specs/openid-connect-basic-1_0.html#Scopes
'';
};
usernameClaim = lib.mkOption {
type = lib.types.str;
default = "name";
example = "preferred_username";
description = ''
Defines the name of the claim that contains the username in the provider's userinfo endpoint.
Common claims are "name", "username", "preferred_username" or "nickname".
See also: https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
'';
};
userProvisioning = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Specifies if mapped OpenID Connect accounts are automatically created upon successful
authentication. When a user logs in with a valid access token but an account has
not been previously provisioned, an authentication failure will be returned.
This allows admins to control specifically which OpenID Connect users can access the
system and which users cannot. When this value is set to true, a local OpenID Connect
user will be created and mapped to the OpenID Connect account automatically. This
automatic provisioning only affects authentication, not authorization.
'';
};
teamSynchronization = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
This option will ensure that team memberships for OpenID Connect users are dynamic and
synchronized with membership of OpenID Connect groups or assigned roles. When a team is
mapped to an OpenID Connect group, all local OpenID Connect users will automatically be
assigned to the team if they are a member of the group the team is mapped to. If the user
is later removed from the OpenID Connect group, they will also be removed from the team. This
option provides the ability to dynamically control user permissions via the identity provider.
Note that team synchronization is only performed during user provisioning and after successful
authentication.
'';
};
teams = {
claim = lib.mkOption {
type = lib.types.str;
default = "groups";
description = ''
Defines the name of the claim that contains group memberships or role assignments in the provider's userinfo endpoint.
The claim must be an array of strings. Most public identity providers do not support group or role management.
When using a customizable / on-demand hosted identity provider, name, content, and inclusion in the userinfo endpoint
will most likely need to be configured.
'';
};
default = lib.mkOption {
type = lib.types.nullOr lib.types.commas;
default = null;
description = ''
Defines one or more team names that auto-provisioned OIDC users shall be added to.
Multiple team names may be provided as comma-separated list.
Has no effect when {option}`services.dependency-track.oidc.userProvisioning`=false,
or {option}`services.dependency-track.oidc.teamSynchronization`=true.
'';
};
};
};
nginx = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
example = false;
description = ''
Whether to set up an nginx virtual host.
'';
};
domain = lib.mkOption {
type = lib.types.str;
example = "dtrack.example.com";
description = ''
The domain name under which to set up the virtual host.
'';
};
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
options = {
"alpine.data.directory" = lib.mkOption {
type = lib.types.path;
default = "/var/lib/dependency-track";
description = ''
Defines the path to the data directory. This directory will hold logs, keys,
and any database or index files along with application-specific files or
directories.
'';
};
"alpine.database.mode" = lib.mkOption {
type = lib.types.enum [
"server"
"embedded"
"external"
];
default =
if cfg.database.type == "h2" then
"embedded"
else if cfg.database.type == "postgresql" then
"external"
else
null;
defaultText = lib.literalExpression ''
if config.services.dependency-track.database.type == "h2" then "embedded"
else if config.services.dependency-track.database.type == "postgresql" then "external"
else null
'';
description = ''
Defines the database mode of operation. Valid choices are:
'server', 'embedded', and 'external'.
In server mode, the database will listen for connections from remote hosts.
In embedded mode, the system will be more secure and slightly faster.
External mode should be used when utilizing an external database server
(i.e. mysql, postgresql, etc).
'';
};
"alpine.database.url" = lib.mkOption {
type = lib.types.str;
default =
if cfg.database.type == "h2" then
"jdbc:h2:/var/lib/dependency-track/db"
else if cfg.database.type == "postgresql" then
"jdbc:postgresql:${cfg.database.databaseName}?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/run/postgresql/.s.PGSQL.5432"
else
null;
defaultText = lib.literalExpression ''
if config.services.dependency-track.database.type == "h2" then "jdbc:h2:/var/lib/dependency-track/db"
else if config.services.dependency-track.database.type == "postgresql" then "jdbc:postgresql:''${config.services.dependency-track.database.name}?socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg&socketFactoryArg=/run/postgresql/.s.PGSQL.5432"
else null
'';
description = "Specifies the JDBC URL to use when connecting to the database.";
};
"alpine.database.driver" = lib.mkOption {
type = lib.types.enum [
"org.h2.Driver"
"org.postgresql.Driver"
"com.microsoft.sqlserver.jdbc.SQLServerDriver"
"com.mysql.cj.jdbc.Driver"
];
default =
if cfg.database.type == "h2" then
"org.h2.Driver"
else if cfg.database.type == "postgresql" then
"org.postgresql.Driver"
else
null;
defaultText = lib.literalExpression ''
if config.services.dependency-track.database.type == "h2" then "org.h2.Driver"
else if config.services.dependency-track.database.type == "postgresql" then "org.postgresql.Driver"
else null;
'';
description = "Specifies the JDBC driver class to use.";
};
"alpine.database.username" = lib.mkOption {
type = lib.types.str;
default = if cfg.database.createLocally then "dependency-track" else cfg.database.username;
defaultText = lib.literalExpression ''
if config.services.dependency-track.database.createLocally then "dependency-track"
else config.services.dependency-track.database.username
'';
description = "Specifies the username to use when authenticating to the database.";
};
"alpine.ldap.enabled" = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Defines if LDAP will be used for user authentication. If enabled,
alpine.ldap.* properties should be set accordingly.
'';
};
"alpine.oidc.enabled" = lib.mkOption {
type = lib.types.bool;
default = cfg.oidc.enable;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.enable";
description = ''
Defines if OpenID Connect will be used for user authentication.
If enabled, alpine.oidc.* properties should be set accordingly.
'';
};
"alpine.oidc.client.id" = lib.mkOption {
type = lib.types.str;
default = cfg.oidc.clientId;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.clientId";
description = ''
Defines the client ID to be used for OpenID Connect.
The client ID should be the same as the one configured for the frontend,
and will only be used to validate ID tokens.
'';
};
"alpine.oidc.issuer" = lib.mkOption {
type = lib.types.str;
default = cfg.oidc.issuer;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.issuer";
description = ''
Defines the issuer URL to be used for OpenID Connect.
This issuer MUST support provider configuration via the /.well-known/openid-configuration endpoint.
See also:
- https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
- https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
'';
};
"alpine.oidc.username.claim" = lib.mkOption {
type = lib.types.str;
default = cfg.oidc.usernameClaim;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.usernameClaim";
description = ''
Defines the name of the claim that contains the username in the provider's userinfo endpoint.
Common claims are "name", "username", "preferred_username" or "nickname".
See also: https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
'';
};
"alpine.oidc.user.provisioning" = lib.mkOption {
type = lib.types.bool;
default = cfg.oidc.userProvisioning;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.userProvisioning";
description = ''
Specifies if mapped OpenID Connect accounts are automatically created upon successful
authentication. When a user logs in with a valid access token but an account has
not been previously provisioned, an authentication failure will be returned.
This allows admins to control specifically which OpenID Connect users can access the
system and which users cannot. When this value is set to true, a local OpenID Connect
user will be created and mapped to the OpenID Connect account automatically. This
automatic provisioning only affects authentication, not authorization.
'';
};
"alpine.oidc.team.synchronization" = lib.mkOption {
type = lib.types.bool;
default = cfg.oidc.teamSynchronization;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.teamSynchronization";
description = ''
This option will ensure that team memberships for OpenID Connect users are dynamic and
synchronized with membership of OpenID Connect groups or assigned roles. When a team is
mapped to an OpenID Connect group, all local OpenID Connect users will automatically be
assigned to the team if they are a member of the group the team is mapped to. If the user
is later removed from the OpenID Connect group, they will also be removed from the team. This
option provides the ability to dynamically control user permissions via the identity provider.
Note that team synchronization is only performed during user provisioning and after successful
authentication.
'';
};
"alpine.oidc.teams.claim" = lib.mkOption {
type = lib.types.str;
default = cfg.oidc.teams.claim;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.teams.claim";
description = ''
Defines the name of the claim that contains group memberships or role assignments in the provider's userinfo endpoint.
The claim must be an array of strings. Most public identity providers do not support group or role management.
When using a customizable / on-demand hosted identity provider, name, content, and inclusion in the userinfo endpoint
will most likely need to be configured.
'';
};
"alpine.oidc.teams.default" = lib.mkOption {
type = lib.types.nullOr lib.types.commas;
default = cfg.oidc.teams.default;
defaultText = lib.literalExpression "config.services.dependency-track.oidc.teams.default";
description = ''
Defines one or more team names that auto-provisioned OIDC users shall be added to.
Multiple team names may be provided as comma-separated list.
Has no effect when {option}`services.dependency-track.oidc.userProvisioning`=false,
or {option}`services.dependency-track.oidc.teamSynchronization`=true.
'';
};
};
};
default = { };
description = "See https://docs.dependencytrack.org/getting-started/configuration/#default-configuration for possible options";
};
};
config = lib.mkIf cfg.enable {
services.nginx = lib.mkIf cfg.nginx.enable {
enable = true;
recommendedGzipSettings = lib.mkDefault true;
recommendedOptimisation = lib.mkDefault true;
recommendedProxySettings = lib.mkDefault true;
recommendedTlsSettings = lib.mkDefault true;
upstreams.dependency-track.servers."localhost:${toString cfg.port}" = { };
virtualHosts.${cfg.nginx.domain} = {
locations = {
"/".proxyPass = "http://dependency-track";
"= /static/config.json".alias = frontendConfigFile;
};
};
};
systemd.services.dependency-track-postgresql-init = lib.mkIf cfg.database.createLocally {
after = [ "postgresql.service" ];
before = [ "dependency-track.service" ];
bindsTo = [ "postgresql.service" ];
path = [ config.services.postgresql.package ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "postgres";
Group = "postgres";
LoadCredential = [ "db_password:${cfg.database.passwordFile}" ];
PrivateTmp = true;
};
script = ''
set -eou pipefail
shopt -s inherit_errexit
# Read the password from the credentials directory and
# escape any single quotes by adding additional single
# quotes after them, following the rules laid out here:
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS
db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")"
db_password="''${db_password//\'/\'\'}"
echo "CREATE ROLE \"dependency-track\" WITH LOGIN PASSWORD '$db_password' CREATEDB" > /tmp/create_role.sql
psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='dependency-track'" | grep -q 1 || psql -tA --file="/tmp/create_role.sql"
psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'dependency-track'" | grep -q 1 || psql -tAc 'CREATE DATABASE "dependency-track" OWNER "dependency-track"'
'';
};
services.postgresql.enable = lib.mkIf cfg.database.createLocally (lib.mkDefault true);
systemd.services."dependency-track" =
let
databaseServices =
if cfg.database.createLocally then
[
"dependency-track-postgresql-init.service"
"postgresql.service"
]
else
[ ];
in
{
description = "Dependency Track";
wantedBy = [ "multi-user.target" ];
requires = databaseServices;
after = databaseServices;
# provide settings via env vars to allow overriding default settings.
environment = {
HOME = "%S/dependency-track";
} // renderSettings cfg.settings;
serviceConfig = {
User = "dependency-track";
Group = "dependency-track";
DynamicUser = true;
StateDirectory = "dependency-track";
LoadCredential =
[ "db_password:${cfg.database.passwordFile}" ]
++ lib.optional cfg.settings."alpine.ldap.enabled"
"ldap_bind_password:${cfg.ldap.bindPasswordFile}";
};
script = ''
set -eou pipefail
shopt -s inherit_errexit
export ALPINE_DATABASE_PASSWORD_FILE="$CREDENTIALS_DIRECTORY/db_password"
${lib.optionalString cfg.settings."alpine.ldap.enabled" ''
export ALPINE_LDAP_BIND_PASSWORD="$(<"$CREDENTIALS_DIRECTORY/ldap_bind_password")"
''}
exec ${lib.getExe pkgs.jre_headless} ${
lib.escapeShellArgs (
cfg.javaArgs
++ [
"-DdependencyTrack.logging.level=${cfg.logLevel}"
"-jar"
"${cfg.package}/share/dependency-track/dependency-track.jar"
"-port"
"${toString cfg.port}"
]
)
}
'';
};
};
meta = {
maintainers = lib.teams.cyberus.members;
};
}

View file

@ -26,7 +26,7 @@ in
(lib.mkRemovedOptionModule [ "services" "hedgedoc" "workDir" ] '' (lib.mkRemovedOptionModule [ "services" "hedgedoc" "workDir" ] ''
This option has been removed in favor of systemd managing the state directory. This option has been removed in favor of systemd managing the state directory.
If you have set this option without specifying `services.settings.uploadsDir`, If you have set this option without specifying `services.hedgedoc.settings.uploadsPath`,
please move these files to `/var/lib/hedgedoc/uploads`, or set the option to point please move these files to `/var/lib/hedgedoc/uploads`, or set the option to point
at the correct location. at the correct location.
'') '')

View file

@ -0,0 +1,311 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.immich;
isPostgresUnixSocket = lib.hasPrefix "/" cfg.database.host;
isRedisUnixSocket = lib.hasPrefix "/" cfg.redis.host;
commonServiceConfig = {
Type = "simple";
Restart = "on-failure";
RestartSec = 3;
# Hardening
CapabilityBoundingSet = "";
NoNewPrivileges = true;
PrivateUsers = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateMounts = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
};
inherit (lib)
types
mkIf
mkOption
mkEnableOption
;
in
{
options.services.immich = {
enable = mkEnableOption "Immich";
package = lib.mkPackageOption pkgs "immich" { };
mediaLocation = mkOption {
type = types.path;
default = "/var/lib/immich";
description = "Directory used to store media files. If it is not the default, the directory has to be created manually such that the immich user is able to read and write to it.";
};
environment = mkOption {
type = types.submodule { freeformType = types.attrsOf types.str; };
default = { };
example = {
IMMICH_LOG_LEVEL = "verbose";
};
description = ''
Extra configuration environment variables. Refer to the [documentation](https://immich.app/docs/install/environment-variables) for options tagged with 'server', 'api' or 'microservices'.
'';
};
secretsFile = mkOption {
type = types.nullOr (
types.str
// {
# We don't want users to be able to pass a path literal here but
# it should look like a path.
check = it: lib.isString it && lib.types.path.check it;
}
);
default = null;
example = "/run/secrets/immich";
description = ''
Path of a file with extra environment variables to be loaded from disk. This file is not added to the nix store, so it can be used to pass secrets to immich. Refer to the [documentation](https://immich.app/docs/install/environment-variables) for options.
To set a database password set this to a file containing:
```
DB_PASSWORD=<pass>
```
'';
};
host = mkOption {
type = types.str;
default = "localhost";
description = "The host that immich will listen on.";
};
port = mkOption {
type = types.port;
default = 3001;
description = "The port that immich will listen on.";
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Whether to open the immich port in the firewall";
};
user = mkOption {
type = types.str;
default = "immich";
description = "The user immich should run as.";
};
group = mkOption {
type = types.str;
default = "immich";
description = "The group immich should run as.";
};
machine-learning = {
enable =
mkEnableOption "immich's machine-learning functionality to detect faces and search for objects"
// {
default = true;
};
environment = mkOption {
type = types.submodule { freeformType = types.attrsOf types.str; };
default = { };
example = {
MACHINE_LEARNING_MODEL_TTL = "600";
};
description = ''
Extra configuration environment variables. Refer to the [documentation](https://immich.app/docs/install/environment-variables) for options tagged with 'machine-learning'.
'';
};
};
database = {
enable =
mkEnableOption "the postgresql database for use with immich. See {option}`services.postgresql`"
// {
default = true;
};
createDB = mkEnableOption "the automatic creation of the database for immich." // {
default = true;
};
name = mkOption {
type = types.str;
default = "immich";
description = "The name of the immich database.";
};
host = mkOption {
type = types.str;
default = "/run/postgresql";
example = "127.0.0.1";
description = "Hostname or address of the postgresql server. If an absolute path is given here, it will be interpreted as a unix socket path.";
};
user = mkOption {
type = types.str;
default = "immich";
description = "The database user for immich.";
};
};
redis = {
enable = mkEnableOption "a redis cache for use with immich" // {
default = true;
};
host = mkOption {
type = types.str;
default = config.services.redis.servers.immich.unixSocket;
defaultText = lib.literalExpression "config.services.redis.servers.immich.unixSocket";
description = "The host that redis will listen on.";
};
port = mkOption {
type = types.port;
default = 0;
description = "The port that redis will listen on. Set to zero to disable TCP.";
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !isPostgresUnixSocket -> cfg.secretsFile != null;
message = "A secrets file containing at least the database password must be provided when unix sockets are not used.";
}
];
services.postgresql = mkIf cfg.database.enable {
enable = true;
ensureDatabases = mkIf cfg.database.createDB [ cfg.database.name ];
ensureUsers = mkIf cfg.database.createDB [
{
name = cfg.database.user;
ensureDBOwnership = true;
ensureClauses.login = true;
}
];
extraPlugins = ps: with ps; [ pgvecto-rs ];
settings = {
shared_preload_libraries = [ "vectors.so" ];
search_path = "\"$user\", public, vectors";
};
};
systemd.services.postgresql.serviceConfig.ExecStartPost =
let
sqlFile = pkgs.writeText "immich-pgvectors-setup.sql" ''
CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS vectors;
CREATE EXTENSION IF NOT EXISTS cube;
CREATE EXTENSION IF NOT EXISTS earthdistance;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
ALTER SCHEMA public OWNER TO ${cfg.database.user};
ALTER SCHEMA vectors OWNER TO ${cfg.database.user};
GRANT SELECT ON TABLE pg_vector_index_stat TO ${cfg.database.user};
ALTER EXTENSION vectors UPDATE;
'';
in
[
''
${lib.getExe' config.services.postgresql.package "psql"} -d "${cfg.database.name}" -f "${sqlFile}"
''
];
services.redis.servers = mkIf cfg.redis.enable {
immich = {
enable = true;
user = cfg.user;
port = cfg.redis.port;
bind = mkIf (!isRedisUnixSocket) cfg.redis.host;
};
};
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
services.immich.environment =
let
postgresEnv =
if isPostgresUnixSocket then
{ DB_URL = "socket://${cfg.database.host}?dbname=${cfg.database.name}"; }
else
{
DB_HOSTNAME = cfg.database.host;
DB_PORT = toString cfg.database.port;
DB_DATABASE_NAME = cfg.database.name;
DB_USERNAME = cfg.database.user;
};
redisEnv =
if isRedisUnixSocket then
{ REDIS_SOCKET = cfg.redis.host; }
else
{
REDIS_PORT = toString cfg.redis.port;
REDIS_HOSTNAME = cfg.redis.host;
};
in
postgresEnv
// redisEnv
// {
HOST = cfg.host;
IMMICH_PORT = toString cfg.port;
IMMICH_MEDIA_LOCATION = cfg.mediaLocation;
IMMICH_MACHINE_LEARNING_URL = "http://localhost:3003";
};
services.immich.machine-learning.environment = {
MACHINE_LEARNING_WORKERS = "1";
MACHINE_LEARNING_WORKER_TIMEOUT = "120";
MACHINE_LEARNING_CACHE_FOLDER = "/var/cache/immich";
IMMICH_HOST = "localhost";
IMMICH_PORT = "3003";
};
systemd.services.immich-server = {
description = "Immich backend server (Self-hosted photo and video backup solution)";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
inherit (cfg) environment;
serviceConfig = commonServiceConfig // {
ExecStart = lib.getExe cfg.package;
EnvironmentFile = mkIf (cfg.secretsFile != null) cfg.secretsFile;
StateDirectory = "immich";
RuntimeDirectory = "immich";
User = cfg.user;
Group = cfg.group;
};
};
systemd.services.immich-machine-learning = mkIf cfg.machine-learning.enable {
description = "immich machine learning";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
inherit (cfg.machine-learning) environment;
serviceConfig = commonServiceConfig // {
ExecStart = lib.getExe cfg.package.machine-learning;
CacheDirectory = "immich";
User = cfg.user;
Group = cfg.group;
};
};
users.users = mkIf (cfg.user == "immich") {
immich = {
name = "immich";
group = cfg.group;
isSystemUser = true;
};
};
users.groups = mkIf (cfg.group == "immich") { immich = { }; };
meta.maintainers = with lib.maintainers; [ jvanbruegge ];
};
}

View file

@ -294,6 +294,15 @@ in
'') '')
]; ];
services.logrotate.settings.pretalx = {
files = "${cfg.settings.filesystem.logs}/*.log";
su = "${cfg.user} ${cfg.group}";
frequency = "weekly";
rotate = "12";
copytruncate = true;
compress = true;
};
services = { services = {
nginx = lib.mkIf cfg.nginx.enable { nginx = lib.mkIf cfg.nginx.enable {
enable = true; enable = true;

View file

@ -249,7 +249,7 @@ in
}; };
host = mkOption { host = mkOption {
type = with types; nullOr path; type = with types; nullOr str;
default = if cfg.settings.database.backend == "postgresql" then "/run/postgresql" else null; default = if cfg.settings.database.backend == "postgresql" then "/run/postgresql" else null;
defaultText = literalExpression '' defaultText = literalExpression ''
if config.services.pretix.settings..database.backend == "postgresql" then "/run/postgresql" if config.services.pretix.settings..database.backend == "postgresql" then "/run/postgresql"
@ -403,6 +403,15 @@ in
'') '')
]; ];
services.logrotate.settings.pretix = {
files = "${cfg.settings.pretix.logdir}/*.log";
su = "${cfg.user} ${cfg.group}";
frequency = "weekly";
rotate = "12";
copytruncate = true;
compress = true;
};
services = { services = {
nginx = mkIf cfg.nginx.enable { nginx = mkIf cfg.nginx.enable {
enable = true; enable = true;

View file

@ -59,6 +59,7 @@ in
pngquant pngquant
tesseract tesseract
python3Packages.weasyprint python3Packages.weasyprint
ghostscript_headless
] ]
++ lib.optional (cfg.environment.INSTALL_BOOK_AND_ADVANCED_HTML_OPS or "false" == "true") calibre; ++ lib.optional (cfg.environment.INSTALL_BOOK_AND_ADVANCED_HTML_OPS or "false" == "true") calibre;

View file

@ -75,13 +75,16 @@ let
mkPhpValue = v: let mkPhpValue = v: let
isHasAttr = s: isAttrs v && hasAttr s v; isHasAttr = s: isAttrs v && hasAttr s v;
# "you're escaped" -> "'you\'re escaped'"
# https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.single
toPhpString = s: "'${escape [ "'" "\\" ] s}'";
in in
if isString v then escapeShellArg v if isString v then toPhpString v
# NOTE: If any value contains a , (comma) this will not get escaped # NOTE: If any value contains a , (comma) this will not get escaped
else if isList v && any lib.strings.isCoercibleToString v then escapeShellArg (concatMapStringsSep "," toString v) else if isList v && any lib.strings.isCoercibleToString v then toPhpString (concatMapStringsSep "," toString v)
else if isInt v then toString v else if isInt v then toString v
else if isBool v then boolToString v else if isBool v then boolToString v
else if isHasAttr "_file" then "trim(file_get_contents(${lib.escapeShellArg v._file}))" else if isHasAttr "_file" then "trim(file_get_contents(${toPhpString v._file}))"
else if isHasAttr "_raw" then v._raw else if isHasAttr "_raw" then v._raw
else abort "The Wordpress config value ${lib.generators.toPretty {} v} can not be encoded." else abort "The Wordpress config value ${lib.generators.toPretty {} v} can not be encoded."
; ;

View file

@ -1,11 +1,11 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
inherit (lib) mkIf mkOption optional;
inherit (lib.types) path bool listOf str port;
cfg = config.services.darkhttpd; cfg = config.services.darkhttpd;
args = concatStringsSep " " ([ args = lib.concatStringsSep " " ([
cfg.rootDir cfg.rootDir
"--port ${toString cfg.port}" "--port ${toString cfg.port}"
"--addr ${cfg.address}" "--addr ${cfg.address}"
@ -14,12 +14,12 @@ let
++ optional config.networking.enableIPv6 "--ipv6"); ++ optional config.networking.enableIPv6 "--ipv6");
in { in {
options.services.darkhttpd = with types; { options.services.darkhttpd = {
enable = mkEnableOption "DarkHTTPd web server"; enable = lib.mkEnableOption "DarkHTTPd web server";
port = mkOption { port = mkOption {
default = 80; default = 80;
type = types.port; type = port;
description = '' description = ''
Port to listen on. Port to listen on.
Pass 0 to let the system choose any free port for you. Pass 0 to let the system choose any free port for you.

View file

@ -7,8 +7,6 @@ let
inherit (lib) inherit (lib)
optionals optionals
types types
concatLists
mapAttrsToList
mkOption mkOption
; ;
@ -17,16 +15,17 @@ let
++ optionals (cfg.socket != null) [ "--interface" cfg.socket ] ++ optionals (cfg.socket != null) [ "--interface" cfg.socket ]
++ optionals (cfg.interface != null) [ "--interface" cfg.interface ] ++ optionals (cfg.interface != null) [ "--interface" cfg.interface ]
++ [ "--signal" (toString cfg.signal) ] ++ [ "--signal" (toString cfg.signal) ]
++ (concatLists (mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions)) ++ (lib.concatLists (lib.mapAttrsToList (_k: _v: [ "--client-option" "${_k}=${_v}" ]) cfg.clientOptions))
++ [ "--terminal-type" cfg.terminalType ] ++ [ "--terminal-type" cfg.terminalType ]
++ optionals cfg.checkOrigin [ "--check-origin" ] ++ optionals cfg.checkOrigin [ "--check-origin" ]
++ optionals cfg.writeable [ "--writable" ] # the typo is correct ++ optionals cfg.writeable [ "--writable" ] # the typo is correct
++ [ "--max-clients" (toString cfg.maxClients) ] ++ [ "--max-clients" (toString cfg.maxClients) ]
++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ] ++ optionals (cfg.indexFile != null) [ "--index" cfg.indexFile ]
++ optionals cfg.enableIPv6 [ "--ipv6" ] ++ optionals cfg.enableIPv6 [ "--ipv6" ]
++ optionals cfg.enableSSL [ "--ssl-cert" cfg.certFile ++ optionals cfg.enableSSL [ "--ssl"
"--ssl-key" cfg.keyFile "--ssl-cert" cfg.certFile
"--ssl-ca" cfg.caFile ] "--ssl-key" cfg.keyFile ]
++ optionals ( cfg.enableSSL && cfg.caFile != null ) [ "--ssl-ca" cfg.caFile ]
++ [ "--debug" (toString cfg.logLevel) ]; ++ [ "--debug" (toString cfg.logLevel) ];
in in
@ -197,8 +196,8 @@ in
assertions = assertions =
[ { assertion = cfg.enableSSL [ { assertion = cfg.enableSSL
-> cfg.certFile != null && cfg.keyFile != null && cfg.caFile != null; -> cfg.certFile != null && cfg.keyFile != null;
message = "SSL is enabled for ttyd, but no certFile, keyFile or caFile has been specified."; } message = "SSL is enabled for ttyd, but no certFile or keyFile has been specified."; }
{ assertion = cfg.writeable != null; { assertion = cfg.writeable != null;
message = "services.ttyd.writeable must be set"; } message = "services.ttyd.writeable must be set"; }
{ assertion = ! (cfg.interface != null && cfg.socket != null); { assertion = ! (cfg.interface != null && cfg.socket != null);

View file

@ -68,9 +68,19 @@ let
else showWarnings config.warnings baseSystem; else showWarnings config.warnings baseSystem;
# Replace runtime dependencies # Replace runtime dependencies
system = foldr ({ oldDependency, newDependency }: drv: system = let inherit (config.system.replaceDependencies) replacements cutoffPackages; in
pkgs.replaceDependency { inherit oldDependency newDependency drv; } if replacements == [] then
) baseSystemAssertWarn config.system.replaceRuntimeDependencies; # Avoid IFD if possible, by sidestepping replaceDependencies if no replacements are specified.
baseSystemAssertWarn
else
(pkgs.replaceDependencies.override {
replaceDirectDependencies = pkgs.replaceDirectDependencies.override {
nix = config.nix.package;
};
}) {
drv = baseSystemAssertWarn;
inherit replacements cutoffPackages;
};
systemWithBuildDeps = system.overrideAttrs (o: { systemWithBuildDeps = system.overrideAttrs (o: {
systemBuildClosure = pkgs.closureInfo { rootPaths = [ system.drvPath ]; }; systemBuildClosure = pkgs.closureInfo { rootPaths = [ system.drvPath ]; };
@ -87,6 +97,7 @@ in
(mkRemovedOptionModule [ "nesting" "clone" ] "Use `specialisation.«name» = { inheritParentConfig = true; configuration = { ... }; }` instead.") (mkRemovedOptionModule [ "nesting" "clone" ] "Use `specialisation.«name» = { inheritParentConfig = true; configuration = { ... }; }` instead.")
(mkRemovedOptionModule [ "nesting" "children" ] "Use `specialisation.«name».configuration = { ... }` instead.") (mkRemovedOptionModule [ "nesting" "children" ] "Use `specialisation.«name».configuration = { ... }` instead.")
(mkRenamedOptionModule [ "system" "forbiddenDependenciesRegex" ] [ "system" "forbiddenDependenciesRegexes" ]) (mkRenamedOptionModule [ "system" "forbiddenDependenciesRegex" ] [ "system" "forbiddenDependenciesRegexes" ])
(mkRenamedOptionModule [ "system" "replaceRuntimeDependencies" ] [ "system" "replaceDependencies" "replacements" ])
]; ];
options = { options = {
@ -205,31 +216,47 @@ in
''; '';
}; };
system.replaceRuntimeDependencies = mkOption { system.replaceDependencies = {
default = []; replacements = mkOption {
example = lib.literalExpression "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { }; }) ]"; default = [];
type = types.listOf (types.submodule ( example = lib.literalExpression "[ ({ oldDependency = pkgs.openssl; newDependency = pkgs.callPackage /path/to/openssl { }; }) ]";
{ ... }: { type = types.listOf (types.submodule (
options.original = mkOption { { ... }: {
type = types.package; imports = [
description = "The original package to override."; (mkRenamedOptionModule [ "original" ] [ "oldDependency" ])
}; (mkRenamedOptionModule [ "replacement" ] [ "newDependency" ])
];
options.replacement = mkOption { options.oldDependency = mkOption {
type = types.package; type = types.package;
description = "The replacement package."; description = "The original package to override.";
}; };
})
); options.newDependency = mkOption {
apply = map ({ original, replacement, ... }: { type = types.package;
oldDependency = original; description = "The replacement package.";
newDependency = replacement; };
}); })
description = '' );
List of packages to override without doing a full rebuild. apply = map ({ oldDependency, newDependency, ... }: {
The original derivation and replacement derivation must have the same inherit oldDependency newDependency;
name length, and ideally should have close-to-identical directory layout. });
''; description = ''
List of packages to override without doing a full rebuild.
The original derivation and replacement derivation must have the same
name length, and ideally should have close-to-identical directory layout.
'';
};
cutoffPackages = mkOption {
default = [ config.system.build.initialRamdisk ];
defaultText = literalExpression "[ config.system.build.initialRamdisk ]";
type = types.listOf types.package;
description = ''
Packages to which no replacements should be applied.
The initrd is matched by default, because its structure renders the replacement process ineffective and prone to breakage.
'';
};
}; };
system.name = mkOption { system.name = mkOption {

View file

@ -1088,6 +1088,8 @@ in
storePaths = [ storePaths = [
"${config.boot.initrd.systemd.package}/bin/systemd-cryptsetup" "${config.boot.initrd.systemd.package}/bin/systemd-cryptsetup"
"${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-cryptsetup-generator" "${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-cryptsetup-generator"
] ++ lib.optionals config.boot.initrd.systemd.tpm2.enable [
"${config.boot.initrd.systemd.package}/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
]; ];
}; };

View file

@ -327,7 +327,7 @@ let
setHostId = optionalString (config.networking.hostId != null) '' setHostId = optionalString (config.networking.hostId != null) ''
hi="${config.networking.hostId}" hi="${config.networking.hostId}"
${if pkgs.stdenv.isBigEndian then '' ${if pkgs.stdenv.hostPlatform.isBigEndian then ''
echo -ne "\x''${hi:0:2}\x''${hi:2:2}\x''${hi:4:2}\x''${hi:6:2}" > /etc/hostid echo -ne "\x''${hi:0:2}\x''${hi:2:2}\x''${hi:4:2}\x''${hi:6:2}" > /etc/hostid
'' else '' '' else ''
echo -ne "\x''${hi:6:2}\x''${hi:4:2}\x''${hi:2:2}\x''${hi:0:2}" > /etc/hostid echo -ne "\x''${hi:6:2}\x''${hi:4:2}\x''${hi:2:2}\x''${hi:0:2}" > /etc/hostid

View file

@ -37,8 +37,6 @@ let
"cryptsetup.target" "cryptsetup.target"
"cryptsetup-pre.target" "cryptsetup-pre.target"
"remote-cryptsetup.target" "remote-cryptsetup.target"
] ++ optionals cfg.package.withTpm2Tss [
"tpm2.target"
] ++ [ ] ++ [
"sigpwr.target" "sigpwr.target"
"timers.target" "timers.target"
@ -679,7 +677,7 @@ in
# Increase numeric PID range (set directly instead of copying a one-line file from systemd) # Increase numeric PID range (set directly instead of copying a one-line file from systemd)
# https://github.com/systemd/systemd/pull/12226 # https://github.com/systemd/systemd/pull/12226
boot.kernel.sysctl."kernel.pid_max" = mkIf pkgs.stdenv.is64bit (lib.mkDefault 4194304); boot.kernel.sysctl."kernel.pid_max" = mkIf pkgs.stdenv.hostPlatform.is64bit (lib.mkDefault 4194304);
services.logrotate.settings = { services.logrotate.settings = {
"/var/log/btmp" = mapAttrs (_: mkDefault) { "/var/log/btmp" = mapAttrs (_: mkDefault) {

View file

@ -0,0 +1,61 @@
{ config, lib, ... }:
let
cfg = config.boot.initrd.systemd.dmVerity;
in
{
options = {
boot.initrd.systemd.dmVerity = {
enable = lib.mkEnableOption "dm-verity" // {
description = ''
Mount verity-protected block devices in the initrd.
Enabling this option allows to use `systemd-veritysetup` and
`systemd-veritysetup-generator` in the initrd.
'';
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = config.boot.initrd.systemd.enable;
message = ''
'boot.initrd.systemd.dmVerity.enable' requires 'boot.initrd.systemd.enable' to be enabled.
'';
}
];
boot.initrd = {
availableKernelModules = [
"dm_mod"
"dm_verity"
];
# dm-verity needs additional udev rules from LVM to work.
services.lvm.enable = true;
# The additional targets and store paths allow users to integrate verity-protected devices
# through the systemd tooling.
systemd = {
additionalUpstreamUnits = [
"veritysetup-pre.target"
"veritysetup.target"
"remote-veritysetup.target"
];
storePaths = [
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-veritysetup"
"${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-veritysetup-generator"
];
};
};
};
meta.maintainers = with lib.maintainers; [
msanft
nikstur
willibutz
];
}

View file

@ -38,6 +38,7 @@ let
"kmod-static-nodes.service" "kmod-static-nodes.service"
"local-fs-pre.target" "local-fs-pre.target"
"local-fs.target" "local-fs.target"
"modprobe@.service"
"multi-user.target" "multi-user.target"
"paths.target" "paths.target"
"poweroff.target" "poweroff.target"
@ -68,7 +69,6 @@ let
"systemd-reboot.service" "systemd-reboot.service"
"systemd-sysctl.service" "systemd-sysctl.service"
"timers.target" "timers.target"
"tpm2.target"
"umount.target" "umount.target"
"systemd-bsod.service" "systemd-bsod.service"
] ++ cfg.additionalUpstreamUnits; ] ++ cfg.additionalUpstreamUnits;
@ -349,15 +349,6 @@ in {
visible = "shallow"; visible = "shallow";
description = "Definition of slice configurations."; description = "Definition of slice configurations.";
}; };
enableTpm2 = mkOption {
default = cfg.package.withTpm2Tss;
defaultText = "boot.initrd.systemd.package.withTpm2Tss";
type = types.bool;
description = ''
Whether to enable TPM2 support in the initrd.
'';
};
}; };
config = mkIf (config.boot.initrd.enable && cfg.enable) { config = mkIf (config.boot.initrd.enable && cfg.enable) {
@ -394,9 +385,7 @@ in {
# systemd needs this for some features # systemd needs this for some features
"autofs" "autofs"
# systemd-cryptenroll # systemd-cryptenroll
] ++ lib.optional cfg.enableTpm2 "tpm-tis" ] ++ lib.optional cfg.package.withEfi "efivarfs";
++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb"
++ lib.optional cfg.package.withEfi "efivarfs";
boot.kernelParams = [ boot.kernelParams = [
"root=${config.boot.initrd.systemd.root}" "root=${config.boot.initrd.systemd.root}"
@ -495,10 +484,6 @@ in {
# so NSS can look up usernames # so NSS can look up usernames
"${pkgs.glibc}/lib/libnss_files.so.2" "${pkgs.glibc}/lib/libnss_files.so.2"
] ++ optionals (cfg.package.withCryptsetup && cfg.enableTpm2) [
# tpm2 support
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
pkgs.tpm2-tss
] ++ optionals cfg.package.withCryptsetup [ ] ++ optionals cfg.package.withCryptsetup [
# fido2 support # fido2 support
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so" "${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"

View file

@ -68,14 +68,10 @@ in
assertion = config.system.activationScripts.users == ""; assertion = config.system.activationScripts.users == "";
message = "system.activationScripts.users has to be empty to use systemd-sysusers"; message = "system.activationScripts.users has to be empty to use systemd-sysusers";
} }
{
assertion = config.users.mutableUsers -> config.system.etc.overlay.enable;
message = "config.users.mutableUsers requires config.system.etc.overlay.enable.";
}
] ++ (lib.mapAttrsToList ] ++ (lib.mapAttrsToList
(_username: opts: { (username: opts: {
assertion = !opts.isNormalUser; assertion = !opts.isNormalUser;
message = "systemd-sysusers doesn't create normal users. You can currently only use it to create system users."; message = "${username} is a normal user. systemd-sysusers doesn't create normal users, only system users.";
}) })
userCfg.users) userCfg.users)
++ lib.mapAttrsToList ++ lib.mapAttrsToList

View file

@ -0,0 +1,80 @@
{
lib,
config,
pkgs,
...
}:
{
meta.maintainers = [ lib.maintainers.elvishjerricco ];
imports = [
(lib.mkRenamedOptionModule
[
"boot"
"initrd"
"systemd"
"enableTpm2"
]
[
"boot"
"initrd"
"systemd"
"tpm2"
"enable"
]
)
];
options = {
systemd.tpm2.enable = lib.mkEnableOption "systemd TPM2 support" // {
default = config.systemd.package.withTpm2Tss;
defaultText = "systemd.package.withTpm2Tss";
};
boot.initrd.systemd.tpm2.enable = lib.mkEnableOption "systemd initrd TPM2 support" // {
default = config.boot.initrd.systemd.package.withTpm2Tss;
defaultText = "boot.initrd.systemd.package.withTpm2Tss";
};
};
# TODO: pcrphase, pcrextend, pcrfs, pcrmachine
config = lib.mkMerge [
# Stage 2
(
let
cfg = config.systemd;
in
lib.mkIf cfg.tpm2.enable {
systemd.additionalUpstreamSystemUnits = [
"tpm2.target"
"systemd-tpm2-setup-early.service"
"systemd-tpm2-setup.service"
];
}
)
# Stage 1
(
let
cfg = config.boot.initrd.systemd;
in
lib.mkIf cfg.tpm2.enable {
boot.initrd.systemd.additionalUpstreamUnits = [
"tpm2.target"
"systemd-tpm2-setup-early.service"
];
boot.initrd.availableKernelModules =
[ "tpm-tis" ]
++ lib.optional (
!(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)
) "tpm-crb";
boot.initrd.systemd.storePaths = [
pkgs.tpm2-tss
"${cfg.package}/lib/systemd/systemd-tpm2-setup"
"${cfg.package}/lib/systemd/system-generators/systemd-tpm2-generator"
];
}
)
];
}

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