Project import generated by Copybara.

GitOrigin-RevId: 1536926ef5621b09bba54035ae2bb6d806d72ac8
This commit is contained in:
Default email 2024-02-29 21:09:43 +01:00
parent 4ef13f4918
commit c7cb07f092
5191 changed files with 202247 additions and 58982 deletions

View file

@ -108,3 +108,7 @@ charset = unset
[lib/tests/*.plist]
indent_style = tab
insert_final_newline = unset
[pkgs/kde/generated/**]
insert_final_newline = unset
end_of_line = unset

View file

@ -96,3 +96,9 @@ fb0e5be84331188a69b3edd31679ca6576edb75a
# nixos/*: add trivial defaultText for options with simple defaults
25124556397ba17bfd70297000270de1e6523b0a
# systemd: rewrite comments
92dfeb7b3dab820ae307c56c216d175c69ee93cd
# systemd: break too long lines of Nix code
67643f8ec84bef1482204709073e417c9f07eb87

View file

@ -52,6 +52,7 @@
/pkgs/pkgs-lib @infinisil
## Format generators/serializers
/pkgs/pkgs-lib/formats/libconfig @ckiee @h7x4
/pkgs/pkgs-lib/formats/hocon @h7x4
# pkgs/by-name
/pkgs/test/nixpkgs-check-by-name @infinisil
@ -184,11 +185,18 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# Licenses
/lib/licenses.nix @alyssais
# Qt / KDE
/pkgs/applications/kde @ttuegel
/pkgs/desktops/plasma-5 @ttuegel
/pkgs/development/libraries/kde-frameworks @ttuegel
/pkgs/development/libraries/qt-5 @ttuegel
# Qt
/pkgs/development/libraries/qt-5 @NixOS/qt-kde
/pkgs/development/libraries/qt-6 @NixOS/qt-kde
# KDE / Plasma 5
/pkgs/applications/kde @NixOS/qt-kde
/pkgs/desktops/plasma-5 @NixOS/qt-kde
/pkgs/development/libraries/kde-frameworks @NixOS/qt-kde
# KDE / Plasma 6
/pkgs/kde @NixOS/qt-kde
/maintainers/scripts/kde @NixOS/qt-kde
# PostgreSQL and related stuff
/pkgs/servers/sql/postgresql @thoughtpolice @marsam
@ -196,6 +204,10 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/modules/services/databases/postgresql.nix @thoughtpolice
/nixos/tests/postgresql.nix @thoughtpolice
# Linux kernel
/pkgs/os-specific/linux/kernel @raitobezarius
/pkgs/top-level/linux-kernels.nix @raitobezarius
# Hardened profile & related modules
/nixos/modules/profiles/hardened.nix @joachifm
/nixos/modules/security/hidepid.nix @joachifm
@ -266,13 +278,13 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/applications/editors/vscode/extensions @jonringer
# PHP interpreter, packages, extensions, tests and documentation
/doc/languages-frameworks/php.section.md @aanderse @drupol @etu @globin @ma27 @talyz
/nixos/tests/php @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php/build-pecl.nix @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php @drupol @etu
/pkgs/development/interpreters/php @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/development/php-packages @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
/doc/languages-frameworks/php.section.md @aanderse @drupol @globin @ma27 @talyz
/nixos/tests/php @aanderse @drupol @globin @ma27 @talyz
/pkgs/build-support/php/build-pecl.nix @aanderse @drupol @globin @ma27 @talyz
/pkgs/build-support/php @drupol
/pkgs/development/interpreters/php @jtojnar @aanderse @drupol @globin @ma27 @talyz
/pkgs/development/php-packages @aanderse @drupol @globin @ma27 @talyz
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @drupol @globin @ma27 @talyz
# Docker tools
/pkgs/build-support/docker @roberth

View file

@ -129,19 +129,17 @@ When a PR is created, it will be pre-populated with some checkboxes detailed bel
#### Tested using sandboxing
When sandbox builds are enabled, Nix will setup an isolated environment for each build process. It is used to remove further hidden dependencies set by the build environment to improve reproducibility. This includes access to the network during the build outside of `fetch*` functions and files outside the Nix store. Depending on the operating system access to other resources are blocked as well (ex. inter process communication is isolated on Linux); see [sandbox](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-sandbox) in the Nix manual for details.
When sandbox builds are enabled, Nix will set up an isolated environment for each build process.
It is used to remove further hidden dependencies set by the build environment to improve reproducibility.
This includes access to the network during the build outside of `fetch*` functions and files outside the Nix store.
Depending on the operating system, access to other resources is blocked as well (e.g., inter-process communication is isolated on Linux); see [sandbox](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-sandbox) in the Nix manual for details.
Sandboxing is not enabled by default in Nix due to a small performance hit on each build. In pull requests for [nixpkgs](https://github.com/NixOS/nixpkgs/) people are asked to test builds with sandboxing enabled (see `Tested using sandboxing` in the pull request template) because in [Hydra](https://nixos.org/hydra/) sandboxing is also used.
In pull requests for [nixpkgs](https://github.com/NixOS/nixpkgs/) people are asked to test builds with sandboxing enabled (see `Tested using sandboxing` in the pull request template) because in [Hydra](https://nixos.org/hydra/) sandboxing is also used.
Depending if you use NixOS or other platforms you can use one of the following methods to enable sandboxing **before** building the package:
If you are on Linux, sandboxing is enabled by default.
On other platforms, sandboxing is disabled by default due to a small performance hit on each build.
- **Globally enable sandboxing on NixOS**: add the following to `configuration.nix`
```nix
nix.settings.sandbox = true;
```
- **Globally enable sandboxing on non-NixOS platforms**: add the following to: `/etc/nix/nix.conf`
Please enable sandboxing **before** building the package by adding the following to: `/etc/nix/nix.conf`:
```ini
sandbox = true
@ -441,14 +439,14 @@ gitGraph
Here's an overview of the different branches:
| branch | `master` | `staging` | `staging-next` |
| branch | `master` | `staging-next` | `staging` |
| --- | --- | --- | --- |
| Used for development | ✔️ | ✔️ | ❌ |
| Built by Hydra | ✔️ | ❌ | ✔️ |
| [Mass rebuilds][mass-rebuild] | ❌ | ✔️ | ⚠️ Only to fix Hydra builds |
| Critical security fixes | ✔️ for non-mass-rebuilds | ❌ | ✔️ for mass-rebuilds |
| Automatically merged into | `staging-next` | - | `staging` |
| Manually merged into | - | `staging-next` | `master` |
| Used for development | ✔️ | ❌ | ✔️ |
| Built by Hydra | ✔️ | ✔️ | ❌ |
| [Mass rebuilds][mass-rebuild] | ❌ | ⚠️ Only to fix Hydra builds | ✔️ |
| Critical security fixes | ✔️ for non-mass-rebuilds | ✔️ for mass-rebuilds | ❌ |
| Automatically merged into | `staging-next` | `staging` | - |
| Manually merged into | - | `master` | `staging-next` |
The staging workflow is used for all main branches, `master` and `release-YY.MM`, with corresponding names:
- `master`/`release-YY.MM`

View file

@ -1,4 +1,4 @@
Copyright (c) 2003-2023 Eelco Dolstra and the Nixpkgs/NixOS contributors
Copyright (c) 2003-2024 Eelco Dolstra and the Nixpkgs/NixOS contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View file

@ -80,6 +80,10 @@ stdenv.mkDerivation {
The main difference between `fetchurl` and `fetchzip` is in how they store the contents. `fetchurl` will store the unaltered contents of the URL within the Nix store. `fetchzip` on the other hand, will decompress the archive for you, making files and directories directly accessible in the future. `fetchzip` can only be used with archives. Despite the name, `fetchzip` is not limited to .zip files and can also be used with any tarball.
Additional parameters to `fetchurl`:
- `downloadToTemp`: Defaults to `false`. If `true`, saves the source to `$downloadedFile`, to be used in conjunction with `postFetch`
- `postFetch`: Shell code executed after the file has been fetched successfully. Use it for postprocessing, to check or transform the file.
## `fetchpatch` {#fetchpatch}
`fetchpatch` works very similarly to `fetchurl` with the same arguments expected. It expects patch files as a source and performs normalization on them before computing the checksum. For example, it will remove comments or other unstable parts that are sometimes added by version control systems and can change over time.

View file

@ -6,7 +6,7 @@ Docker itself is not used to perform any of the operations done by these functio
## buildImage {#ssec-pkgs-dockerTools-buildImage}
This function builds a Docker-compatible repository tarball containing a single image.
As such, the result is suitable for being loaded in Docker with `docker load` (see [](#ex-dockerTools-buildImage) for how to do this).
As such, the result is suitable for being loaded in Docker with `docker image load` (see [](#ex-dockerTools-buildImage) for how to do this).
This function will create a single layer for all files (and dependencies) that are specified in its argument.
Only new dependencies that are not already in the existing layers will be copied.
@ -43,7 +43,7 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has
`fromImage` (Path or Null; _optional_)
: The repository tarball of an image to be used as the base for the generated image.
It must be a valid Docker image, such as one exported by `docker save`, or another image built with the `dockerTools` utility functions.
It must be a valid Docker image, such as one exported by `docker image save`, or another image built with the `dockerTools` utility functions.
This can be seen as an equivalent of `FROM fromImage` in a `Dockerfile`.
A value of `null` can be seen as an equivalent of `FROM scratch`.
@ -123,7 +123,7 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has
_Default value:_ `""`.
`config` (Attribute Set; _optional_)
`config` (Attribute Set or Null; _optional_)
: Used to specify the configuration of the containers that will be started off the generated image.
Must be an attribute set, with each attribute as listed in the [Docker Image Specification v1.3.0](https://github.com/moby/moby/blob/46f7ab808b9504d735d600e259ca0723f76fb164/image/spec/spec.md#image-json-field-descriptions).
@ -178,6 +178,13 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has
_Default value:_ 0.
`compressor` (String; _optional_)
: Selects the algorithm used to compress the image.
_Default value:_ `"gz"`.\
_Possible values:_ `"none"`, `"gz"`, `"zstd"`.
`contents` **DEPRECATED**
: This attribute is deprecated, and users are encouraged to use `copyToRoot` instead.
@ -247,7 +254,7 @@ Cooking the image...
Finished.
/nix/store/p4dsg62inh9d2ksy3c7bv58xa851dasr-docker-image-redis.tar.gz
$ docker load -i /nix/store/p4dsg62inh9d2ksy3c7bv58xa851dasr-docker-image-redis.tar.gz
$ docker image load -i /nix/store/p4dsg62inh9d2ksy3c7bv58xa851dasr-docker-image-redis.tar.gz
(some output removed for clarity)
Loaded image: redis:latest
```
@ -345,8 +352,8 @@ dockerTools.buildImage {
After importing the generated repository tarball with Docker, its CLI will display a reasonable date and sort the images as expected:
```ShellSession
$ docker images
```shell
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest de2bf4786de6 About a minute ago 25.2MB
```
@ -364,7 +371,7 @@ Despite the similar name, [`buildImage`](#ssec-pkgs-dockerTools-buildImage) work
Even though some of the arguments may seem related, they cannot be interchanged.
:::
You can use this function to load an image in Docker with `docker load`.
You can load the result of this function in Docker with `docker image load`.
See [](#ex-dockerTools-buildLayeredImage-hello) to see how to do that.
### Examples {#ssec-pkgs-dockerTools-buildLayeredImage-examples}
@ -404,7 +411,7 @@ Adding manifests...
Done.
/nix/store/hxcz7snvw7f8rzhbh6mv8jq39d992905-hello.tar.gz
$ docker load -i /nix/store/hxcz7snvw7f8rzhbh6mv8jq39d992905-hello.tar.gz
$ docker image load -i /nix/store/hxcz7snvw7f8rzhbh6mv8jq39d992905-hello.tar.gz
(some output removed for clarity)
Loaded image: hello:latest
```
@ -415,7 +422,7 @@ Loaded image: hello:latest
`streamLayeredImage` builds a **script** which, when run, will stream to stdout a Docker-compatible repository tarball containing a single image, using multiple layers to improve sharing between images.
This means that `streamLayeredImage` does not output an image into the Nix store, but only a script that builds the image, saving on IO and disk/cache space, particularly with large images.
You can use this function to load an image in Docker with `docker load`.
You can load the result of this function in Docker with `docker image load`.
See [](#ex-dockerTools-streamLayeredImage-hello) to see how to do that.
For this function, you specify a [store path](https://nixos.org/manual/nix/stable/store/store-path) or a list of store paths to be added to the image, and the functions will automatically include any dependencies of those paths in the image.
@ -440,7 +447,7 @@ This allows the function to produce reproducible images.
: The name of the generated image.
`tag` (String; _optional_)
`tag` (String or Null; _optional_)
: Tag of the generated image.
If `null`, the hash of the nix derivation will be used as the tag.
@ -450,7 +457,7 @@ This allows the function to produce reproducible images.
`fromImage`(Path or Null; _optional_)
: The repository tarball of an image to be used as the base for the generated image.
It must be a valid Docker image, such as one exported by `docker save`, or another image built with the `dockerTools` utility functions.
It must be a valid Docker image, such as one exported by `docker image save`, or another image built with the `dockerTools` utility functions.
This can be seen as an equivalent of `FROM fromImage` in a `Dockerfile`.
A value of `null` can be seen as an equivalent of `FROM scratch`.
@ -470,7 +477,7 @@ This allows the function to produce reproducible images.
_Default value:_ `[]`
`config` (Attribute Set; _optional_) []{#dockerTools-buildLayeredImage-arg-config}
`config` (Attribute Set or Null; _optional_) []{#dockerTools-buildLayeredImage-arg-config}
: Used to specify the configuration of the containers that will be started off the generated image.
Must be an attribute set, with each attribute as listed in the [Docker Image Specification v1.3.0](https://github.com/moby/moby/blob/46f7ab808b9504d735d600e259ca0723f76fb164/image/spec/spec.md#image-json-field-descriptions).
@ -500,6 +507,16 @@ This allows the function to produce reproducible images.
_Default value:_ `"1970-01-01T00:00:01Z"`.
`uid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-uid}
`gid` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-gid}
`uname` (String; _optional_) []{#dockerTools-buildLayeredImage-arg-uname}
`gname` (String; _optional_) []{#dockerTools-buildLayeredImage-arg-gname}
: Credentials for Nix store ownership.
Can be overridden to e.g. `1000` / `1000` / `"user"` / `"user"` to enable building a container where Nix can be used as an unprivileged user in single-user mode.
_Default value:_ `0` / `0` / `"root"` / `"root"`
`maxLayers` (Number; _optional_) []{#dockerTools-buildLayeredImage-arg-maxLayers}
: The maximum number of layers that will be used by the generated image.
@ -594,7 +611,7 @@ dockerTools.streamLayeredImage {
```
The result of building this package is a script.
Running this script and piping it into `docker load` gives you the same image that was built in [](#ex-dockerTools-buildLayeredImage-hello).
Running this script and piping it into `docker image load` gives you the same image that was built in [](#ex-dockerTools-buildLayeredImage-hello).
Note that in this case, the image is never added to the Nix store, but instead streamed directly into Docker.
```shell
@ -602,7 +619,7 @@ $ nix-build
(output removed for clarity)
/nix/store/wsz2xl8ckxnlb769irvq6jv1280dfvxd-stream-hello
$ /nix/store/wsz2xl8ckxnlb769irvq6jv1280dfvxd-stream-hello | docker load
$ /nix/store/wsz2xl8ckxnlb769irvq6jv1280dfvxd-stream-hello | docker image load
No 'fromImage' provided
Creating layer 1 from paths: ['/nix/store/i93s7xxblavsacpy82zdbn4kplsyq48l-libunistring-1.1']
Creating layer 2 from paths: ['/nix/store/ji01n9vinnj22nbrb86nx8a1ssgpilx8-libidn2-2.3.4']
@ -718,7 +735,7 @@ dockerTools.streamLayeredImage {
[]{#ssec-pkgs-dockerTools-fetchFromRegistry}
## pullImage {#ssec-pkgs-dockerTools-pullImage}
This function is similar to the `docker pull` command, which means it can be used to pull a Docker image from a registry that implements the [Docker Registry HTTP API V2](https://distribution.github.io/distribution/spec/api/).
This function is similar to the `docker image pull` command, which means it can be used to pull a Docker image from a registry that implements the [Docker Registry HTTP API V2](https://distribution.github.io/distribution/spec/api/).
By default, the `docker.io` registry is used.
The image will be downloaded as an uncompressed Docker-compatible repository tarball, which is suitable for use with other `dockerTools` functions such as [`buildImage`](#ssec-pkgs-dockerTools-buildImage), [`buildLayeredImage`](#ssec-pkgs-dockerTools-buildLayeredImage), and [`streamLayeredImage`](#ssec-pkgs-dockerTools-streamLayeredImage).
@ -1088,238 +1105,482 @@ If you don't specify a `name` attribute, you'll encounter an evaluation error an
## Environment Helpers {#ssec-pkgs-dockerTools-helpers}
Some packages expect certain files to be available globally.
When building an image from scratch (i.e. without `fromImage`), these files are missing.
`pkgs.dockerTools` provides some helpers to set up an environment with the necessary files.
You can include them in `copyToRoot` like this:
When building Docker images with Nix, you might also want to add certain files that are expected to be available globally by the software you're packaging.
Simple examples are the `env` utility in `/usr/bin/env`, or trusted root TLS/SSL certificates.
Such files will most likely not be included if you're building a Docker image from scratch with Nix, and they might also not be included if you're starting from a Docker image that doesn't include them.
The helpers in this section are packages that provide some of these commonly-needed global files.
```nix
buildImage {
name = "environment-example";
copyToRoot = with pkgs.dockerTools; [
usrBinEnv
binSh
caCertificates
fakeNss
];
}
```
Most of these helpers are packages, which means you have to add them to the list of contents to be included in the image (this changes depending on the function you're using to build the image).
[](#ex-dockerTools-helpers-buildImage) and [](#ex-dockerTools-helpers-buildLayeredImage) show how to include these packages on `dockerTools` functions that build an image.
For more details on how that works, see the documentation for the function you're using.
### usrBinEnv {#sssec-pkgs-dockerTools-helpers-usrBinEnv}
This provides the `env` utility at `/usr/bin/env`.
This is currently implemented by linking to the `env` binary from the `coreutils` package, but is considered an implementation detail that could change in the future.
### binSh {#sssec-pkgs-dockerTools-helpers-binSh}
This provides `bashInteractive` at `/bin/sh`.
This provides a `/bin/sh` link to the `bash` binary from the `bashInteractive` package.
Because of this, it supports cases such as running a command interactively in a container (for example by running `docker container run -it <image_name>`).
### caCertificates {#sssec-pkgs-dockerTools-helpers-caCertificates}
This sets up `/etc/ssl/certs/ca-certificates.crt`.
This adds trusted root TLS/SSL certificates from the `cacert` package in multiple locations in an attempt to be compatible with binaries built for multiple Linux distributions.
The locations currently used are:
- `/etc/ssl/certs/ca-bundle.crt`
- `/etc/ssl/certs/ca-certificates.crt`
- `/etc/pki/tls/certs/ca-bundle.crt`
[]{#ssec-pkgs-dockerTools-fakeNss}
### fakeNss {#sssec-pkgs-dockerTools-helpers-fakeNss}
Provides `/etc/passwd` and `/etc/group` that contain root and nobody.
Useful when packaging binaries that insist on using nss to look up
username/groups (like nginx).
This is a re-export of the `fakeNss` package from Nixpkgs.
See [](#sec-fakeNss).
### shadowSetup {#ssec-pkgs-dockerTools-shadowSetup}
This constant string is a helper for setting up the base files for managing users and groups, only if such files don't exist already. It is suitable for being used in a [`buildImage` `runAsRoot`](#ex-dockerTools-buildImage-runAsRoot) script for cases like in the example below:
This is a string containing a script that sets up files needed for [`shadow`](https://github.com/shadow-maint/shadow) to work (using the `shadow` package from Nixpkgs), and alters `PATH` to make all its utilities available in the same script.
It is intended to be used with other dockerTools functions in attributes that expect scripts.
After the script in `shadowSetup` runs, you'll then be able to add more commands that make use of the utilities in `shadow`, such as adding any extra users and/or groups.
See [](#ex-dockerTools-shadowSetup-buildImage) and [](#ex-dockerTools-shadowSetup-buildLayeredImage) to better understand how to use it.
`shadowSetup` achieves a result similar to [`fakeNss`](#sssec-pkgs-dockerTools-helpers-fakeNss), but only sets up a `root` user with different values for the home directory and the shell to use, in addition to setting up files for [PAM](https://en.wikipedia.org/wiki/Linux_PAM) and a {manpage}`login.defs(5)` file.
:::{.caution}
Using both `fakeNss` and `shadowSetup` at the same time will either cause your build to break or produce unexpected results.
Use either `fakeNss` or `shadowSetup` depending on your use case, but avoid using both.
:::
:::{.note}
When used with [`buildLayeredImage`](#ssec-pkgs-dockerTools-buildLayeredImage) or [`streamLayeredImage`](#ssec-pkgs-dockerTools-streamLayeredImage), you will have to set the `enableFakechroot` attribute to `true`, or else the script in `shadowSetup` won't run properly.
See [](#ex-dockerTools-shadowSetup-buildLayeredImage).
:::
### Examples {#ssec-pkgs-dockerTools-helpers-examples}
:::{.example #ex-dockerTools-helpers-buildImage}
# Using `dockerTools`'s environment helpers with `buildImage`
This example adds the [`binSh`](#sssec-pkgs-dockerTools-helpers-binSh) helper to a basic Docker image built with [`dockerTools.buildImage`](#ssec-pkgs-dockerTools-buildImage).
This helper makes it possible to enter a shell inside the container.
This is the `buildImage` equivalent of [](#ex-dockerTools-helpers-buildLayeredImage).
```nix
buildImage {
name = "shadow-basic";
{ dockerTools, hello }:
dockerTools.buildImage {
name = "env-helpers";
tag = "latest";
runAsRoot = ''
#!${pkgs.runtimeShell}
${pkgs.dockerTools.shadowSetup}
groupadd -r redis
useradd -r -g redis redis
mkdir /data
chown redis:redis /data
'';
}
copyToRoot = [
hello
dockerTools.binSh
];
```
Creating base files like `/etc/passwd` or `/etc/login.defs` is necessary for shadow-utils to manipulate users and groups.
After building the image and loading it in Docker, we can create a container based on it and enter a shell inside the container.
This is made possible by `binSh`.
When using `buildLayeredImage`, you can put this in `fakeRootCommands` if you `enableFakechroot`:
```nix
buildLayeredImage {
name = "shadow-layered";
fakeRootCommands = ''
${pkgs.dockerTools.shadowSetup}
'';
enableFakechroot = true;
}
```shell
$ nix-build
(some output removed for clarity)
/nix/store/2p0i3i04cgjlk71hsn7ll4kxaxxiv4qg-docker-image-env-helpers.tar.gz
$ docker image load -i /nix/store/2p0i3i04cgjlk71hsn7ll4kxaxxiv4qg-docker-image-env-helpers.tar.gz
(output removed for clarity)
$ docker container run --rm -it env-helpers:latest /bin/sh
sh-5.2# help
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
(rest of output removed for clarity)
```
:::
## fakeNss {#ssec-pkgs-dockerTools-fakeNss}
:::{.example #ex-dockerTools-helpers-buildLayeredImage}
# Using `dockerTools`'s environment helpers with `buildLayeredImage`
If your primary goal is providing a basic skeleton for user lookups to work,
and/or a lesser privileged user, adding `pkgs.fakeNss` to
the container image root might be the better choice than a custom script
running `useradd` and friends.
It provides a `/etc/passwd` and `/etc/group`, containing `root` and `nobody`
users and groups.
It also provides a `/etc/nsswitch.conf`, configuring NSS host resolution to
first check `/etc/hosts`, before checking DNS, as the default in the absence of
a config file (`dns [!UNAVAIL=return] files`) is quite unexpected.
You can pair it with `binSh`, which provides `bin/sh` as a symlink
to `bashInteractive` (as `/bin/sh` is configured as a shell).
This example adds the [`binSh`](#sssec-pkgs-dockerTools-helpers-binSh) helper to a basic Docker image built with [`dockerTools.buildLayeredImage`](#ssec-pkgs-dockerTools-buildLayeredImage).
This helper makes it possible to enter a shell inside the container.
This is the `buildLayeredImage` equivalent of [](#ex-dockerTools-helpers-buildImage).
```nix
buildImage {
name = "shadow-basic";
{ dockerTools, hello }:
dockerTools.buildLayeredImage {
name = "env-helpers";
tag = "latest";
copyToRoot = pkgs.buildEnv {
name = "image-root";
paths = [ binSh pkgs.fakeNss ];
pathsToLink = [ "/bin" "/etc" "/var" ];
contents = [
hello
dockerTools.binSh
];
config = {
Cmd = [ "/bin/hello" ];
};
}
```
## buildNixShellImage {#ssec-pkgs-dockerTools-buildNixShellImage}
After building the image and loading it in Docker, we can create a container based on it and enter a shell inside the container.
This is made possible by `binSh`.
Create a Docker image that sets up an environment similar to that of running `nix-shell` on a derivation.
When run in Docker, this environment somewhat resembles the Nix sandbox typically used by `nix-build`, with a major difference being that access to the internet is allowed.
It additionally also behaves like an interactive `nix-shell`, running things like `shellHook` and setting an interactive prompt.
If the derivation is fully buildable (i.e. `nix-build` can be used on it), running `buildDerivation` inside such a Docker image will build the derivation, with all its outputs being available in the correct `/nix/store` paths, pointed to by the respective environment variables like `$out`, etc.
::: {.warning}
The behavior doesn't match `nix-shell` or `nix-build` exactly and this function is known not to work correctly for e.g. fixed-output derivations, content-addressed derivations, impure derivations and other special types of derivations.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/rpf47f4z5b9qr4db4ach9yr4b85hjhxq-env-helpers.tar.gz
$ docker image load -i /nix/store/rpf47f4z5b9qr4db4ach9yr4b85hjhxq-env-helpers.tar.gz
(output removed for clarity)
$ docker container run --rm -it env-helpers:latest /bin/sh
sh-5.2# help
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
(rest of output removed for clarity)
```
:::
### Arguments {#ssec-pkgs-dockerTools-buildNixShellImage-arguments}
:::{.example #ex-dockerTools-shadowSetup-buildImage}
# Using `dockerTools.shadowSetup` with `dockerTools.buildImage`
`drv`
: The derivation on which to base the Docker image.
Adding packages to the Docker image is possible by e.g. extending the list of `nativeBuildInputs` of this derivation like
This is an example that shows how to use `shadowSetup` with `dockerTools.buildImage`.
Note that the extra script in `runAsRoot` uses `groupadd` and `useradd`, which are binaries provided by the `shadow` package.
These binaries are added to the `PATH` by the `shadowSetup` script, but only for the duration of `runAsRoot`.
```nix
buildNixShellImage {
drv = someDrv.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs or [] ++ [
somethingExtra
];
});
# ...
{ dockerTools, hello }:
dockerTools.buildImage {
name = "shadow-basic";
tag = "latest";
copyToRoot = [ hello ];
runAsRoot = ''
${dockerTools.shadowSetup}
groupadd -r hello
useradd -r -g hello hello
mkdir /data
chown hello:hello /data
'';
config = {
Cmd = [ "/bin/hello" ];
WorkingDir = "/data";
};
}
```
:::
Similarly, you can extend the image initialization script by extending `shellHook`
:::{.example #ex-dockerTools-shadowSetup-buildLayeredImage}
# Using `dockerTools.shadowSetup` with `dockerTools.buildLayeredImage`
`name` _optional_
It accomplishes the same thing as [](#ex-dockerTools-shadowSetup-buildImage), but using `buildLayeredImage` instead.
: The name of the resulting image.
*Default:* `drv.name + "-env"`
`tag` _optional_
: Tag of the generated image.
*Default:* the resulting image derivation output path's hash
`uid`/`gid` _optional_
: The user/group ID to run the container as. This is like a `nixbld` build user.
*Default:* 1000/1000
`homeDirectory` _optional_
: The home directory of the user the container is running as
*Default:* `/build`
`shell` _optional_
: The path to the `bash` binary to use as the shell. This shell is started when running the image.
*Default:* `pkgs.bashInteractive + "/bin/bash"`
`command` _optional_
: Run this command in the environment of the derivation, in an interactive shell. See the `--command` option in the [`nix-shell` documentation](https://nixos.org/manual/nix/stable/command-ref/nix-shell.html?highlight=nix-shell#options).
*Default:* (none)
`run` _optional_
: Same as `command`, but runs the command in a non-interactive shell instead. See the `--run` option in the [`nix-shell` documentation](https://nixos.org/manual/nix/stable/command-ref/nix-shell.html?highlight=nix-shell#options).
*Default:* (none)
### Example {#ssec-pkgs-dockerTools-buildNixShellImage-example}
The following shows how to build the `pkgs.hello` package inside a Docker container built with `buildNixShellImage`.
Note that the extra script in `fakeRootCommands` uses `groupadd` and `useradd`, which are binaries provided by the `shadow` package.
These binaries are added to the `PATH` by the `shadowSetup` script, but only for the duration of `fakeRootCommands`.
```nix
with import <nixpkgs> {};
{ dockerTools, hello }:
dockerTools.buildLayeredImage {
name = "shadow-basic";
tag = "latest";
contents = [ hello ];
fakeRootCommands = ''
${dockerTools.shadowSetup}
groupadd -r hello
useradd -r -g hello hello
mkdir /data
chown hello:hello /data
'';
enableFakechroot = true;
config = {
Cmd = [ "/bin/hello" ];
WorkingDir = "/data";
};
}
```
:::
[]{#ssec-pkgs-dockerTools-buildNixShellImage-arguments}
## buildNixShellImage {#ssec-pkgs-dockerTools-buildNixShellImage}
`buildNixShellImage` uses [`streamNixShellImage`](#ssec-pkgs-dockerTools-streamNixShellImage) underneath to build a compressed Docker-compatible repository tarball of an image that sets up an environment similar to that of running `nix-shell` on a derivation.
Basically, `buildNixShellImage` runs the script created by `streamNixShellImage` to save the compressed image in the Nix store.
`buildNixShellImage` supports the same options as `streamNixShellImage`, see [`streamNixShellImage`](#ssec-pkgs-dockerTools-streamNixShellImage) for details.
[]{#ssec-pkgs-dockerTools-buildNixShellImage-example}
### Examples {#ssec-pkgs-dockerTools-buildNixShellImage-examples}
:::{.example #ex-dockerTools-buildNixShellImage-hello}
# Building a Docker image with `buildNixShellImage` with the build environment for the `hello` package
This example shows how to build the `hello` package inside a Docker container built with `buildNixShellImage`.
The Docker image generated will have a name like `hello-<version>-env` and tag `latest`.
This example is the `buildNixShellImage` equivalent of [](#ex-dockerTools-streamNixShellImage-hello).
```nix
{ dockerTools, hello }:
dockerTools.buildNixShellImage {
drv = hello;
tag = "latest";
}
```
Build the derivation:
The result of building this package is a `.tar.gz` file that can be loaded into Docker:
```console
nix-build hello.nix
```shell
$ nix-build
(some output removed for clarity)
/nix/store/pkj1sgzaz31wl0pbvbg3yp5b3kxndqms-hello-2.12.1-env.tar.gz
$ docker image load -i /nix/store/pkj1sgzaz31wl0pbvbg3yp5b3kxndqms-hello-2.12.1-env.tar.gz
(some output removed for clarity)
Loaded image: hello-2.12.1-env:latest
```
these 8 derivations will be built:
/nix/store/xmw3a5ln29rdalavcxk1w3m4zb2n7kk6-nix-shell-rc.drv
...
Creating layer 56 from paths: ['/nix/store/crpnj8ssz0va2q0p5ibv9i6k6n52gcya-stdenv-linux']
Creating layer 57 with customisation...
Adding manifests...
Done.
/nix/store/cpyn1lc897ghx0rhr2xy49jvyn52bazv-hello-2.12-env.tar.gz
After starting an interactive container, the derivation can be built by running `buildDerivation`, and the output can be executed as expected:
Load the image:
```console
docker load -i result
```
0d9f4c4cd109: Loading layer [==================================================>] 2.56MB/2.56MB
...
ab1d897c0697: Loading layer [==================================================>] 10.24kB/10.24kB
Loaded image: hello-2.12-env:pgj9h98nal555415faa43vsydg161bdz
Run the container:
```console
docker run -it hello-2.12-env:pgj9h98nal555415faa43vsydg161bdz
```
[nix-shell:/build]$
In the running container, run the build:
```console
buildDerivation
```
unpacking sources
unpacking source archive /nix/store/8nqv6kshb3vs5q5bs2k600xpj5bkavkc-hello-2.12.tar.gz
...
patching script interpreter paths in /nix/store/z5wwy5nagzy15gag42vv61c2agdpz2f2-hello-2.12
checking for references to /build/ in /nix/store/z5wwy5nagzy15gag42vv61c2agdpz2f2-hello-2.12...
Check the build result:
```console
$out/bin/hello
```
```shell
$ docker container run -it hello-2.12.1-env:latest
[nix-shell:~]$ buildDerivation
Running phase: unpackPhase
unpacking source archive /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz
source root is hello-2.12.1
(some output removed for clarity)
Running phase: fixupPhase
shrinking RPATHs of ELF executables and libraries in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1
shrinking /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/bin/hello
checking for references to /build/ in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1...
gzipping man pages under /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/share/man/
patching script interpreter paths in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1
stripping (with command strip and flags -S -p) in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/bin
[nix-shell:~]$ $out/bin/hello
Hello, world!
```
:::
## streamNixShellImage {#ssec-pkgs-dockerTools-streamNixShellImage}
`streamNixShellImage` builds a **script** which, when run, will stream to stdout a Docker-compatible repository tarball of an image that sets up an environment similar to that of running `nix-shell` on a derivation.
This means that `streamNixShellImage` does not output an image into the Nix store, but only a script that builds the image, saving on IO and disk/cache space, particularly with large images.
See [](#ex-dockerTools-streamNixShellImage-hello) to understand how to load in Docker the image generated by this script.
The environment set up by `streamNixShellImage` somewhat resembles the Nix sandbox typically used by `nix-build`, with a major difference being that access to the internet is allowed.
It also behaves like an interactive `nix-shell`, running things like `shellHook` (see [](#ex-dockerTools-streamNixShellImage-addingShellHook)) and setting an interactive prompt.
If the derivation is buildable (i.e. `nix-build` can be used on it), running `buildDerivation` in the container will build the derivation, with all its outputs being available in the correct `/nix/store` paths, pointed to by the respective environment variables (e.g. `$out`).
::: {.caution}
The environment in the image doesn't match `nix-shell` or `nix-build` exactly, and this function is known not to work correctly for fixed-output derivations, content-addressed derivations, impure derivations and other special types of derivations.
:::
### Inputs {#ssec-pkgs-dockerTools-streamNixShellImage-inputs}
`streamNixShellImage` expects one argument with the following attributes:
`drv` (Attribute Set)
: The derivation for which the environment in the image will be set up.
Adding packages to the Docker image is possible by extending the list of `nativeBuildInputs` of this derivation.
See [](#ex-dockerTools-streamNixShellImage-extendingBuildInputs) for how to do that.
Similarly, you can extend the image initialization script by extending `shellHook`.
[](#ex-dockerTools-streamNixShellImage-addingShellHook) shows how to do that.
`name` (String; _optional_)
: The name of the generated image.
_Default value:_ the value of `drv.name + "-env"`.
`tag` (String or Null; _optional_)
: Tag of the generated image.
If `null`, the hash of the nix derivation that builds the Docker image will be used as the tag.
_Default value:_ `null`.
`uid` (Number; _optional_)
: The user ID to run the container as.
This can be seen as a `nixbld` build user.
_Default value:_ 1000.
`gid` (Number; _optional_)
: The group ID to run the container as.
This can be seen as a `nixbld` build group.
_Default value:_ 1000.
`homeDirectory` (String; _optional_)
: The home directory of the user the container is running as.
_Default value:_ `/build`.
`shell` (String; _optional_)
: The path to the `bash` binary to use as the shell.
This shell is started when running the image.
This can be seen as an equivalent of the `NIX_BUILD_SHELL` [environment variable](https://nixos.org/manual/nix/stable/command-ref/nix-shell.html#environment-variables) for {manpage}`nix-shell(1)`.
_Default value:_ the `bash` binary from the `bashInteractive` package.
`command` (String or Null; _optional_)
: If specified, this command will be run in the environment of the derivation in an interactive shell.
A call to `exit` will be added after the command if it is specified, so the shell will exit after it's finished running.
This can be seen as an equivalent of the `--command` option in {manpage}`nix-shell(1)`.
_Default value:_ `null`.
`run` (String or Null; _optional_)
: Similar to the `command` attribute, but runs the command in a non-interactive shell instead.
A call to `exit` will be added after the command if it is specified, so the shell will exit after it's finished running.
This can be seen as an equivalent of the `--run` option in {manpage}`nix-shell(1)`.
_Default value:_ `null`.
### Examples {#ssec-pkgs-dockerTools-streamNixShellImage-examples}
:::{.example #ex-dockerTools-streamNixShellImage-hello}
# Building a Docker image with `streamNixShellImage` with the build environment for the `hello` package
This example shows how to build the `hello` package inside a Docker container built with `streamNixShellImage`.
The Docker image generated will have a name like `hello-<version>-env` and tag `latest`.
This example is the `streamNixShellImage` equivalent of [](#ex-dockerTools-buildNixShellImage-hello).
```nix
{ dockerTools, hello }:
dockerTools.streamNixShellImage {
drv = hello;
tag = "latest";
}
```
The result of building this package is a script.
Running this script and piping it into `docker image load` gives you the same image that was built in [](#ex-dockerTools-buildNixShellImage-hello).
```shell
$ nix-build
(some output removed for clarity)
/nix/store/8vhznpz2frqazxnd8pgdvf38jscdypax-stream-hello-2.12.1-env
$ /nix/store/8vhznpz2frqazxnd8pgdvf38jscdypax-stream-hello-2.12.1-env | docker image load
(some output removed for clarity)
Loaded image: hello-2.12.1-env:latest
```
After starting an interactive container, the derivation can be built by running `buildDerivation`, and the output can be executed as expected:
```shell
$ docker container run -it hello-2.12.1-env:latest
[nix-shell:~]$ buildDerivation
Running phase: unpackPhase
unpacking source archive /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz
source root is hello-2.12.1
(some output removed for clarity)
Running phase: fixupPhase
shrinking RPATHs of ELF executables and libraries in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1
shrinking /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/bin/hello
checking for references to /build/ in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1...
gzipping man pages under /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/share/man/
patching script interpreter paths in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1
stripping (with command strip and flags -S -p) in /nix/store/f2vs29jibd7lwxyj35r9h87h6brgdysz-hello-2.12.1/bin
[nix-shell:~]$ $out/bin/hello
Hello, world!
```
:::
:::{.example #ex-dockerTools-streamNixShellImage-extendingBuildInputs}
# Adding extra packages to a Docker image built with `streamNixShellImage`
This example shows how to add extra packages to an image built with `streamNixShellImage`.
In this case, we'll add the `cowsay` package.
The Docker image generated will have a name like `hello-<version>-env` and tag `latest`.
This example uses [](#ex-dockerTools-streamNixShellImage-hello) as a starting point.
```nix
{ dockerTools, cowsay, hello }:
dockerTools.streamNixShellImage {
tag = "latest";
drv = hello.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs or [] ++ [
cowsay
];
});
}
```
The result of building this package is a script which can be run and piped into `docker image load` to load the generated image.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/h5abh0vljgzg381lna922gqknx6yc0v7-stream-hello-2.12.1-env
$ /nix/store/h5abh0vljgzg381lna922gqknx6yc0v7-stream-hello-2.12.1-env | docker image load
(some output removed for clarity)
Loaded image: hello-2.12.1-env:latest
```
After starting an interactive container, we can verify the extra package is available by running `cowsay`:
```shell
$ docker container run -it hello-2.12.1-env:latest
[nix-shell:~]$ cowsay "Hello, world!"
_______________
< Hello, world! >
---------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
```
:::
:::{.example #ex-dockerTools-streamNixShellImage-addingShellHook}
# Adding a `shellHook` to a Docker image built with `streamNixShellImage`
This example shows how to add a `shellHook` command to an image built with `streamNixShellImage`.
In this case, we'll simply output the string `Hello, world!`.
The Docker image generated will have a name like `hello-<version>-env` and tag `latest`.
This example uses [](#ex-dockerTools-streamNixShellImage-hello) as a starting point.
```nix
{ dockerTools, hello }:
dockerTools.streamNixShellImage {
tag = "latest";
drv = hello.overrideAttrs (old: {
shellHook = ''
${old.shellHook or ""}
echo "Hello, world!"
'';
});
}
```
The result of building this package is a script which can be run and piped into `docker image load` to load the generated image.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/iz4dhdvgzazl5vrgyz719iwjzjy6xlx1-stream-hello-2.12.1-env
$ /nix/store/iz4dhdvgzazl5vrgyz719iwjzjy6xlx1-stream-hello-2.12.1-env | docker image load
(some output removed for clarity)
Loaded image: hello-2.12.1-env:latest
```
After starting an interactive container, we can see the result of the `shellHook`:
```shell
$ docker container run -it hello-2.12.1-env:latest
Hello, world!
[nix-shell:~]$
```
:::

View file

@ -1,37 +1,104 @@
# pkgs.ociTools {#sec-pkgs-ociTools}
`pkgs.ociTools` is a set of functions for creating containers according to the [OCI container specification v1.0.0](https://github.com/opencontainers/runtime-spec). Beyond that, it makes no assumptions about the container runner you choose to use to run the created container.
`pkgs.ociTools` is a set of functions for creating runtime container bundles according to the [OCI runtime specification v1.0.0](https://github.com/opencontainers/runtime-spec/blob/v1.0.0/spec.md).
It makes no assumptions about the container runner you choose to use to run the created container.
The set of functions in `pkgs.ociTools` currently does not handle the [OCI image specification](https://github.com/opencontainers/image-spec).
At a high-level an OCI implementation would download an OCI Image then unpack that image into an OCI Runtime filesystem bundle.
At this point the OCI Runtime Bundle would be run by an OCI Runtime.
`pkgs.ociTools` provides utilities to create OCI Runtime bundles.
## buildContainer {#ssec-pkgs-ociTools-buildContainer}
This function creates a simple OCI container that runs a single command inside of it. An OCI container consists of a `config.json` and a rootfs directory. The nix store of the container will contain all referenced dependencies of the given command.
This function creates an OCI runtime container (consisting of a `config.json` and a root filesystem directory) that runs a single command inside of it.
The nix store of the container will contain all referenced dependencies of the given command.
The parameters of `buildContainer` with an example value are described below:
This function has an assumption that the container will run on POSIX platforms, and sets configurations (such as the user running the process or certain mounts) according to this assumption.
Because of this, a container built with `buildContainer` will not work on Windows or other non-POSIX platforms without modifications to the container configuration.
These modifications aren't supported by `buildContainer`.
For `linux` platforms, `buildContainer` also configures the following namespaces (see {manpage}`unshare(1)`) to isolate the OCI container from the global namespace:
PID, network, mount, IPC, and UTS.
Note that no user namespace is created, which means that you won't be able to run the container unless you are the `root` user.
### Inputs {#ssec-pkgs-ociTools-buildContainer-inputs}
`buildContainer` expects an argument with the following attributes:
`args` (List of String)
: Specifies a set of arguments to run inside the container.
Any packages referenced by `args` will be made available inside the container.
`mounts` (Attribute Set; _optional_)
: Would specify additional mounts that the runtime must make available to the container.
:::{.warning}
As explained in [issue #290879](https://github.com/NixOS/nixpkgs/issues/290879), this attribute is currently ignored.
:::
:::{.note}
`buildContainer` includes a minimal set of necessary filesystems to be mounted into the container, and this set can't be changed with the `mounts` attribute.
:::
_Default value:_ `{}`.
`readonly` (Boolean; _optional_)
: If `true`, sets the container's root filesystem as read-only.
_Default value:_ `false`.
`os` **DEPRECATED**
: Specifies the operating system on which the container filesystem is based on.
If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/main/config.md#properties).
According to the linked specification, all possible values for `$GOOS` in [the Go docs](https://go.dev/doc/install/source#environment) should be valid, but will commonly be one of `darwin` or `linux`.
_Default value:_ `"linux"`.
`arch` **DEPRECATED**
: Used to specify the architecture for which the binaries in the container filesystem have been compiled.
If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/main/config.md#properties).
According to the linked specification, all possible values for `$GOARCH` in [the Go docs](https://go.dev/doc/install/source#environment) should be valid, but will commonly be one of `386`, `amd64`, `arm`, or `arm64`.
_Default value:_ `x86_64`.
### Examples {#ssec-pkgs-ociTools-buildContainer-examples}
::: {.example #ex-ociTools-buildContainer-bash}
# Creating an OCI runtime container that runs `bash`
This example uses `ociTools.buildContainer` to create a simple container that runs `bash`.
```nix
buildContainer {
{ ociTools, lib, bash }:
ociTools.buildContainer {
args = [
(with pkgs;
writeScript "run.sh" ''
#!${bash}/bin/bash
exec ${bash}/bin/bash
'').outPath
(lib.getExe bash)
];
mounts = {
"/data" = {
type = "none";
source = "/var/lib/mydata";
options = [ "bind" ];
};
};
readonly = false;
}
```
- `args` specifies a set of arguments to run inside the container. This is the only required argument for `buildContainer`. All referenced packages inside the derivation will be made available inside the container.
As an example of how to run the container generated by this package, we'll use `runc` to start the container.
Any other tool that supports OCI containers could be used instead.
- `mounts` specifies additional mount points chosen by the user. By default only a minimal set of necessary filesystems are mounted into the container (e.g procfs, cgroupfs)
```shell
$ nix-build
(some output removed for clarity)
/nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join
- `readonly` makes the container's rootfs read-only if it is set to true. The default value is false `false`.
$ cd /nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join
$ nix-shell -p runc
[nix-shell:/nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join]$ sudo runc run ocitools-example
help
GNU bash, version 5.2.26(1)-release (x86_64-pc-linux-gnu)
(some output removed for clarity)
```
:::

View file

@ -1,81 +1,174 @@
# pkgs.portableService {#sec-pkgs-portableService}
`pkgs.portableService` is a function to create _portable service images_,
as read-only, immutable, `squashfs` archives.
systemd supports a concept of [Portable Services](https://systemd.io/PORTABLE_SERVICES/).
Portable Services are a delivery method for system services that uses two specific features of container management:
* Applications are bundled. I.e. multiple services, their binaries and
all their dependencies are packaged in an image, and are run directly from it.
* Stricter default security policies, i.e. sandboxing of applications.
This allows using Nix to build images which can be run on many recent Linux distributions.
The primary tool for interacting with Portable Services is `portablectl`,
and they are managed by the `systemd-portabled` system service.
`pkgs.portableService` is a function to create [Portable Services](https://systemd.io/PORTABLE_SERVICES/) in a read-only, immutable, `squashfs` raw disk image.
This lets you use Nix to build images which can be run on many recent Linux distributions.
::: {.note}
Portable services are supported starting with systemd 239 (released on 2018-06-22).
:::
A very simple example of using `portableService` is described below:
The generated image will contain the file system structure as required by the Portable Services specification, along with the packages given to `portableService` and all of their dependencies.
When generated, the image will exist in the Nix store with the `.raw` file extension, as required by the specification.
See [](#ex-portableService-hello) to understand how to use the output of `portableService`.
## Inputs {#ssec-pkgs-portableService-inputs}
`portableService` expects one argument with the following attributes:
`pname` (String)
: The name of the portable service.
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
`version` (String)
: The version of the portable service.
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
`units` (List of Attribute Set)
: A list of derivations for systemd unit files.
Each derivation must produce a single file, and must have a name that starts with the value of `pname` and ends with the suffix of the unit type (e.g. ".service", ".socket", ".timer", and so on).
See [](#ex-portableService-hello) to better understand this naming constraint.
`description` (String or Null; _optional_)
: If specified, the value is added as `PORTABLE_PRETTY_NAME` to the `/etc/os-release` file in the generated image.
This could be used to provide more information to anyone inspecting the image.
_Default value:_ `null`.
`homepage` (String or Null; _optional_)
: If specified, the value is added as `HOME_URL` to the `/etc/os-release` file in the generated image.
This could be used to provide more information to anyone inspecting the image.
_Default value:_ `null`.
`symlinks` (List of Attribute Set; _optional_)
: A list of attribute sets in the format `{object, symlink}`.
For each item in the list, `portableService` will create a symlink in the path specified by `symlink` (relative to the root of the image) that points to `object`.
All packages that `object` depends on and their dependencies are automatically copied into the image.
This can be used to create symlinks for applications that assume some files to exist globally (`/etc/ssl` or `/bin/bash`, for example).
See [](#ex-portableService-symlinks) to understand how to do that.
_Default value:_ `[]`.
`contents` (List of Attribute Set; _optional_)
: A list of additional derivations to be included as-is in the image.
These derivations will be included directly in a `/nix/store` directory inside the image.
_Default value:_ `[]`.
`squashfsTools` (Attribute Set; _optional_)
: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `pkgs.squashfsTools`.
`squash-compression` (String; _optional_)
: Passed as the compression option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `"xz -Xdict-size 100%"`.
`squash-block-size` (String; _optional_)
: Passed as the block size option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `"1M"`.
## Examples {#ssec-pkgs-portableService-examples}
[]{#ex-pkgs-portableService}
:::{.example #ex-portableService-hello}
# Building a Portable Service image
The following example builds a Portable Service image with the `hello` package, along with a service unit that runs it.
```nix
pkgs.portableService {
pname = "demo";
version = "1.0";
units = [ demo-service demo-socket ];
{ lib, writeText, portableService, hello }:
let
hello-service = writeText "hello.service" ''
[Unit]
Description=Hello world service
[Service]
Type=oneshot
ExecStart=${lib.getExe hello}
'';
in
portableService {
pname = "hello";
inherit (hello) version;
units = [ hello-service ];
}
```
The above example will build an squashfs archive image in `result/$pname_$version.raw`. The image will contain the
file system structure as required by the portable service specification, and a subset of the Nix store with all the
dependencies of the two derivations in the `units` list.
`units` must be a list of derivations, and their names must be prefixed with the service name (`"demo"` in this case).
Otherwise `systemd-portabled` will ignore them.
After building the package, the generated image can be loaded into a system through {manpage}`portablectl(1)`:
::: {.note}
The `.raw` file extension of the image is required by the portable services specification.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1
$ portablectl attach /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw
Created directory /etc/systemd/system.attached.
Created directory /etc/systemd/system.attached/hello.service.d.
Written /etc/systemd/system.attached/hello.service.d/20-portable.conf.
Created symlink /etc/systemd/system.attached/hello.service.d/10-profile.conf → /usr/lib/systemd/portable/profile/default/service.conf.
Copied /etc/systemd/system.attached/hello.service.
Created symlink /etc/portables/hello_2.12.1.raw → /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw.
$ systemctl start hello
$ journalctl -u hello
Feb 28 22:39:16 hostname systemd[1]: Starting Hello world service...
Feb 28 22:39:16 hostname hello[102887]: Hello, world!
Feb 28 22:39:16 hostname systemd[1]: hello.service: Deactivated successfully.
Feb 28 22:39:16 hostname systemd[1]: Finished Hello world service.
$ portablectl detach hello_2.12.1
Removed /etc/systemd/system.attached/hello.service.
Removed /etc/systemd/system.attached/hello.service.d/10-profile.conf.
Removed /etc/systemd/system.attached/hello.service.d/20-portable.conf.
Removed /etc/systemd/system.attached/hello.service.d.
Removed /etc/portables/hello_2.12.1.raw.
Removed /etc/systemd/system.attached.
```
:::
Some other options available are:
- `description`, `homepage`
:::{.example #ex-portableService-symlinks}
# Specifying symlinks when building a Portable Service image
Are added to the `/etc/os-release` in the image and are shown by the portable services tooling.
Default to empty values, not added to os-release.
- `symlinks`
Some services may expect files or directories to be available globally.
An example is a service which expects all trusted SSL certificates to exist in a specific location by default.
A list of attribute sets {object, symlink}. Symlinks will be created in the root filesystem of the image to
objects in the Nix store. Defaults to an empty list.
- `contents`
To make things available globally, you must specify the `symlinks` attribute when using `portableService`.
The following package builds on the package from [](#ex-portableService-hello) to make `/etc/ssl` available globally (this is only for illustrative purposes, because `hello` doesn't use `/etc/ssl`).
A list of additional derivations to be included in the image Nix store, as-is. Defaults to an empty list.
- `squashfsTools`
Defaults to `pkgs.squashfsTools`, allows you to override the package that provides `mksquashfs`.
- `squash-compression`, `squash-block-size`
Options to `mksquashfs`. Default to `"xz -Xdict-size 100%"` and `"1M"` respectively.
A typical usage of `symlinks` would be:
```nix
symlinks = [
{ object = "${pkgs.cacert}/etc/ssl"; symlink = "/etc/ssl"; }
{ object = "${pkgs.bash}/bin/bash"; symlink = "/bin/sh"; }
{ object = "${pkgs.php}/bin/php"; symlink = "/usr/bin/php"; }
];
```
to create these symlinks for legacy applications that assume them existing globally.
{ lib, writeText, portableService, hello, cacert }:
let
hello-service = writeText "hello.service" ''
[Unit]
Description=Hello world service
Once the image is created, and deployed on a host in `/var/lib/portables/`, you can attach the image and run the service. As root run:
```console
portablectl attach demo_1.0.raw
systemctl enable --now demo.socket
systemctl enable --now demo.service
[Service]
Type=oneshot
ExecStart=${lib.getExe hello}
'';
in
portableService {
pname = "hello";
inherit (hello) version;
units = [ hello-service ];
symlinks = [
{ object = "${cacert}/etc/ssl"; symlink = "/etc/ssl"; }
];
}
```
::: {.note}
See the [man page](https://www.freedesktop.org/software/systemd/man/portablectl.html) of `portablectl` for more info on its usage.
:::

View file

@ -3,6 +3,7 @@
This chapter describes several special build helpers.
```{=include=} sections
special/fakenss.section.md
special/fhs-environments.section.md
special/makesetuphook.section.md
special/mkshell.section.md

View file

@ -0,0 +1,77 @@
# fakeNss {#sec-fakeNss}
Provides `/etc/passwd` and `/etc/group` files that contain `root` and `nobody`, allowing user/group lookups to work in binaries that insist on doing those.
This might be a better choice than a custom script running `useradd` and related utilities if you only need those files to exist with some entries.
`fakeNss` also provides `/etc/nsswitch.conf`, configuring NSS host resolution to first check `/etc/hosts` before checking DNS, since the default in the absence of a config file (`dns [!UNAVAIL=return] files`) is quite unexpected.
It also creates an empty directory at `/var/empty` because it uses that as the home directory for the `root` and `nobody` users.
The `/var/empty` directory can also be used as a `chroot` target to prevent file access in processes that do not need to access files, if your container runs such processes.
The user entries created by `fakeNss` use the `/bin/sh` shell, which is not provided by `fakeNss` because in most cases it won't be used.
If you need that to be available, see [`dockerTools.binSh`](#sssec-pkgs-dockerTools-helpers-binSh) or provide your own.
## Inputs {#sec-fakeNss-inputs}
`fakeNss` is made available in Nixpkgs as a package rather than a function, but it has two attributes that can be overridden and might be useful in particular cases.
For more details on how overriding works, see [](#ex-fakeNss-overriding) and [](#sec-pkg-override).
`extraPasswdLines` (List of Strings; _optional_)
: A list of lines that will be added to `/etc/passwd`.
Useful if extra users need to exist in the output of `fakeNss`.
If `extraPasswdLines` is specified, it will **not** override the `root` and `nobody` entries created by `fakeNss`.
Those entries will always exist.
Lines specified here must follow the format in {manpage}`passwd(5)`.
_Default value:_ `[]`.
`extraGroupLines` (List of Strings; _optional_)
: A list of lines that will be added to `/etc/group`.
Useful if extra groups need to exist in the output of `fakeNss`.
If `extraGroupLines` is specified, it will **not** override the `root` and `nobody` entries created by `fakeNss`.
Those entries will always exist.
Lines specified here must follow the format in {manpage}`group(5)`.
_Default value:_ `[]`.
## Examples {#sec-fakeNss-examples}
:::{.example #ex-fakeNss-dockerTools-buildImage}
# Using `fakeNss` with `dockerTools.buildImage`
This example shows how to use `fakeNss` as-is.
It is useful with functions in `dockerTools` to allow building Docker images that have the `/etc/passwd` and `/etc/group` files.
This example includes the `hello` binary in the image so it can do something besides just have the extra files.
```nix
{ dockerTools, fakeNss, hello }:
dockerTools.buildImage {
name = "image-with-passwd";
tag = "latest";
copyToRoot = [ fakeNss hello ];
config = {
Cmd = [ "/bin/hello" ];
};
}
```
:::
:::{.example #ex-fakeNss-overriding}
# Using `fakeNss` with an override to add extra lines
The following code uses `override` to add extra lines to `/etc/passwd` and `/etc/group` to create another user and group entry.
```nix
{ fakeNss }:
fakeNss.override {
extraPasswdLines = ["newuser:x:9001:9001:new user:/var/empty:/bin/sh"];
extraGroupLines = ["newuser:x:9001:"];
}
```
:::

View file

@ -2,7 +2,7 @@
This hook helps with installing manpages and shell completion files. It exposes 2 shell functions `installManPage` and `installShellCompletion` that can be used from your `postInstall` hook.
The `installManPage` function takes one or more paths to manpages to install. The manpages must have a section suffix, and may optionally be compressed (with `.gz` suffix). This function will place them into the correct directory.
The `installManPage` function takes one or more paths to manpages to install. The manpages must have a section suffix, and may optionally be compressed (with `.gz` suffix). This function will place them into the correct `share/man/man<section>/` directory, in [`outputMan`](#outputman).
The `installShellCompletion` function takes one or more paths to shell completion files. By default it will autodetect the shell type from the completion file extension, but you may also specify it by passing one of `--bash`, `--fish`, or `--zsh`. These flags apply to all paths listed after them (up until another shell flag is given). Each path may also have a custom installation name provided by providing a flag `--name NAME` before the path. If this flag is not provided, zsh completions will be renamed automatically such that `foobar.zsh` becomes `_foobar`. A root name may be provided for all paths using the flag `--cmd NAME`; this synthesizes the appropriate name depending on the shell (e.g. `--cmd foo` will synthesize the name `foo.bash` for bash and `_foo` for zsh). The path may also be a fifo or named fd (such as produced by `<(cmd)`), in which case the shell and name must be provided.

View file

@ -93,7 +93,11 @@ The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given
To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions:
* `projectFile` is used for specifying the dotnet project file, relative to the source root. These have `.sln` (entire solution) or `.csproj` (single project) file extensions. This can be a list of multiple projects as well. When omitted, will attempt to find and build the solution (`.sln`). If running into problems, make sure to set it to a file (or a list of files) with the `.csproj` extension - building applications as entire solutions is not fully supported by the .NET CLI.
* `nugetDeps` takes either a path to a `deps.nix` file, or a derivation. The `deps.nix` file can be generated using the script attached to `passthru.fetch-deps`. This file can also be generated manually using `nuget-to-nix` tool, which is available in nixpkgs. If the argument is a derivation, it will be used directly and assume it has the same output as `mkNugetDeps`.
* `nugetDeps` takes either a path to a `deps.nix` file, or a derivation. The `deps.nix` file can be generated using the script attached to `passthru.fetch-deps`. If the argument is a derivation, it will be used directly and assume it has the same output as `mkNugetDeps`.
::: {.note}
For more detail about managing the `deps.nix` file, see [Generating and updating NuGet dependencies](#generating-and-updating-nuget-dependencies)
:::
* `packNupkg` is used to pack project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `projectReferences`.
* `projectReferences` can be used to resolve `ProjectReference` project items. Referenced projects can be packed with `buildDotnetModule` by setting the `packNupkg = true` attribute and passing a list of derivations to `projectReferences`. Since we are sharing referenced projects as NuGets they must be added to csproj/fsproj files as `PackageReference` as well.
For example, your project has a local dependency:
@ -156,6 +160,8 @@ in buildDotnetModule rec {
}
```
Keep in mind that you can tag the [`@NixOS/dotnet`](https://github.com/orgs/nixos/teams/dotnet) team for help and code review.
## Dotnet global tools {#dotnet-global-tools}
[.NET Global tools](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) are a mechanism provided by the dotnet CLI to install .NET binaries from Nuget packages.
@ -212,5 +218,43 @@ buildDotnetGlobalTool {
};
}
```
## Generating and updating NuGet dependencies {#generating-and-updating-nuget-dependencies}
First, restore the packages to the `out` directory, ensure you have cloned
the upstream repository and you are inside it.
```bash
$ dotnet restore --packages out
Determining projects to restore...
Restored /home/lychee/Celeste64/Celeste64.csproj (in 1.21 sec).
```
Next, use `nuget-to-nix` tool provided in nixpkgs to generate a lockfile to `deps.nix` from
the packages inside the `out` directory.
```bash
$ nuget-to-nix out > deps.nix
```
Which `nuget-to-nix` will generate an output similar to below
```
{ fetchNuGet }: [
(fetchNuGet { pname = "FosterFramework"; version = "0.1.15-alpha"; sha256 = "0pzsdfbsfx28xfqljcwy100xhbs6wyx0z1d5qxgmv3l60di9xkll"; })
(fetchNuGet { pname = "Microsoft.AspNetCore.App.Runtime.linux-x64"; version = "8.0.1"; sha256 = "1gjz379y61ag9whi78qxx09bwkwcznkx2mzypgycibxk61g11da1"; })
(fetchNuGet { pname = "Microsoft.NET.ILLink.Tasks"; version = "8.0.1"; sha256 = "1drbgqdcvbpisjn8mqfgba1pwb6yri80qc4mfvyczqwrcsj5k2ja"; })
(fetchNuGet { pname = "Microsoft.NETCore.App.Runtime.linux-x64"; version = "8.0.1"; sha256 = "1g5b30f4l8a1zjjr3b8pk9mcqxkxqwa86362f84646xaj4iw3a4d"; })
(fetchNuGet { pname = "SharpGLTF.Core"; version = "1.0.0-alpha0031"; sha256 = "0ln78mkhbcxqvwnf944hbgg24vbsva2jpih6q3x82d3h7rl1pkh6"; })
(fetchNuGet { pname = "SharpGLTF.Runtime"; version = "1.0.0-alpha0031"; sha256 = "0lvb3asi3v0n718qf9y367km7qpkb9wci38y880nqvifpzllw0jg"; })
(fetchNuGet { pname = "Sledge.Formats"; version = "1.2.2"; sha256 = "1y0l66m9rym0p1y4ifjlmg3j9lsmhkvbh38frh40rpvf1axn2dyh"; })
(fetchNuGet { pname = "Sledge.Formats.Map"; version = "1.1.5"; sha256 = "1bww60hv9xcyxpvkzz5q3ybafdxxkw6knhv97phvpkw84pd0jil6"; })
(fetchNuGet { pname = "System.Numerics.Vectors"; version = "4.5.0"; sha256 = "1kzrj37yzawf1b19jq0253rcs8hsq1l2q8g69d7ipnhzb0h97m59"; })
]
```
Finally, you move the `deps.nix` file to the appropriate location to be used by `nugetDeps`, then you're all set!
If you ever need to update the dependencies of a package, you instead do
* `nix-build -A package.fetch-deps` to generate the update script for `package`
* Run `./result deps.nix` to regenerate the lockfile to `deps.nix`, keep in mind if a location isn't provided, it will write to a temporary path instead
* Finally, move the file where needed and look at its contents to confirm it has updated the dependencies.
When packaging a new .NET application in nixpkgs, you can tag the [`@NixOS/dotnet`](https://github.com/orgs/nixos/teams/dotnet) team for help and code review.

View file

@ -215,6 +215,11 @@ install the package
environment variable and add dependent libraries to script's `LUA_PATH` and
`LUA_CPATH`.
It accepts as arguments:
* 'luarocksConfig': a nix value that directly maps to the luarocks config used during
the installation
By default `meta.platforms` is set to the same value as the interpreter unless overridden otherwise.
#### `buildLuaApplication` function {#buildluaapplication-function}

View file

@ -116,11 +116,11 @@ buildPythonPackage rec {
rm testing/test_argcomplete.py
'';
nativeBuildInputs = [
build-system = [
setuptools-scm
];
propagatedBuildInputs = [
dependencies = [
attrs
py
setuptools
@ -172,10 +172,10 @@ following are specific to `buildPythonPackage`:
variable in wrapped programs.
* `pyproject`: Whether the pyproject format should be used. When set to `true`,
`pypaBuildHook` will be used, and you can add the required build dependencies
from `build-system.requires` to `nativeBuildInputs`. Note that the pyproject
from `build-system.requires` to `build-system`. Note that the pyproject
format falls back to using `setuptools`, so you can use `pyproject = true`
even if the package only has a `setup.py`. When set to `false`, you can
use the existing [hooks](#setup-hooks0 or provide your own logic to build the
use the existing [hooks](#setup-hooks) or provide your own logic to build the
package. This can be useful for packages that don't support the pyproject
format. When unset, the legacy `setuptools` hooks are used for backwards
compatibility.
@ -206,17 +206,22 @@ build inputs (see "Specifying dependencies"). The following are of special
interest for Python packages, either because these are primarily used, or
because their behaviour is different:
* `nativeBuildInputs ? []`: Build-time only dependencies. Typically executables
as well as the items listed in `setup_requires`.
* `nativeBuildInputs ? []`: Build-time only dependencies. Typically executables.
* `build-system ? []`: Build-time only Python dependencies. Items listed in `build-system.requires`/`setup_requires`.
* `buildInputs ? []`: Build and/or run-time dependencies that need to be
compiled for the host machine. Typically non-Python libraries which are being
linked.
* `nativeCheckInputs ? []`: Dependencies needed for running the [`checkPhase`](#ssec-check-phase). These
are added to [`nativeBuildInputs`](#var-stdenv-nativeBuildInputs) when [`doCheck = true`](#var-stdenv-doCheck). Items listed in
`tests_require` go here.
* `propagatedBuildInputs ? []`: Aside from propagating dependencies,
* `dependencies ? []`: Aside from propagating dependencies,
`buildPythonPackage` also injects code into and wraps executables with the
paths included in this list. Items listed in `install_requires` go here.
* `optional-dependencies ? { }`: Optional feature flagged dependencies. Items listed in `extras_requires` go here.
Aside from propagating dependencies,
`buildPythonPackage` also injects code into and wraps executables with the
paths included in this list. Items listed in `extras_requires` go here.
##### Overriding Python packages {#overriding-python-packages}
@ -299,11 +304,12 @@ python3Packages.buildPythonApplication rec {
hash = "sha256-Pe229rT0aHwA98s+nTHQMEFKZPo/yw6sot8MivFDvAw=";
};
nativeBuildInputs = with python3Packages; [
build-system = with python3Packages; [
setuptools
wheel
];
propagatedBuildInputs = with python3Packages; [
dependencies = with python3Packages; [
tornado
python-daemon
];
@ -462,14 +468,14 @@ are used in [`buildPythonPackage`](#buildpythonpackage-function).
- `eggBuildHook` to skip building for eggs.
- `eggInstallHook` to install eggs.
- `pipBuildHook` to build a wheel using `pip` and PEP 517. Note a build system
(e.g. `setuptools` or `flit`) should still be added as `nativeBuildInput`.
(e.g. `setuptools` or `flit`) should still be added as `build-system`.
- `pypaBuildHook` to build a wheel using
[`pypa/build`](https://pypa-build.readthedocs.io/en/latest/index.html) and
PEP 517/518. Note a build system (e.g. `setuptools` or `flit`) should still
be added as `nativeBuildInput`.
be added as `build-system`.
- `pipInstallHook` to install wheels.
- `pytestCheckHook` to run tests with `pytest`. See [example usage](#using-pytestcheckhook).
- `pythonCatchConflictsHook` to check whether a Python package is not already existing.
- `pythonCatchConflictsHook` to fail if the package depends on two different versions of the same dependency.
- `pythonImportsCheckHook` to check whether importing the listed modules works.
- `pythonRelaxDepsHook` will relax Python dependencies restrictions for the package.
See [example usage](#using-pythonrelaxdepshook).
@ -881,7 +887,7 @@ buildPythonPackage rec {
hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
};
nativeBuildInputs = [
build-system = [
setuptools
wheel
];
@ -941,7 +947,7 @@ with import <nixpkgs> {};
hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
};
nativeBuildInputs = [
build-system = [
python311.pkgs.setuptools
python311.pkgs.wheel
];
@ -977,13 +983,15 @@ that we introduced with the `let` expression.
#### Handling dependencies {#handling-dependencies}
Our example, `toolz`, does not have any dependencies on other Python packages or
system libraries. According to the manual, [`buildPythonPackage`](#buildpythonpackage-function) uses the
arguments [`buildInputs`](#var-stdenv-buildInputs) and [`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs) to specify dependencies. If
something is exclusively a build-time dependency, then the dependency should be
included in [`buildInputs`](#var-stdenv-buildInputs), but if it is (also) a runtime dependency, then it
should be added to [`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs). Test dependencies are considered
build-time dependencies and passed to [`nativeCheckInputs`](#var-stdenv-nativeCheckInputs).
Our example, `toolz`, does not have any dependencies on other Python packages or system libraries.
[`buildPythonPackage`](#buildpythonpackage-function) uses the the following arguments in the following circumstances:
- `dependencies` - For Python runtime dependencies.
- `build-system` - For Python build-time requirements.
- [`buildInputs`](#var-stdenv-buildInputs) - For non-Python build-time requirements.
- [`nativeCheckInputs`](#var-stdenv-nativeCheckInputs) - For test dependencies
Dependencies can belong to multiple arguments, for example if something is both a build time requirement & a runtime dependency.
The following example shows which arguments are given to [`buildPythonPackage`](#buildpythonpackage-function) in
order to build [`datashape`](https://github.com/blaze/datashape).
@ -1013,12 +1021,12 @@ buildPythonPackage rec {
hash = "sha256-FLLvdm1MllKrgTGC6Gb0k0deZeVYvtCCLji/B7uhong=";
};
nativeBuildInputs = [
build-system = [
setuptools
wheel
];
propagatedBuildInputs = [
dependencies = [
multipledispatch
numpy
python-dateutil
@ -1041,7 +1049,7 @@ buildPythonPackage rec {
We can see several runtime dependencies, `numpy`, `multipledispatch`, and
`python-dateutil`. Furthermore, we have [`nativeCheckInputs`](#var-stdenv-nativeCheckInputs) with `pytest`.
`pytest` is a test runner and is only used during the [`checkPhase`](#ssec-check-phase) and is
therefore not added to [`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs).
therefore not added to `dependencies`.
In the previous case we had only dependencies on other Python packages to consider.
Occasionally you have also system libraries to consider. E.g., `lxml` provides
@ -1068,7 +1076,7 @@ buildPythonPackage rec {
hash = "sha256-s9NiusRxFydHzaNRMjjxFcvWxfi45jGb9ql6eJJyQJk=";
};
nativeBuildInputs = [
build-system = [
setuptools
wheel
];
@ -1125,7 +1133,7 @@ buildPythonPackage rec {
hash = "sha256-9ru2r6kwhUCaskiFoaPNuJCfCVoUL01J40byvRt4kHQ=";
};
nativeBuildInputs = [
build-system = [
setuptools
wheel
];
@ -1136,7 +1144,7 @@ buildPythonPackage rec {
fftwLongDouble
];
propagatedBuildInputs = [
dependencies = [
numpy
scipy
];
@ -1459,9 +1467,7 @@ mode is activated.
In the following example, we create a simple environment that has a Python 3.11
version of our package in it, as well as its dependencies and other packages we
like to have in the environment, all specified with [`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs).
Indeed, we can just add any package we like to have in our environment to
[`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs).
like to have in the environment, all specified with `dependencies`.
```nix
with import <nixpkgs> {};
@ -1470,9 +1476,11 @@ with python311Packages;
buildPythonPackage rec {
name = "mypackage";
src = ./path/to/package/source;
propagatedBuildInputs = [
dependencies = [
pytest
numpy
];
propagatedBuildInputs = [
pkgs.libsndfile
];
}
@ -1519,7 +1527,7 @@ buildPythonPackage rec {
hash = "sha256-CP3V73yWSArRHBLUct4hrNMjWZlvaaUlkpm1QP66RWA=";
};
nativeBuildInputs = [
build-system = [
setuptools
wheel
];
@ -1903,8 +1911,8 @@ configure alternatives](#sec-overlays-alternatives-blas-lapack)".
In a `setup.py` or `setup.cfg` it is common to declare dependencies:
* `setup_requires` corresponds to [`nativeBuildInputs`](#var-stdenv-nativeBuildInputs)
* `install_requires` corresponds to [`propagatedBuildInputs`](#var-stdenv-propagatedBuildInputs)
* `setup_requires` corresponds to `build-system`
* `install_requires` corresponds to `dependencies`
* `tests_require` corresponds to [`nativeCheckInputs`](#var-stdenv-nativeCheckInputs)
### How to enable interpreter optimizations? {#optimizations}
@ -1928,12 +1936,10 @@ in mypython
Some packages define optional dependencies for additional features. With
`setuptools` this is called `extras_require` and `flit` calls it
`extras-require`, while PEP 621 calls these `optional-dependencies`. A
method for supporting this is by declaring the extras of a package in its
`passthru`, e.g. in case of the package `dask`
`extras-require`, while PEP 621 calls these `optional-dependencies`.
```nix
passthru.optional-dependencies = {
optional-dependencies = {
complete = [ distributed ];
};
```
@ -1941,11 +1947,13 @@ passthru.optional-dependencies = {
and letting the package requiring the extra add the list to its dependencies
```nix
propagatedBuildInputs = [
dependencies = [
...
] ++ dask.optional-dependencies.complete;
```
This method is using `passthru`, meaning that changing `optional-dependencies` of a package won't cause it to rebuild.
Note this method is preferred over adding parameters to builders, as that can
result in packages depending on different variants and thereby causing
collisions.

View file

@ -3,72 +3,61 @@
Writing Nix expressions for Qt libraries and applications is largely similar as for other C++ software.
This section assumes some knowledge of the latter.
The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime,
from a list of well-known locations. In Nixpkgs, we patch QtCore to instead use an environment variable,
and wrap Qt applications to set it to the right paths. This effectively makes the runtime dependencies
pure and explicit at build-time, at the cost of introducing an extra indirection.
The major caveat with Qt applications is that Qt uses a plugin system to load additional modules at runtime.
In Nixpkgs, we wrap Qt applications to inject environment variables telling Qt where to discover the required plugins and QML modules.
This effectively makes the runtime dependencies pure and explicit at build-time, at the cost of introducing
an extra indirection.
## Nix expression for a Qt package (default.nix) {#qt-default-nix}
```nix
{ stdenv, lib, qtbase, wrapQtAppsHook }:
{ stdenv, lib, qt6, wrapQtAppsHook }:
stdenv.mkDerivation {
pname = "myapp";
version = "1.0";
buildInputs = [ qtbase ];
nativeBuildInputs = [ wrapQtAppsHook ];
buildInputs = [ qt6.qtbase ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
}
```
It is important to import Qt modules directly, that is: `qtbase`, `qtdeclarative`, etc. *Do not* import Qt package sets such as `qt5` because the Qt versions of dependencies may not be coherent, causing build and runtime failures.
Any Qt package should include `wrapQtAppsHook` in `nativeBuildInputs`, or explicitly set `dontWrapQtApps` to bypass generating the wrappers.
Additionally all Qt packages must include `wrapQtAppsHook` in `nativeBuildInputs`, or you must explicitly set `dontWrapQtApps`.
::: {.note}
Graphical Linux applications should also include `qtwayland` in `buildInputs`, to ensure the Wayland platform plugin is available.
`pkgs.callPackage` does not provide injections for `qtbase` or the like.
Instead you want to either use `pkgs.libsForQt5.callPackage`, or `pkgs.qt6Packages.callPackage`, depending on the Qt version you want to use.
This may become default in the future, see [NixOS/nixpkgs#269674](https://github.com/NixOS/nixpkgs/pull/269674).
:::
For example (from [here](https://github.com/NixOS/nixpkgs/blob/2f9286912cb215969ece465147badf6d07aa43fe/pkgs/top-level/all-packages.nix#L30106))
## Packages supporting multiple Qt versions {#qt-versions}
```nix
zeal-qt5 = libsForQt5.callPackage ../data/documentation/zeal { };
zeal-qt6 = qt6Packages.callPackage ../data/documentation/zeal { };
zeal = zeal-qt5;
```
If your package is a library that can be built with multiple Qt versions, you may want to take Qt modules as separate arguments (`qtbase`, `qtdeclarative` etc.), and invoke the package from `pkgs/top-level/qt5-packages.nix` or `pkgs/top-level/qt6-packages.nix` using the respective `callPackage` functions.
## Locating runtime dependencies {#qt-runtime-dependencies}
Applications should generally be built with upstream's preferred Qt version.
Qt applications must be wrapped to find runtime dependencies.
Include `wrapQtAppsHook` in `nativeBuildInputs`:
```nix
{ stdenv, wrapQtAppsHook }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
}
```
## Locating additional runtime dependencies {#qt-runtime-dependencies}
Add entries to `qtWrapperArgs` are to modify the wrappers created by
`wrapQtAppsHook`:
```nix
{ stdenv, wrapQtAppsHook }:
{ stdenv, qt6 }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ wrapQtAppsHook ];
nativeBuildInputs = [ qt6.wrapQtAppsHook ];
qtWrapperArgs = [ ''--prefix PATH : /path/to/bin'' ];
}
```
The entries are passed as arguments to [wrapProgram](#fun-wrapProgram).
Set `dontWrapQtApps` to stop applications from being wrapped automatically.
Wrap programs manually with `wrapQtApp`, using the syntax of
[wrapProgram](#fun-wrapProgram):
If you need more control over the wrapping process, set `dontWrapQtApps` to disable automatic wrapper generation,
and then create wrappers manually in `fixupPhase`, using `wrapQtApp`, which itself is a small wrapper over [wrapProgram](#fun-wrapProgram):
The `makeWrapper` arguments required for Qt are also exposed in the environment as `$qtWrapperArgs`.
```nix
{ stdenv, lib, wrapQtAppsHook }:

View file

@ -44,11 +44,11 @@ rustPlatform.buildRustPackage rec {
}
```
`buildRustPackage` requires either the `cargoHash` or the `cargoSha256`
attribute which is computed over all crate sources of this package.
`cargoSha256` is used for traditional Nix SHA-256 hashes. `cargoHash` should
instead be used for [SRI](https://www.w3.org/TR/SRI/) hashes and should be
preferred. For example:
`buildRustPackage` requires either a `cargoHash` (preferred) or a
`cargoSha256` attribute, computed over all crate sources of this package.
`cargoHash` supports [SRI](https://www.w3.org/TR/SRI/) hashes and should be
preferred over `cargoSha256` which was used for traditional Nix SHA-256 hashes.
For example:
```nix
cargoHash = "sha256-l1vL2ZdtDRxSGvP0X/l3nMw8+6WF67KPutJEzUROjg8=";
@ -64,18 +64,18 @@ Both types of hashes are permitted when contributing to nixpkgs. The
Cargo hash is obtained by inserting a fake checksum into the
expression and building the package once. The correct checksum can
then be taken from the failed build. A fake hash can be used for
`cargoSha256` as follows:
```nix
cargoSha256 = lib.fakeSha256;
```
For `cargoHash` you can use:
`cargoHash` as follows:
```nix
cargoHash = lib.fakeHash;
```
For `cargoSha256` you can use:
```nix
cargoSha256 = lib.fakeSha256;
```
Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
best practices guide, Rust applications should always commit the `Cargo.lock`
file in git to ensure a reproducible build. However, a few packages do not, and
@ -90,7 +90,7 @@ directory into a tar.gz archive.
The tarball with vendored dependencies contains a directory with the
package's `name`, which is normally composed of `pname` and
`version`. This means that the vendored dependencies hash
(`cargoSha256`/`cargoHash`) is dependent on the package name and
(`cargoHash`/`cargoSha256`) is dependent on the package name and
version. The `cargoDepsName` attribute can be used to use another name
for the directory of vendored dependencies. For example, the hash can
be made invariant to the version by setting `cargoDepsName` to
@ -115,7 +115,7 @@ rustPlatform.buildRustPackage rec {
### Importing a `Cargo.lock` file {#importing-a-cargo.lock-file}
Using `cargoSha256` or `cargoHash` is tedious when using
Using a vendored hash (`cargoHash`/`cargoSha256`) is tedious when using
`buildRustPackage` within a project, since it requires that the hash
is updated after every change to `Cargo.lock`. Therefore,
`buildRustPackage` also supports vendoring dependencies directly from

View file

@ -314,5 +314,11 @@
"systemd-veritysetup@.service(8)": "https://www.freedesktop.org/software/systemd/man/systemd-veritysetup@.service.html",
"systemd-volatile-root(8)": "https://www.freedesktop.org/software/systemd/man/systemd-volatile-root.html",
"systemd-xdg-autostart-generator(8)": "https://www.freedesktop.org/software/systemd/man/systemd-xdg-autostart-generator.html",
"udevadm(8)": "https://www.freedesktop.org/software/systemd/man/udevadm.html"
"udevadm(8)": "https://www.freedesktop.org/software/systemd/man/udevadm.html",
"passwd(5)": "https://man.archlinux.org/man/passwd.5",
"group(5)": "https://man.archlinux.org/man/group.5",
"login.defs(5)": "https://man.archlinux.org/man/login.defs.5",
"unshare(1)": "https://man.archlinux.org/man/unshare.1.en",
"nix-shell(1)": "https://nixos.org/manual/nix/stable/command-ref/nix-shell.html",
"mksquashfs(1)": "https://man.archlinux.org/man/extra/squashfs-tools/mksquashfs.1.en"
}

View file

@ -1,5 +1,12 @@
# darwin.linux-builder {#sec-darwin-builder}
:::{.warning}
By default, `darwin.linux-builder` uses a publicly-known private SSH **host key** (this is different from the SSH key used by the user that connects to the builder).
Given the intended use case for it (a Linux builder that runs **on the same machine**), this shouldn't be an issue.
However, if you plan to deviate from this use case in any way (e.g. by exposing this builder to remote machines), you should understand the security implications of doing so and take any appropriate measures.
:::
`darwin.linux-builder` provides a way to bootstrap a Linux remote builder on a macOS machine.
This requires macOS version 12.4 or later.
@ -97,8 +104,9 @@ $ sudo launchctl kickstart -k system/org.nixos.nix-daemon
{ virtualisation = {
host.pkgs = pkgs;
darwin-builder.workingDirectory = "/var/lib/darwin-builder";
darwin-builder.hostPort = 22;
};
};
}
];
};
in {
@ -110,7 +118,9 @@ $ sudo launchctl kickstart -k system/org.nixos.nix-daemon
{
nix.distributedBuilds = true;
nix.buildMachines = [{
hostName = "ssh://builder@localhost";
hostName = "localhost";
sshUser = "builder";
sshKey = "/etc/nix/builder_ed25519";
system = linuxSystem;
maxJobs = 4;
supportedFeatures = [ "kvm" "benchmark" "big-parallel" ];

View file

@ -27,7 +27,19 @@
# We set it to null, to remove the "legacy" entrypoint's
# non-hermetic default.
system = null;
} // args
modules = args.modules ++ [
# This module is injected here since it exposes the nixpkgs self-path in as
# constrained of contexts as possible to avoid more things depending on it and
# introducing unnecessary potential fragility to changes in flakes itself.
#
# See: failed attempt to make pkgs.path not copy when using flakes:
# https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1023287913
({ config, pkgs, lib, ... }: {
config.nixpkgs.flake.source = self.outPath;
})
];
} // builtins.removeAttrs args [ "modules" ]
);
});

View file

@ -2,10 +2,10 @@
{ lib }:
let
inherit (builtins) head tail length;
inherit (lib.trivial) id mergeAttrs;
inherit (builtins) head length;
inherit (lib.trivial) mergeAttrs warn;
inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
inherit (lib.lists) foldr foldl' concatMap concatLists elemAt all partition groupBy take foldl;
inherit (lib.lists) foldr foldl' concatMap elemAt all partition groupBy take foldl;
in
rec {
@ -369,7 +369,7 @@ rec {
Type:
attrValues :: AttrSet -> [Any]
*/
attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
attrValues = builtins.attrValues;
/* Given a set of attribute names, return the set of the corresponding
@ -398,8 +398,7 @@ rec {
Type:
catAttrs :: String -> [AttrSet] -> [Any]
*/
catAttrs = builtins.catAttrs or
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
catAttrs = builtins.catAttrs;
/* Filter an attribute set by removing all attributes for which the
@ -608,9 +607,7 @@ rec {
Type:
mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
*/
mapAttrs = builtins.mapAttrs or
(f: set:
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)));
mapAttrs = builtins.mapAttrs;
/* Like `mapAttrs`, but allows the name of each attribute to be
@ -1197,9 +1194,10 @@ rec {
(x // y) // mask;
# DEPRECATED
zipWithNames = zipAttrsWithNames;
zipWithNames = warn
"lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
# DEPRECATED
zip = builtins.trace
"lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;
zip = warn
"lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
}

View file

@ -84,8 +84,8 @@ let
mapAttrs' mapAttrsToList attrsToList concatMapAttrs mapAttrsRecursive
mapAttrsRecursiveCond genAttrs isDerivation toDerivation optionalAttrs
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
recursiveUpdate matchAttrs overrideExisting showAttrPath getOutput getBin
getLib getDev getMan chooseDevOutputs zipWithNames zip
recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets
updateManyAttrsByPath;
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1

View file

@ -23,6 +23,10 @@
Add files in file sets to the store to use as derivation sources.
- [`lib.fileset.toList`](#function-library-lib.fileset.toList):
The list of files contained in a file set.
Combinators:
- [`lib.fileset.union`](#function-library-lib.fileset.union)/[`lib.fileset.unions`](#function-library-lib.fileset.unions):
@ -102,6 +106,7 @@ let
_coerceMany
_toSourceFilter
_fromSourceFilter
_toList
_unionMany
_fileFilter
_printFileset
@ -412,6 +417,38 @@ in {
filter = sourceFilter;
};
/*
The list of file paths contained in the given file set.
:::{.note}
This function is strict in the entire file set.
This is in contrast with combinators [`lib.fileset.union`](#function-library-lib.fileset.union),
[`lib.fileset.intersection`](#function-library-lib.fileset.intersection) and [`lib.fileset.difference`](#function-library-lib.fileset.difference).
Thus it is recommended to call `toList` on file sets created using the combinators,
instead of doing list processing on the result of `toList`.
:::
The resulting list of files can be turned back into a file set using [`lib.fileset.unions`](#function-library-lib.fileset.unions).
Type:
toList :: FileSet -> [ Path ]
Example:
toList ./.
[ ./README.md ./Makefile ./src/main.c ./src/main.h ]
toList (difference ./. ./src)
[ ./README.md ./Makefile ]
*/
toList =
# The file set whose file paths to return.
# This argument can also be a path,
# which gets [implicitly coerced to a file set](#sec-fileset-path-coercion).
fileset:
_toList (_coerce "lib.fileset.toList: Argument" fileset);
/*
The file set containing all files that are in either of two given file sets.
This is the same as [`unions`](#function-library-lib.fileset.unions),

View file

@ -18,6 +18,7 @@ let
attrNames
attrValues
mapAttrs
mapAttrsToList
optionalAttrs
zipAttrsWith
;
@ -29,6 +30,7 @@ let
inherit (lib.lists)
all
commonPrefix
concatLists
elemAt
filter
findFirst
@ -539,6 +541,27 @@ rec {
${baseNameOf root} = rootPathType;
};
# Turns a file set into the list of file paths it includes.
# Type: fileset -> [ Path ]
_toList = fileset:
let
recurse = path: tree:
if isAttrs tree then
concatLists (mapAttrsToList (name: value:
recurse (path + "/${name}") value
) tree)
else if tree == "directory" then
recurse path (readDir path)
else if tree == null then
[ ]
else
[ path ];
in
if fileset._internalIsEmptyWithoutBase then
[ ]
else
recurse fileset._internalBase fileset._internalTree;
# Transforms the filesetTree of a file set to a shorter base path, e.g.
# _shortenTreeBase [ "foo" ] (_create /foo/bar null)
# => { bar = null; }

View file

@ -275,7 +275,6 @@ createTree() {
# )
# checkFileset './a' # Pass the fileset as the argument
checkFileset() {
# New subshell so that we can have a separate trap handler, see `trap` below
local fileset=$1
# Create the tree
@ -283,16 +282,20 @@ checkFileset() {
# Process the tree into separate arrays for included paths, excluded paths and excluded files.
local -a included=()
local -a includedFiles=()
local -a excluded=()
local -a excludedFiles=()
for p in "${!tree[@]}"; do
case "${tree[$p]}" in
1)
included+=("$p")
# If keys end with a `/` we treat them as directories, otherwise files
if [[ ! "$p" =~ /$ ]]; then
includedFiles+=("$p")
fi
;;
0)
excluded+=("$p")
# If keys end with a `/` we treat them as directories, otherwise files
if [[ ! "$p" =~ /$ ]]; then
excludedFiles+=("$p")
fi
@ -302,6 +305,10 @@ checkFileset() {
esac
done
# Test that lib.fileset.toList contains exactly the included files.
# The /#/./ part prefixes each element with `./`
expectEqual "toList ($fileset)" "sort lessThan [ ${includedFiles[*]/#/./} ]"
expression="toSource { root = ./.; fileset = $fileset; }"
# We don't have lambda's in bash unfortunately,
@ -338,13 +345,17 @@ checkFileset() {
#### Error messages #####
# We're using [[:blank:]] here instead of \s, because only the former is POSIX
# (see https://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html#tag_007_003_005).
# And indeed, Darwin's bash only supports the former
# Absolute paths in strings cannot be passed as `root`
expectFailure 'toSource { root = "/nix/store/foobar"; fileset = ./.; }' 'lib.fileset.toSource: `root` \(/nix/store/foobar\) is a string-like value, but it should be a path instead.
\s*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
[[:blank:]]*Paths in strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
expectFailure 'toSource { root = cleanSourceWith { src = ./.; }; fileset = ./.; }' 'lib.fileset.toSource: `root` is a `lib.sources`-based value, but it should be a path instead.
\s*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
\s*Note that this only works for sources created from paths.'
[[:blank:]]*To use a `lib.sources`-based value, convert it to a file set using `lib.fileset.fromSource` and pass it as `fileset`.
[[:blank:]]*Note that this only works for sources created from paths.'
# Only paths are accepted as `root`
expectFailure 'toSource { root = 10; fileset = ./.; }' 'lib.fileset.toSource: `root` is of type int, but it should be a path instead.'
@ -354,9 +365,9 @@ mkdir -p {foo,bar}/mock-root
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
toSource { root = ./foo/mock-root; fileset = ./bar/mock-root; }
' 'lib.fileset.toSource: Filesystem roots are not the same for `fileset` and `root` \('"$work"'/foo/mock-root\):
\s*`root`: Filesystem root is "'"$work"'/foo/mock-root"
\s*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
\s*Different filesystem roots are not supported.'
[[:blank:]]*`root`: Filesystem root is "'"$work"'/foo/mock-root"
[[:blank:]]*`fileset`: Filesystem root is "'"$work"'/bar/mock-root"
[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# `root` needs to exist
@ -365,8 +376,8 @@ expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `
# `root` needs to be a file
touch a
expectFailure 'toSource { root = ./a; fileset = ./a; }' 'lib.fileset.toSource: `root` \('"$work"'/a\) is a file, but it should be a directory instead. Potential solutions:
\s*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
\s*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
[[:blank:]]*- If you want to import the file into the store _without_ a containing directory, use string interpolation or `builtins.path` instead of this function.
[[:blank:]]*- If you want to import the file into the store _with_ a containing directory, set `root` to the containing directory, such as '"$work"', and set `fileset` to the file path.'
rm -rf -- *
# The fileset argument should be evaluated, even if the directory is empty
@ -375,36 +386,36 @@ expectFailure 'toSource { root = ./.; fileset = abort "This should be evaluated"
# Only paths under `root` should be able to influence the result
mkdir a
expectFailure 'toSource { root = ./a; fileset = ./.; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
rm -rf -- *
# non-regular and non-symlink files cannot be added to the Nix store
mkfifo a
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` contains a file that cannot be added to the store: '"$work"'/a
\s*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
\s*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
[[:blank:]]*This file is neither a regular file nor a symlink, the only file types supported by the Nix store.
[[:blank:]]*Therefore the file set cannot be added to the Nix store as is. Make sure to not include that file to avoid this error.'
rm -rf -- *
# Path coercion only works for paths
expectFailure 'toSource { root = ./.; fileset = 10; }' 'lib.fileset.toSource: `fileset` is of type int, but it should be a file set or a path instead.'
expectFailure 'toSource { root = ./.; fileset = "/some/path"; }' 'lib.fileset.toSource: `fileset` \("/some/path"\) is a string-like value, but it should be a file set or a path instead.
\s*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
[[:blank:]]*Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'
expectFailure 'toSource { root = ./.; fileset = cleanSourceWith { src = ./.; }; }' 'lib.fileset.toSource: `fileset` is a `lib.sources`-based value, but it should be a file set or a path instead.
\s*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
\s*Note that this only works for sources created from paths.'
[[:blank:]]*To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`.
[[:blank:]]*Note that this only works for sources created from paths.'
# Path coercion errors for non-existent paths
expectFailure 'toSource { root = ./.; fileset = ./a; }' 'lib.fileset.toSource: `fileset` \('"$work"'/a\) is a path that does not exist.
\s*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
[[:blank:]]*To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'
# File sets cannot be evaluated directly
expectFailure 'union ./. ./.' 'lib.fileset: Directly evaluating a file set is not supported.
\s*To turn it into a usable source, use `lib.fileset.toSource`.
\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
expectFailure '_emptyWithoutBase' 'lib.fileset: Directly evaluating a file set is not supported.
\s*To turn it into a usable source, use `lib.fileset.toSource`.
\s*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
[[:blank:]]*To turn it into a usable source, use `lib.fileset.toSource`.
[[:blank:]]*To pretty-print the contents, use `lib.fileset.trace` or `lib.fileset.traceVal`.'
# Past versions of the internal representation are supported
expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 0; _internalBase = ./.; }' \
@ -416,9 +427,9 @@ expectEqual '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 2;
# Future versions of the internal representation are unsupported
expectFailure '_coerce "<tests>: value" { _type = "fileset"; _internalVersion = 4; }' '<tests>: value is a file set created from a future version of the file set library with a different internal representation:
\s*- Internal version of the file set: 4
\s*- Internal version of the library: 3
\s*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
[[:blank:]]*- Internal version of the file set: 4
[[:blank:]]*- Internal version of the library: 3
[[:blank:]]*Make sure to update your Nixpkgs to have a newer version of `lib.fileset`.'
# _create followed by _coerce should give the inputs back without any validation
expectEqual '{
@ -511,6 +522,19 @@ expectEqual '_toSourceFilter (_create /. { foo = "regular"; }) "/foo" ""' 'true'
expectEqual '_toSourceFilter (_create /. { foo = null; }) "/foo" ""' 'false'
## lib.fileset.toList
# This function is mainly tested in checkFileset
# The error context for an invalid argument must be correct
expectFailure 'toList null' 'lib.fileset.toList: Argument is of type null, but it should be a file set or a path instead.'
# Works for the empty fileset
expectEqual 'toList _emptyWithoutBase' '[ ]'
# Works on empty paths
expectEqual 'toList ./.' '[ ]'
## lib.fileset.union, lib.fileset.unions
@ -519,16 +543,16 @@ mkdir -p {foo,bar}/mock-root
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
toSource { root = ./.; fileset = union ./foo/mock-root ./bar/mock-root; }
' 'lib.fileset.union: Filesystem roots are not the same:
\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
\s*Different filesystem roots are not supported.'
[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
[[:blank:]]*Different filesystem roots are not supported.'
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
toSource { root = ./.; fileset = unions [ ./foo/mock-root ./bar/mock-root ]; }
' 'lib.fileset.unions: Filesystem roots are not the same:
\s*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
\s*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
\s*Different filesystem roots are not supported.'
[[:blank:]]*Element 0: Filesystem root is "'"$work"'/foo/mock-root"
[[:blank:]]*Element 1: Filesystem root is "'"$work"'/bar/mock-root"
[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# Coercion errors show the correct context
@ -632,9 +656,9 @@ mkdir -p {foo,bar}/mock-root
expectFailure 'with ((import <nixpkgs/lib>).extend (import <nixpkgs/lib/fileset/mock-splitRoot.nix>)).fileset;
toSource { root = ./.; fileset = intersection ./foo/mock-root ./bar/mock-root; }
' 'lib.fileset.intersection: Filesystem roots are not the same:
\s*First argument: Filesystem root is "'"$work"'/foo/mock-root"
\s*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
\s*Different filesystem roots are not supported.'
[[:blank:]]*First argument: Filesystem root is "'"$work"'/foo/mock-root"
[[:blank:]]*Second argument: Filesystem root is "'"$work"'/bar/mock-root"
[[:blank:]]*Different filesystem roots are not supported.'
rm -rf -- *
# Coercion errors show the correct context
@ -741,8 +765,8 @@ rm -rf -- *
# Also not the other way around
mkdir a
expectFailure 'toSource { root = ./a; fileset = difference ./. ./a; }' 'lib.fileset.toSource: `fileset` could contain files in '"$work"', which is not under the `root` \('"$work"'/a\). Potential solutions:
\s*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
\s*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
[[:blank:]]*- Set `root` to '"$work"' or any directory higher up. This changes the layout of the resulting store path.
[[:blank:]]*- Set `fileset` to a file set that cannot contain files outside the `root` \('"$work"'/a\). This could change the files included in the result.'
rm -rf -- *
# Difference actually works
@ -819,7 +843,7 @@ expectFailure 'fileFilter null (abort "this is not needed")' 'lib.fileset.fileFi
# The second argument needs to be an existing path
expectFailure 'fileFilter (file: abort "this is not needed") _emptyWithoutBase' 'lib.fileset.fileFilter: Second argument is a file set, but it should be a path instead.
\s*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
[[:blank:]]*If you need to filter files in a file set, use `intersection fileset \(fileFilter pred \./\.\)` instead.'
expectFailure 'fileFilter (file: abort "this is not needed") null' 'lib.fileset.fileFilter: Second argument is of type null, but it should be a path instead.'
expectFailure 'fileFilter (file: abort "this is not needed") ./a' 'lib.fileset.fileFilter: Second argument \('"$work"'/a\) is a path that does not exist.'
@ -1083,7 +1107,7 @@ rm -rf -- *
# String-like values are not supported
expectFailure 'fromSource (lib.cleanSource "")' 'lib.fileset.fromSource: The source origin of the argument is a string-like value \(""\), but it should be a path instead.
\s*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
[[:blank:]]*Sources created from paths in strings cannot be turned into file sets, use `lib.sources` or derivations instead.'
# Wrong type
expectFailure 'fromSource null' 'lib.fileset.fromSource: The source origin of the argument is of type null, but it should be a path instead.'
@ -1400,10 +1424,10 @@ expectEqual '(import '"$storePath"' { fs = lib.fileset; }).outPath' \""$storePat
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*\) is a store path within a working tree of a Git repository.
\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
## Even with submodules
if [[ -n "$fetchGitSupportsSubmodules" ]]; then
@ -1427,15 +1451,15 @@ if [[ -n "$fetchGitSupportsSubmodules" ]]; then
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
\s*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
\s*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
\s*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
\s*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
fi
rm -rf -- *

View file

@ -145,6 +145,12 @@ rec {
in fix g
```
:::{.note}
The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
:::
:::{.example}
# Extend a fixed-point function with an overlay
@ -230,13 +236,6 @@ rec {
fix (extends (final: prev: { c = final.a + final.b; }) f)
=> { a = 1; b = 3; c = 4; }
:::{.note}
The argument to the given fixed-point function after applying an overlay will *not* refer to its own return value, but rather to the value after evaluating the overlay function.
The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
The new argument
:::
*/
extends =
# The overlay to apply to the fixed-point function

View file

@ -854,6 +854,11 @@ in mkLicense lset) ({
fullName = "Mozilla Public License 2.0";
};
mplus = {
spdxId = "mplus";
fullName = "M+ Font License";
};
mspl = {
spdxId = "MS-PL";
fullName = "Microsoft Public License";

View file

@ -2,9 +2,8 @@
{ lib }:
let
inherit (lib.strings) toInt;
inherit (lib.trivial) compare min id;
inherit (lib.trivial) compare min id warn;
inherit (lib.attrsets) mapAttrs;
inherit (lib.lists) sort;
in
rec {
@ -172,7 +171,7 @@ rec {
concatMap (x: [x] ++ ["z"]) ["a" "b"]
=> [ "a" "z" "b" "z" ]
*/
concatMap = builtins.concatMap or (f: list: concatLists (map f list));
concatMap = builtins.concatMap;
/* Flatten the argument into a single list; that is, nested lists are
spliced into the top-level lists.
@ -316,7 +315,7 @@ rec {
any isString [ 1 { } ]
=> false
*/
any = builtins.any or (pred: foldr (x: y: if pred x then true else y) false);
any = builtins.any;
/* Return true if function `pred` returns true for all elements of
`list`.
@ -329,7 +328,7 @@ rec {
all (x: x < 3) [ 1 2 3 ]
=> false
*/
all = builtins.all or (pred: foldr (x: y: if pred x then y else false) true);
all = builtins.all;
/* Count how many elements of `list` match the supplied predicate
function.
@ -428,12 +427,7 @@ rec {
partition (x: x > 2) [ 5 1 2 3 4 ]
=> { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
*/
partition = builtins.partition or (pred:
foldr (h: t:
if pred h
then { right = [h] ++ t.right; wrong = t.wrong; }
else { right = t.right; wrong = [h] ++ t.wrong; }
) { right = []; wrong = []; });
partition = builtins.partition;
/* Splits the elements of a list into many lists, using the return value of a predicate.
Predicate should return a string which becomes keys of attrset `groupBy` returns.
@ -602,22 +596,7 @@ rec {
Type:
sort :: (a -> a -> Bool) -> [a] -> [a]
*/
sort = builtins.sort or (
strictLess: list:
let
len = length list;
first = head list;
pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (n + 1); in
if n == len
then acc
else if strictLess first el
then next { inherit left; right = [ el ] ++ right; }
else
next { left = [ el ] ++ left; inherit right; };
pivot = pivot' 1 { left = []; right = []; };
in
if len < 2 then list
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
sort = builtins.sort;
/*
Sort a list based on the default comparison of a derived property `b`.
@ -848,8 +827,8 @@ rec {
crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
=> [ "13" "14" "23" "24" ]
*/
crossLists = builtins.trace
"lib.crossLists is deprecated, use lib.cartesianProductOfSets instead"
crossLists = warn
"lib.crossLists is deprecated, use lib.cartesianProductOfSets instead."
(f: foldl (fs: args: concatMap (f: map f args) fs) [f]);

View file

@ -87,6 +87,10 @@ rec {
We can inject these into a pattern for the whole of a structured platform,
and then match that.
Example:
lib.meta.platformMatch { system = "aarch64-darwin"; } "aarch64-darwin"
=> true
*/
platformMatch = platform: elem: (
# Check with simple string comparison if elem was a string.
@ -112,6 +116,10 @@ rec {
platform, or `meta.platforms` is not present.
2. None of `meta.badPlatforms` pattern matches the given platform.
Example:
lib.meta.availableOn { system = "aarch64-darwin"; } pkg.zsh
=> true
*/
availableOn = platform: pkg:
((!pkg?meta.platforms) || any (platformMatch platform) pkg.meta.platforms) &&

View file

@ -81,9 +81,9 @@ let
, # `class`:
# A nominal type for modules. When set and non-null, this adds a check to
# make sure that only compatible modules are imported.
# This would be remove in the future, Prefer _module.args option instead.
class ? null
, args ? {}
, # This would be remove in the future, Prefer _module.args option instead.
args ? {}
, # This would be remove in the future, Prefer _module.check option instead.
check ? true
}:
@ -1256,7 +1256,78 @@ let
(opt.highestPrio or defaultOverridePriority)
(f opt.value);
doRename = { from, to, visible, warn, use, withPriority ? true, condition ? true }:
/*
Return a module that help declares an option that has been renamed.
When a value is defined for the old option, it is forwarded to the `to` option.
*/
doRename = {
# List of strings representing the attribute path of the old option.
from,
# List of strings representing the attribute path of the new option.
to,
# Boolean, whether the old option is to be included in documentation.
visible,
# Whether to warn when a value is defined for the old option.
# NOTE: This requires the NixOS assertions module to be imported, so
# - this generally does not work in submodules
# - this may or may not work outside NixOS
warn,
# A function that is applied to the option value, to form the value
# of the old `from` option.
#
# For example, the identity function can be passed, to return the option value unchanged.
# ```nix
# use = x: x;
# ```
#
# To add a warning, you can pass the partially applied `warn` function.
# ```nix
# use = lib.warn "Obsolete option `${opt.old}' is used. Use `${opt.to}' instead.";
# ```
use,
# Legacy option, enabled by default: whether to preserve the priority of definitions in `old`.
withPriority ? true,
# A boolean that defines the `mkIf` condition for `to`.
# If the condition evaluates to `true`, and the `to` path points into an
# `attrsOf (submodule ...)`, then `doRename` would cause an empty module to
# be created, even if the `from` option is undefined.
# By setting this to an expression that may return `false`, you can inhibit
# this undesired behavior.
#
# Example:
#
# ```nix
# { config, lib, ... }:
# let
# inherit (lib) mkOption mkEnableOption types doRename;
# in
# {
# options = {
#
# # Old service
# services.foo.enable = mkEnableOption "foo";
#
# # New multi-instance service
# services.foos = mkOption {
# type = types.attrsOf (types.submodule …);
# };
# };
# imports = [
# (doRename {
# from = [ "services" "foo" "bar" ];
# to = [ "services" "foos" "" "bar" ];
# visible = true;
# warn = false;
# use = x: x;
# withPriority = true;
# # Only define services.foos."" if needed. (It's not just about `bar`)
# condition = config.services.foo.enable;
# })
# ];
# }
# ```
condition ? true
}:
{ config, options, ... }:
let
fromOpt = getAttrFromPath from options;

View file

@ -254,12 +254,30 @@ rec {
else if all isInt list && all (x: x == head list) list then head list
else throw "Cannot merge definitions of `${showOption loc}'. Definition values:${showDefs defs}";
/*
Require a single definition.
WARNING: Does not perform nested checks, as this does not run the merge function!
*/
mergeOneOption = mergeUniqueOption { message = ""; };
mergeUniqueOption = { message }: loc: defs:
/*
Require a single definition.
NOTE: When the type is not checked completely by check, pass a merge function for further checking (of sub-attributes, etc).
*/
mergeUniqueOption = args@{
message,
# WARNING: the default merge function assumes that the definition is a valid (option) value. You MUST pass a merge function if the return value needs to be
# - type checked beyond what .check does (which should be very litte; only on the value head; not attribute values, etc)
# - if you want attribute values to be checked, or list items
# - if you want coercedTo-like behavior to work
merge ? loc: defs: (head defs).value }:
loc: defs:
if length defs == 1
then (head defs).value
else assert length defs > 1;
then merge loc defs
else
assert length defs > 1;
throw "The option `${showOption loc}' is defined multiple times while it's expected to be unique.\n${message}\nDefinition values:${showDefs defs}\n${prioritySuggestion}";
/* "Merge" option definitions by checking that they all have the same value. */
@ -379,7 +397,7 @@ rec {
if ! isString text then throw "literalExpression expects a string."
else { _type = "literalExpression"; inherit text; };
literalExample = lib.warn "literalExample is deprecated, use literalExpression instead, or use literalMD for a non-Nix description." literalExpression;
literalExample = lib.warn "lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description." literalExpression;
/* Transition marker for documentation that's already migrated to markdown
syntax. This is a no-op and no longer needed.

View file

@ -95,8 +95,7 @@ rec {
concatStringsSep "/" ["usr" "local" "bin"]
=> "usr/local/bin"
*/
concatStringsSep = builtins.concatStringsSep or (separator: list:
lib.foldl' (x: y: x + y) "" (intersperse separator list));
concatStringsSep = builtins.concatStringsSep;
/* Maps a function over a list of strings and then concatenates the
result with the specified separator interspersed between
@ -561,7 +560,7 @@ rec {
["&quot;" "&apos;" "&lt;" "&gt;" "&amp;"];
# warning added 12-12-2022
replaceChars = lib.warn "replaceChars is a deprecated alias of replaceStrings, replace usages of it with replaceStrings." builtins.replaceStrings;
replaceChars = lib.warn "lib.replaceChars is a deprecated alias of lib.replaceStrings." builtins.replaceStrings;
# Case conversion utilities.
lowerChars = stringToCharacters "abcdefghijklmnopqrstuvwxyz";
@ -1133,7 +1132,7 @@ rec {
"/prefix/nix-profiles-library-paths.patch"
"/prefix/compose-search-path.patch" ]
*/
readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead"
readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead."
(rootPath: file:
let
lines = lib.splitString "\n" (readFile file);

View file

@ -48,6 +48,7 @@ rec {
isRiscV64 = { cpu = { family = "riscv"; bits = 64; }; };
isRx = { cpu = { family = "rx"; }; };
isSparc = { cpu = { family = "sparc"; }; };
isSparc64 = { cpu = { family = "sparc"; bits = 64; }; };
isWasm = { cpu = { family = "wasm"; }; };
isMsp430 = { cpu = { family = "msp430"; }; };
isVc4 = { cpu = { family = "vc4"; }; };

View file

@ -407,6 +407,16 @@ checkConfigOutput "{}" config.submodule.a ./emptyValues.nix
checkConfigError 'The option .int.a. is used but not defined' config.int.a ./emptyValues.nix
checkConfigError 'The option .nonEmptyList.a. is used but not defined' config.nonEmptyList.a ./emptyValues.nix
# types.unique
# requires a single definition
checkConfigError 'The option .examples\.merged. is defined multiple times while it.s expected to be unique' config.examples.merged.a ./types-unique.nix
# user message is printed
checkConfigError 'We require a single definition, because seeing the whole value at once helps us maintain critical invariants of our system.' config.examples.merged.a ./types-unique.nix
# let the inner merge function check the values (on demand)
checkConfigError 'A definition for option .examples\.badLazyType\.a. is not of type .string.' config.examples.badLazyType.a ./types-unique.nix
# overriding still works (unlike option uniqueness)
checkConfigOutput '^"bee"$' config.examples.override.b ./types-unique.nix
## types.raw
checkConfigOutput '^true$' config.unprocessedNestingEvaluates.success ./raw.nix
checkConfigOutput "10" config.processedToplevel ./raw.nix

View file

@ -0,0 +1,27 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
options.examples = mkOption {
type = types.lazyAttrsOf
(types.unique
{ message = "We require a single definition, because seeing the whole value at once helps us maintain critical invariants of our system."; }
(types.attrsOf types.str));
};
imports = [
{ examples.merged = { b = "bee"; }; }
{ examples.override = lib.mkForce { b = "bee"; }; }
];
config.examples = {
merged = {
a = "aye";
};
override = {
a = "aye";
};
badLazyType = {
a = true;
};
};
}

View file

@ -9,60 +9,7 @@
let
lib = import ../.;
testWithNix = nix:
pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" {
buildInputs = [
(import ./check-eval.nix)
(import ./maintainers.nix {
inherit pkgs;
lib = import ../.;
})
(import ./teams.nix {
inherit pkgs;
lib = import ../.;
})
(import ../path/tests {
inherit pkgs;
})
];
nativeBuildInputs = [
nix
pkgs.gitMinimal
] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools;
strictDeps = true;
} ''
datadir="${nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
export HOME=$(mktemp -d)
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
cacheDir=$TEST_ROOT/binary-cache
nix-store --init
cp -r ${../.} lib
echo "Running lib/tests/modules.sh"
bash lib/tests/modules.sh
echo "Running lib/tests/filesystem.sh"
TEST_LIB=$PWD/lib bash lib/tests/filesystem.sh
echo "Running lib/tests/sources.sh"
TEST_LIB=$PWD/lib bash lib/tests/sources.sh
echo "Running lib/fileset/tests.sh"
TEST_LIB=$PWD/lib bash lib/fileset/tests.sh
echo "Running lib/tests/systems.nix"
[[ $(nix-instantiate --eval --strict lib/tests/systems.nix | tee /dev/stderr) == '[ ]' ]];
mkdir $out
echo success > $out/${nix.version}
'';
import ./test-with-nix.nix { inherit lib nix pkgs; };
in
pkgs.symlinkJoin {

View file

@ -0,0 +1,70 @@
/**
* Instantiate the library tests for a given Nix version.
*
* IMPORTANT:
* This is used by the github.com/NixOS/nix CI.
*
* Try not to change the interface of this file, or if you need to, ping the
* Nix maintainers for help. Thank you!
*/
{
pkgs,
lib,
# Only ever use this nix; see comment at top
nix,
}:
pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" {
buildInputs = [
(import ./check-eval.nix)
(import ./maintainers.nix {
inherit pkgs;
lib = import ../.;
})
(import ./teams.nix {
inherit pkgs;
lib = import ../.;
})
(import ../path/tests {
inherit pkgs;
})
];
nativeBuildInputs = [
nix
pkgs.gitMinimal
] ++ lib.optional pkgs.stdenv.isLinux pkgs.inotify-tools;
strictDeps = true;
} ''
datadir="${nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
export HOME=$(mktemp -d)
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
cacheDir=$TEST_ROOT/binary-cache
nix-store --init
cp -r ${../.} lib
echo "Running lib/tests/modules.sh"
bash lib/tests/modules.sh
echo "Running lib/tests/filesystem.sh"
TEST_LIB=$PWD/lib bash lib/tests/filesystem.sh
echo "Running lib/tests/sources.sh"
TEST_LIB=$PWD/lib bash lib/tests/sources.sh
echo "Running lib/fileset/tests.sh"
TEST_LIB=$PWD/lib bash lib/fileset/tests.sh
echo "Running lib/tests/systems.nix"
[[ $(nix-instantiate --eval --strict lib/tests/systems.nix | tee /dev/stderr) == '[ ]' ]];
mkdir $out
echo success > $out/${nix.version}
''

View file

@ -95,21 +95,6 @@ in {
/* boolean and */
and = x: y: x && y;
/* bitwise and */
bitAnd = builtins.bitAnd
or (import ./zip-int-bits.nix
(a: b: if a==1 && b==1 then 1 else 0));
/* bitwise or */
bitOr = builtins.bitOr
or (import ./zip-int-bits.nix
(a: b: if a==1 || b==1 then 1 else 0));
/* bitwise xor */
bitXor = builtins.bitXor
or (import ./zip-int-bits.nix
(a: b: if a!=b then 1 else 0));
/* bitwise not */
bitNot = builtins.sub (-1);
@ -165,8 +150,8 @@ in {
inherit (builtins)
pathExists readFile isBool
isInt isFloat add sub lessThan
seq deepSeq genericClosure;
seq deepSeq genericClosure
bitAnd bitOr bitXor;
## nixpkgs version strings
@ -230,7 +215,7 @@ in {
else if lib.pathExists revisionFile then lib.fileContents revisionFile
else default;
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
/* Determine whether the function is being called from inside a Nix
shell.

View file

@ -614,23 +614,12 @@ rec {
nestedTypes.elemType = elemType;
};
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
uniq = elemType: mkOptionType rec {
name = "uniq";
inherit (elemType) description descriptionClass check;
merge = mergeOneOption;
emptyValue = elemType.emptyValue;
getSubOptions = elemType.getSubOptions;
getSubModules = elemType.getSubModules;
substSubModules = m: uniq (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
uniq = unique { message = ""; };
unique = { message }: type: mkOptionType rec {
name = "unique";
inherit (type) description descriptionClass check;
merge = mergeUniqueOption { inherit message; };
merge = mergeUniqueOption { inherit message; inherit (type) merge; };
emptyValue = type.emptyValue;
getSubOptions = type.getSubOptions;
getSubModules = type.getSubModules;

View file

@ -9,7 +9,7 @@ rec {
splitVersion "1.2.3"
=> ["1" "2" "3"]
*/
splitVersion = builtins.splitVersion or (lib.splitString ".");
splitVersion = builtins.splitVersion;
/* Get the major version string from a string.

View file

@ -1,39 +0,0 @@
/* Helper function to implement a fallback for the bit operators
`bitAnd`, `bitOr` and `bitXor` on older nix version.
See ./trivial.nix
*/
f: x: y:
let
# (intToBits 6) -> [ 0 1 1 ]
intToBits = x:
if x == 0 || x == -1 then
[]
else
let
headbit = if (x / 2) * 2 != x then 1 else 0; # x & 1
tailbits = if x < 0 then ((x + 1) / 2) - 1 else x / 2; # x >> 1
in
[headbit] ++ (intToBits tailbits);
# (bitsToInt [ 0 1 1 ] 0) -> 6
# (bitsToInt [ 0 1 0 ] 1) -> -6
bitsToInt = l: signum:
if l == [] then
(if signum == 0 then 0 else -1)
else
(builtins.head l) + (2 * (bitsToInt (builtins.tail l) signum));
xsignum = if x < 0 then 1 else 0;
ysignum = if y < 0 then 1 else 0;
zipListsWith' = fst: snd:
if fst==[] && snd==[] then
[]
else if fst==[] then
[(f xsignum (builtins.head snd))] ++ (zipListsWith' [] (builtins.tail snd))
else if snd==[] then
[(f (builtins.head fst) ysignum )] ++ (zipListsWith' (builtins.tail fst) [] )
else
[(f (builtins.head fst) (builtins.head snd))] ++ (zipListsWith' (builtins.tail fst) (builtins.tail snd));
in
assert (builtins.isInt x) && (builtins.isInt y);
bitsToInt (zipListsWith' (intToBits x) (intToBits y)) (f xsignum ysignum)

View file

@ -203,6 +203,15 @@
fingerprint = "D292 365E 3C46 A5AA 75EE B30B 78DB 7EDE 3540 794B";
}];
};
_6543 = {
email = "6543@obermui.de";
github = "6543";
githubId = 24977596;
name = "6543";
keys = [{
fingerprint = "8722 B61D 7234 1082 553B 201C B8BE 6D61 0E61 C862";
}];
};
_6AA4FD = {
email = "f6442954@gmail.com";
github = "6AA4FD";
@ -241,6 +250,12 @@
fingerprint = "DBF4 E6D0 90B8 BEA4 4BFE 1F1C 3442 4321 39B5 0691";
}];
};
_9R = {
email = "nix@9-r.net";
github = "9R";
githubId = 381298;
name = "9R";
};
a1russell = {
email = "adamlr6+pub@gmail.com";
github = "a1russell";
@ -361,6 +376,12 @@
githubId = 13504599;
name = "Adam Boseley";
};
abueide = {
email = "andrea@abueide.com";
github = "abueide";
githubId = 19354425;
name = "Andrea Bueide";
};
abuibrahim = {
email = "ruslan@babayev.com";
github = "abuibrahim";
@ -373,6 +394,13 @@
githubId = 2526296;
name = "Adrien Bustany";
};
abysssol = {
name = "abysssol";
email = "abysssol@pm.me";
matrix = "@abysssol:tchncs.de";
github = "abysssol";
githubId = 76763323;
};
acairncross = {
email = "acairncross@gmail.com";
github = "acairncross";
@ -1724,6 +1752,12 @@
githubId = 113123021;
name = "Ashvith Shetty";
};
asininemonkey = {
email = "nixpkgs@asininemonkey.com";
github = "asininemonkey";
githubId = 65740649;
name = "Jose Cardoso";
};
aske = {
email = "aske@fmap.me";
github = "aske";
@ -1736,6 +1770,15 @@
githubId = 453170;
name = "Alastair Pharo";
};
aspulse = {
email = "contact@aspulse.dev";
github = "aspulse";
githubId = 84216737;
name = "AsPulse / ";
keys = [{
fingerprint = "C919 E69E A7C0 E147 9E0F C26E 1EDA D0C6 70BD 062D";
}];
};
astavie = {
email = "astavie@pm.me";
github = "astavie";
@ -1847,12 +1890,6 @@
github = "Atry";
githubId = 601530;
};
attila-lendvai = {
name = "Attila Lendvai";
email = "attila@lendvai.name";
github = "attila-lendvai";
githubId = 840345;
};
auchter = {
name = "Michael Auchter";
email = "a@phire.org";
@ -2238,6 +2275,12 @@
githubId = 24027;
name = "Bruno Bigras";
};
bbjubjub = {
name = "Julie B.";
email = "julie+nixpkgs@bbjubjub.fr";
github = "bbjubjub2494";
githubId = 15657735;
};
bburdette = {
email = "bburdette@protonmail.com";
github = "bburdette";
@ -2526,6 +2569,12 @@
githubId = 185443;
name = "Alexey Lebedeff";
};
binarycat = {
email = "binarycat@envs.net";
github = "lolbinarycat";
githubId = 19915050;
name = "binarycat";
};
binsky = {
email = "timo@binsky.org";
github = "binsky08";
@ -2958,7 +3007,7 @@
};
cafkafk = {
email = "christina@cafkafk.com";
matrix = "@cafkafk:nixos.dev";
matrix = "@cafkafk:gitter.im";
name = "Christina Sørensen";
github = "cafkafk";
githubId = 89321978;
@ -3204,6 +3253,13 @@
github = "cdmistman";
githubId = 23486351;
};
cdombroski = {
name = "Chris Dombroski";
email = "cdombroski@gmail.com";
matrix = "@cdombroski:kow.is";
github = "cdombroski";
githubId = 244909;
};
ceedubs = {
email = "ceedubs@gmail.com";
github = "ceedubs";
@ -3954,6 +4010,15 @@
githubId = 6821729;
github = "criyle";
};
croissong = {
email = "jan.moeller0@pm.me";
name = "Jan Möller";
github = "Croissong";
githubId = 4162215;
keys = [{
fingerprint = "CE97 9DEE 904C 26AA 3716 78C2 96A4 38F9 EE72 572F";
}];
};
crschnick = {
email = "crschnick@xpipe.io";
name = "Christopher Schnick";
@ -4082,6 +4147,12 @@
github = "D3vil0p3r";
githubId = 83867734;
};
d4ilyrun = {
name = "Léo Duboin";
email = "leo@duboin.com";
github = "d4ilyrun";
githubId = 34611103;
};
dadada = {
name = "dadada";
email = "dadada@dadada.li";
@ -4268,6 +4339,15 @@
githubId = 34766150;
name = "datafoo";
};
DataHearth = {
email = "dev@antoine-langlois.net";
github = "DataHearth";
githubId = 28595242;
name = "DataHearth";
keys = [{
fingerprint = "A129 2547 0298 BFEE 7EE0 92B3 946E 2D0C 410C 7B3D";
}];
};
davegallant = {
name = "Dave Gallant";
email = "davegallant@gmail.com";
@ -4371,6 +4451,18 @@
githubId = 49904992;
name = "Dawid Sowa";
};
dawoox = {
email = "contact@antoinebellanger.fr";
github = "dawoox";
githubId = 48325941;
name = "Dawoox";
};
daylinmorgan = {
email = "daylinmorgan@gmail.com";
github = "daylinmorgan";
githubId = 47667941;
name = "Daylin Morgan";
};
dbalan = {
email = "nix@dbalan.in";
github = "dbalan";
@ -4419,6 +4511,12 @@
githubId = 14032;
name = "Daniel Brockman";
};
DCsunset = {
email = "DCsunset@protonmail.com";
github = "DCsunset";
githubId = 23468812;
name = "DCsunset";
};
ddelabru = {
email = "ddelabru@redhat.com";
github = "ddelabru";
@ -4516,6 +4614,12 @@
githubId = 47436522;
name = "deliciouslytyped";
};
delliott = {
name = "Darragh Elliott";
github = "delliottxyz";
githubId = 150736012;
email = "me+git@delliott.xyz";
};
delroth = {
email = "delroth@gmail.com";
github = "delroth";
@ -4749,6 +4853,12 @@
githubId = 8404455;
name = "Diego Lelis";
};
diegs = {
email = "dpontor@gmail.com";
github = "diegs";
githubId = 74719;
name = "Diego Pontoriero";
};
DieracDelta = {
email = "justin@restivo.me";
github = "DieracDelta";
@ -4767,6 +4877,11 @@
githubId = 32810399;
name = "Diffumist";
};
DimitarNestorov = {
name = "Dimitar Nestorov";
github = "DimitarNestorov";
githubId = 8790386;
};
diogotcorreia = {
name = "Diogo Correia";
email = "me@diogotc.com";
@ -5266,6 +5381,12 @@
githubId = 7875;
name = "Rommel Martinez";
};
ecklf = {
email = "ecklf@icloud.com";
github = "ecklf";
githubId = 8146736;
name = "Florentin Eckl";
};
eclairevoyant = {
github = "eclairevoyant";
githubId = 848000;
@ -5693,6 +5814,13 @@
githubId = 8706;
name = "Rafael Fernández López";
};
erethon = {
email = "dgrig@erethon.com";
matrix = "@dgrig:erethon.com";
github = "erethon";
githubId = 1254842;
name = "Dionysis Grigoropoulos";
};
ericbmerritt = {
email = "eric@afiniate.com";
github = "ericbmerritt";
@ -5840,7 +5968,7 @@
};
etu = {
email = "elis@hirwing.se";
matrix = "@etu:semi.social";
matrix = "@etu:failar.nu";
github = "etu";
githubId = 461970;
name = "Elis Hirwing";
@ -5907,6 +6035,12 @@
githubId = 2512008;
name = "Even Brenden";
};
evey = {
email = "nix@lubdub.nl";
github = "lub-dub";
githubId = 159288204;
name = "evey";
};
evilmav = {
email = "elenskiy.ilya@gmail.com";
github = "evilmav";
@ -6250,6 +6384,13 @@
fingerprint = "2F93 661D AC17 EA98 A104 F780 ECC7 55EE 583C 1672";
}];
};
flandweber = {
email = "finn@landweber.xyz";
github = "flandweber";
githubId = 110117466;
matrix = "@flandweber:envs.net";
name = "Finn Landweber";
};
fleaz = {
email = "mail@felixbreidenstein.de";
matrix = "@fleaz:rainbownerds.de";
@ -6603,6 +6744,16 @@
githubId = 29337229;
name = "mtths";
};
fx-chun = {
email = "faye@lolc.at";
matrix = "@faye:lolc.at";
github = "fx-chun";
githubId = 40049608;
name = "Faye Chun";
keys = [{
fingerprint = "ACB8 DB1F E88D A908 6332 BDB1 5A71 B010 2FD7 3FC0";
}];
};
fxfactorial = {
email = "edgar.factorial@gmail.com";
github = "fxfactorial";
@ -6989,6 +7140,11 @@
githubId = 615606;
name = "Glenn Searby";
};
Gliczy = {
name = "Gliczy";
github = "Gliczy";
githubId = 129636582;
};
glittershark = {
name = "Griffin Smith";
email = "root@gws.fyi";
@ -7466,6 +7622,12 @@
githubId = 287769;
name = "Sergii Paryzhskyi";
};
heijligen = {
email = "src@posteo.de";
github = "heijligen";
githubId = 19170376;
name = "Thomas Heijligen";
};
heisfer = {
email = "heisfer@refract.dev";
github = "heisfer";
@ -8204,6 +8366,12 @@
fingerprint = "E864 BDFA AB55 36FD C905 5195 DBF2 52AF FB26 19FD";
}];
};
ironicbadger = {
email = "alexktz@gmail.com";
github = "ironicbadger";
githubId = 2773080;
name = "Alex Kretzschmar";
};
ironpinguin = {
email = "michele@catalano.de";
github = "ironpinguin";
@ -9162,6 +9330,12 @@
fingerprint = "7249 70E6 A661 D84E 8B47 678A 0590 93B1 A278 BCD0";
}];
};
jokatzke = {
email = "jokatzke@fastmail.com";
github = "jokatzke";
githubId = 46931073;
name = "Jonas Katzke";
};
joko = {
email = "ioannis.koutras@gmail.com";
github = "jokogr";
@ -9250,6 +9424,12 @@
github = "josephst";
githubId = 1269177;
};
josephsurin = {
name = "Joseph Surin";
email = "nix@jsur.in";
github = "josephsurin";
githubId = 14977484;
};
joshniemela = {
name = "Joshua Niemelä";
email = "josh@jniemela.dk";
@ -9418,6 +9598,16 @@
githubId = 5802758;
name = "Joshua Trees";
};
juancmuller = {
email = "nix@juancmuller.com";
githubId = 208500;
github = "jcmuller";
matrix = "@jcmuller@beeper.com";
name = "Juan C. Müller";
keys = [{
fingerprint = "D78D 25D8 A1B8 2596 267F 35B8 F44E A51A 28F9 B4A7";
}];
};
juaningan = {
email = "juaningan@gmail.com";
github = "oneingan";
@ -9797,6 +9987,9 @@
github = "kevincox";
githubId = 494012;
name = "Kevin Cox";
keys = [{
fingerprint = "B66B 891D D83B 0E67 7D84 FC30 9BB9 2CC1 552E 99AA";
}];
};
kevingriffin = {
email = "me@kevin.jp";
@ -10304,6 +10497,12 @@
githubId = 894884;
name = "Jakub Kozłowski";
};
kud = {
email = "kasa7qi@gmail.com";
github = "KUD-00";
githubId = 70764075;
name = "kud";
};
kupac = {
github = "Kupac";
githubId = 8224569;
@ -10751,6 +10950,12 @@
name = "Yanning Chen";
matrix = "@self:lightquantum.me";
};
Ligthiago = {
email = "donets.andre@gmail.com";
github = "Ligthiago";
githubId = 142721811;
name = "Andrey Donets";
};
lihop = {
email = "nixos@leroy.geek.nz";
github = "lihop";
@ -10840,6 +11045,12 @@
githubId = 591860;
name = "Lionello Lunesu";
};
litchipi = {
email = "litchi.pi@proton.me";
github = "litchipi";
githubId = 61109829;
name = "Litchi Pi";
};
livnev = {
email = "lev@liv.nev.org.uk";
github = "livnev";
@ -10984,15 +11195,6 @@
githubId = 4969294;
name = "Louis Tim Larsen";
};
lourkeur = {
name = "Louis Bettens";
email = "louis@bettens.info";
github = "lourkeur";
githubId = 15657735;
keys = [{
fingerprint = "5B93 9CFA E8FC 4D8F E07A 3AEA DFE1 D4A0 1733 7E2A";
}];
};
loveisgrief = {
name = "LoveIsGrief";
email = "loveisgrief@tuta.io";
@ -11083,6 +11285,12 @@
githubId = 35580196;
name = "Luca Guerra";
};
lucasbergman = {
email = "lucas@bergmans.us";
github = "lucasbergman";
githubId = 3717454;
name = "Lucas Bergman";
};
lucasew = {
email = "lucas59356@gmail.com";
github = "lucasew";
@ -11662,12 +11870,6 @@
githubId = 1729331;
name = "Dominique Martinet";
};
martingms = {
email = "martin@mg.am";
github = "martingms";
githubId = 458783;
name = "Martin Gammelsæter";
};
martinjlowm = {
email = "martin@martinjlowm.dk";
github = "martinjlowm";
@ -12819,6 +13021,16 @@
githubId = 10601196;
name = "Jérémie Ferry";
};
motiejus = {
email = "motiejus@jakstys.lt";
github = "motiejus";
githubId = 107720;
keys = [{
fingerprint = "5F6B 7A8A 92A2 60A4 3704 9BEB 6F13 3A0C 1C28 48D7";
}];
matrix = "@motiejus:jakstys.lt";
name = "Motiejus Jakštys";
};
mounium = {
email = "muoniurn@gmail.com";
github = "Mounium";
@ -13773,13 +13985,6 @@
githubId = 47303199;
name = "Simon Gutgesell";
};
noneucat = {
email = "andy@lolc.at";
matrix = "@noneucat:lolc.at";
github = "noneucat";
githubId = 40049608;
name = "Andy Chun";
};
noodlez1232 = {
email = "contact@nathanielbarragan.xyz";
matrix = "@noodlez1232:matrix.org";
@ -13963,6 +14168,12 @@
github = "numkem";
githubId = 332423;
};
nu-nu-ko = {
email = "host@nuko.city";
github = "nu-nu-ko";
githubId = 153512689;
name = "nuko";
};
nviets = {
email = "nathan.g.viets@gmail.com";
github = "nviets";
@ -14505,6 +14716,12 @@
githubId = 72527881;
name = "PassiveLemon";
};
patka = {
email = "patka@patka.dev";
github = "patka-123";
githubId = 69802930;
name = "patka";
};
patricksjackson = {
email = "patrick@jackson.dev";
github = "patricksjackson";
@ -14768,6 +14985,12 @@
fingerprint = "3AC6 F170 F011 33CE 393B CD94 BE94 8AFD 7E78 73BE";
}];
};
phijor = {
name = "Philipp Joram";
email = "nixpkgs@phijor.me";
github = "phijor";
githubId = 10487782;
};
philandstuff = {
email = "philip.g.potter@gmail.com";
github = "philandstuff";
@ -15643,6 +15866,12 @@
github = "rafaelrc7";
githubId = 5376043;
};
rafameou = {
email = "rafaelmazz22@gmail.com";
name = "Rafael Mazzutti";
github = "rafameou";
githubId = 26395874;
};
ragge = {
email = "r.dahlen@gmail.com";
github = "ragnard";
@ -15740,6 +15969,12 @@
githubId = 11351304;
name = "Ricardo Ardissone";
};
raroh73 = {
email = "me@raroh73.com";
github = "Raroh73";
githubId = 96078496;
name = "Raroh73";
};
rasendubi = {
email = "rasen.dubi@gmail.com";
github = "rasendubi";
@ -15752,6 +15987,12 @@
githubId = 1891350;
name = "Michael Raskin";
};
raspher = {
email = "raspher@protonmail.com";
github = "raspher";
githubId = 23345803;
name = "Szymon Scholz";
};
ratcornu = {
email = "ratcornu@skaven.org";
github = "RatCornu";
@ -15980,7 +16221,7 @@
};
RGBCube = {
name = "RGBCube";
email = "rgbsphere+nixpkgs@gmail.com";
email = "nixpkgs@rgbcu.be";
github = "RGBCube";
githubId = 78925721;
keys = [{
@ -16344,6 +16585,12 @@
github = "RossComputerGuy";
githubId = 19699320;
};
rostan-t = {
name = "Rostan Tabet";
email = "rostan.tabet@gmail.com";
github = "rostan-t";
githubId = 30502549;
};
rotaerk = {
name = "Matthew Stewart";
email = "m.scott.stewart@gmail.com";
@ -16449,6 +16696,18 @@
github = "rubyowo";
githubId = 105302757;
};
rucadi = {
email = "ruben.canodiaz@gmail.com";
github = "rucadi";
githubId = 6445619;
name = "Ruben Cano Diaz";
};
RudiOnTheAir = {
name = "Rüdiger Schwoon";
email = "wolf@schwoon.info";
github = "RudiOnTheAir";
githubId = 47517341;
};
rudolfvesely = {
name = "Rudolf Vesely";
email = "i@rudolfvesely.com";
@ -16652,6 +16911,12 @@
github = "samalws";
githubId = 20981725;
};
samasaur = {
name = "Samasaur";
email = "sam@samasaur.com";
github = "Samasaur1";
githubId = 30577766;
};
samb96 = {
email = "samb96@gmail.com";
github = "samb96";
@ -16931,6 +17196,12 @@
fingerprint = "E173 237A C782 296D 98F5 ADAC E13D FD4B 4712 7951";
}];
};
sdht0 = {
email = "nixpkgs@sdht.in";
github = "sdht0";
githubId = 867424;
name = "Siddhartha Sahu";
};
sdier = {
email = "scott@dier.name";
matrix = "@sdier:matrix.org";
@ -17024,6 +17295,12 @@
githubId = 1286668;
name = "Thilo Uttendorfer";
};
sentientmonkey = {
email = "swindsor@gmail.com";
github = "sentientmonkey";
githubId = 9032;
name = "Scott Windsor";
};
sents = {
email = "finn@krein.moe";
github = "sents";
@ -17345,6 +17622,12 @@
github = "shymega";
githubId = 1334592;
};
siddarthkay = {
email = "siddarthkay@gmail.com";
github = "siddarthkay";
githubId = 64726664;
name = "Siddarth Kumar";
};
siddharthdhakane = {
email = "siddharthdhakane@gmail.com";
github = "siddharthdhakane";
@ -18215,6 +18498,13 @@
githubId = 2666479;
name = "Y Nguyen";
};
superherointj = {
email = "sergiomarcelo@yandex.com";
github = "superherointj";
githubId = 5861043;
matrix = "@superherointj:matrix.org";
name = "Sérgio Marcelo";
};
SuperSandro2000 = {
email = "sandro.jaeckel@gmail.com";
matrix = "@sandro:supersandro.de";
@ -18481,6 +18771,12 @@
githubId = 11619234;
name = "Sergey Volkov";
};
tarantoj = {
email = "taranto.james@gmail.com";
github = "tarantoj";
githubId = 13129552;
name = "James Taranto";
};
tari = {
email = "peter@taricorp.net";
github = "tari";
@ -19993,6 +20289,12 @@
githubId = 326263;
name = "Danny Wilson";
};
vizid = {
email = "vizid1337@gmail.com";
github = "ViZiD";
githubId = 7444430;
name = "Radik Islamov";
};
vklquevs = {
email = "vklquevs@gmail.com";
github = "vklquevs";
@ -20643,6 +20945,13 @@
githubId = 31734358;
name = "Xavier Groleau";
};
xgwq = {
name = "XGWQ";
email = "nixos@xnee.de";
matrix = "@xgwq:nerdberg.de";
github = "peterablehmann";
githubId = 36541313;
};
xiorcale = {
email = "quentin.vaucher@pm.me";
github = "xiorcale";

View file

@ -39,7 +39,7 @@ target:
```
To validate cross-targets `binfmt` `NixOS` helper can be useful.
For `riscv64-unknown-linux-gnu` the `/etc/nixox/configuraqtion.nix`
For `riscv64-unknown-linux-gnu` the `/etc/nixos/configuration.nix`
entry would be `boot.binfmt.emulatedSystems = [ "riscv64-linux" ]`.
3. Propose the commit as a PR to update bootstrap tarballs, tag people

View file

@ -0,0 +1,31 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnutar jq reuse
set -eu
cd "$(dirname "$(readlink -f "$0")")"/../../..
TMPDIR=$(mktemp -d)
trap 'rm -rf $TMPDIR' EXIT
echo "# Prebuilding sources..."
nix-build -A kdePackages.sources --no-link || true
echo "# Evaluating sources..."
declare -A sources
eval "$(nix-instantiate --eval -A kdePackages.sources --json --strict | jq 'to_entries[] | "sources[" + .key + "]=" + .value' -r)"
echo "# Collecting licenses..."
for k in "${!sources[@]}"; do
echo "- Processing $k..."
if [ ! -f "${sources[$k]}" ]; then
echo "Not found!"
continue
fi
mkdir "$TMPDIR/$k"
tar -C "$TMPDIR/$k" -xf "${sources[$k]}"
(cd "$TMPDIR/$k"; reuse lint --json) | jq --arg name "$k" '{$name: .summary.used_licenses | sort}' -c > "$TMPDIR/$k.json"
done
jq -s 'add' -S "$TMPDIR"/*.json > pkgs/kde/generated/licenses.json

View file

@ -0,0 +1,11 @@
#!/usr/bin/env nix-shell
#!nix-shell -i nu -p nushell
cd $"($env.FILE_PWD)/../../.."
mkdir logs
nix-env -qaP -f . -A kdePackages --json --out-path | from json | values | par-each { |it|
echo $"Processing ($it.pname)..."
if "outputs" in $it {
nix-store --read-log $it.outputs.out | save -f $"logs/($it.pname).log"
}
}

View file

@ -0,0 +1,36 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages(ps: [ ps.click ps.pyyaml ])"
import pathlib
import click
import utils
@click.command
@click.argument(
"repo-metadata",
type=click.Path(
exists=True,
file_okay=False,
resolve_path=True,
path_type=pathlib.Path,
),
)
@click.option(
"--nixpkgs",
type=click.Path(
exists=True,
file_okay=False,
resolve_path=True,
writable=True,
path_type=pathlib.Path,
),
default=pathlib.Path(__file__).parent.parent.parent.parent
)
def main(repo_metadata: pathlib.Path, nixpkgs: pathlib.Path):
metadata = utils.KDERepoMetadata.from_repo_metadata_checkout(repo_metadata)
out_dir = nixpkgs / "pkgs/kde/generated"
metadata.write_json(out_dir)
if __name__ == "__main__":
main() # type: ignore

View file

@ -0,0 +1,127 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3
import pathlib
OK_MISSING = {
# we don't use precompiled QML
'Qt6QuickCompiler',
'Qt6QmlCompilerPlusPrivate',
# usually used for version numbers
'Git',
# useless by itself, will warn if something else is not found
'PkgConfig',
# license verification
'ReuseTool',
# dev only
'ClangFormat',
# doesn't exist
'Qt6X11Extras',
}
OK_MISSING_BY_PACKAGE = {
"angelfish": {
"Qt6Feedback", # we don't have it
},
"attica": {
"Python3", # only used for license checks
},
"discover": {
"rpm-ostree-1", # we don't have rpm-ostree (duh)
"Snapd", # we don't have snaps and probably never will
},
"elisa": {
"UPNPQT", # upstream says it's broken
},
"extra-cmake-modules": {
"Sphinx", # only used for docs, bloats closure size
"QCollectionGenerator"
},
"kio-extras-kf5": {
"KDSoapWSDiscoveryClient", # actually vendored on KF5 version
},
"kitinerary": {
"OsmTools", # used for map data updates, we use prebuilt
},
"kosmindoormap": {
"OsmTools", # same
"Protobuf",
},
"kpty": {
"UTEMPTER", # we don't have it and it probably wouldn't work anyway
},
"kpublictransport": {
"OsmTools", # same
"PolyClipping",
"Protobuf",
},
"krfb": {
"Qt6XkbCommonSupport", # not real
},
"kuserfeedback": {
"Qt6Svg", # all used for backend console stuff we don't ship
"QmlLint",
"Qt6Charts",
"FLEX",
"BISON",
"Php",
"PhpUnit",
},
"kwin": {
"display-info", # newer versions identify as libdisplay-info
},
"mlt": {
"Qt5", # intentionally disabled
"SWIG",
},
"plasma-desktop": {
"scim", # upstream is dead, not packaged in Nixpkgs
},
"powerdevil": {
"DDCUtil", # cursed, intentionally disabled
},
"pulseaudio-qt": {
"Qt6Qml", # tests only
"Qt6Quick",
},
"syntax-highlighting": {
"XercesC", # only used for extra validation at build time
}
}
def main():
here = pathlib.Path(__file__).parent.parent.parent.parent
logs = (here / "logs").glob("*.log")
for log in sorted(logs):
pname = log.stem
missing = []
is_in_block = False
with log.open(errors="replace") as fd:
for line in fd:
line = line.strip()
if line.startswith("-- No package '"):
package = line.removeprefix("-- No package '").removesuffix("' found")
missing.append(package)
if line == "-- The following OPTIONAL packages have not been found:" or line == "-- The following RECOMMENDED packages have not been found:":
is_in_block = True
elif line.startswith("--") and is_in_block:
is_in_block = False
elif line.startswith("*") and is_in_block:
package = line.removeprefix("* ")
missing.append(package)
missing = {
package
for package in missing
if not any(package.startswith(i) for i in OK_MISSING | OK_MISSING_BY_PACKAGE.get(pname, set()))
}
if missing:
print(pname + ":")
for line in missing:
print(" -", line)
print()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,113 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages(ps: [ ps.beautifulsoup4 ps.click ps.httpx ps.jinja2 ps.pyyaml ])
import base64
import binascii
import json
import pathlib
from urllib.parse import urlparse
import bs4
import click
import httpx
import jinja2
import utils
LEAF_TEMPLATE = jinja2.Template('''
{mkKdeDerivation}:
mkKdeDerivation {
pname = "{{ pname }}";
}
'''.strip())
ROOT_TEMPLATE = jinja2.Template('''
{callPackage}: {
{%- for p in packages %}
{{ p }} = callPackage ./{{ p }} {};
{%- endfor %}
}
'''.strip());
def to_sri(hash):
raw = binascii.unhexlify(hash)
b64 = base64.b64encode(raw).decode()
return f"sha256-{b64}"
@click.command
@click.argument(
"set",
type=click.Choice(["frameworks", "gear", "plasma"]),
required=True
)
@click.argument(
"version",
type=str,
required=True
)
@click.option(
"--nixpkgs",
type=click.Path(
exists=True,
file_okay=False,
resolve_path=True,
writable=True,
path_type=pathlib.Path,
),
default=pathlib.Path(__file__).parent.parent.parent.parent
)
def main(set: str, version: str, nixpkgs: pathlib.Path):
root_dir = nixpkgs / "pkgs/kde"
set_dir = root_dir / set
generated_dir = root_dir / "generated"
metadata = utils.KDERepoMetadata.from_json(generated_dir)
set_url = {
"frameworks": "kf",
"gear": "releases",
"plasma": "plasma",
}[set]
sources = httpx.get(f"https://kde.org/info/sources/source-{set_url}-{version}.html")
sources.raise_for_status()
bs = bs4.BeautifulSoup(sources.text, features="html.parser")
results = {}
for item in bs.select("tr")[1:]:
link = item.select_one("td:nth-child(1) a")
assert link
hash = item.select_one("td:nth-child(3) tt")
assert hash
project_name, version = link.text.rsplit("-", maxsplit=1)
if project_name not in metadata.projects_by_name:
print(f"Warning: unknown tarball: {project_name}")
results[project_name] = {
"version": version,
"url": "mirror://kde" + urlparse(link.attrs["href"]).path,
"hash": to_sri(hash.text)
}
pkg_dir = set_dir / project_name
pkg_file = pkg_dir / "default.nix"
if not pkg_file.exists():
print(f"Generated new package: {set}/{project_name}")
pkg_dir.mkdir(parents=True, exist_ok=True)
with pkg_file.open("w") as fd:
fd.write(LEAF_TEMPLATE.render(pname=project_name) + "\n")
set_dir.mkdir(parents=True, exist_ok=True)
with (set_dir / "default.nix").open("w") as fd:
fd.write(ROOT_TEMPLATE.render(packages=results.keys()) + "\n")
sources_dir = generated_dir / "sources"
sources_dir.mkdir(parents=True, exist_ok=True)
with (sources_dir / f"{set}.json").open("w") as fd:
json.dump(results, fd, indent=2)
if __name__ == "__main__":
main() # type: ignore

View file

@ -0,0 +1,185 @@
import collections
import dataclasses
import functools
import json
import pathlib
import subprocess
import yaml
class DataclassEncoder(json.JSONEncoder):
def default(self, it):
if dataclasses.is_dataclass(it):
return dataclasses.asdict(it)
return super().default(it)
@dataclasses.dataclass
class Project:
name: str
description: str | None
project_path: str
repo_path: str | None
def __hash__(self) -> int:
return hash(self.name)
@classmethod
def from_yaml(cls, path: pathlib.Path):
data = yaml.safe_load(path.open())
return cls(
name=data["identifier"],
description=data["description"],
project_path=data["projectpath"],
repo_path=data["repopath"]
)
def get_git_commit(path: pathlib.Path):
return subprocess.check_output(["git", "-C", path, "rev-parse", "--short", "HEAD"]).decode().strip()
def validate_unique(projects: list[Project], attr: str):
seen = set()
for item in projects:
attr_value = getattr(item, attr)
if attr_value in seen:
raise Exception(f"Duplicate {attr}: {attr_value}")
seen.add(attr_value)
THIRD_PARTY = {
"third-party/appstream": "appstream-qt",
"third-party/cmark": "cmark",
"third-party/gpgme": "gpgme",
"third-party/kdsoap": "kdsoap",
"third-party/libaccounts-qt": "accounts-qt",
"third-party/libgpg-error": "libgpg-error",
"third-party/libquotient": "libquotient",
"third-party/packagekit-qt": "packagekit-qt",
"third-party/poppler": "poppler",
"third-party/qcoro": "qcoro",
"third-party/qmltermwidget": "qmltermwidget",
"third-party/qtkeychain": "qtkeychain",
"third-party/signond": "signond",
"third-party/taglib": "taglib",
"third-party/wayland-protocols": "wayland-protocols",
"third-party/wayland": "wayland",
"third-party/zxing-cpp": "zxing-cpp",
}
IGNORE = {
"kdesupport/phonon-directshow",
"kdesupport/phonon-mmf",
"kdesupport/phonon-mplayer",
"kdesupport/phonon-quicktime",
"kdesupport/phonon-waveout",
"kdesupport/phonon-xine"
}
WARNED = set()
@dataclasses.dataclass
class KDERepoMetadata:
version: str
projects: list[Project]
dep_graph: dict[Project, set[Project]]
@functools.cached_property
def projects_by_name(self):
return {p.name: p for p in self.projects}
@functools.cached_property
def projects_by_path(self):
return {p.project_path: p for p in self.projects}
def try_lookup_package(self, path):
if path in IGNORE:
return None
project = self.projects_by_path.get(path)
if project is None and path not in WARNED:
WARNED.add(path)
print(f"Warning: unknown project {path}")
return project
@classmethod
def from_repo_metadata_checkout(cls, repo_metadata: pathlib.Path):
projects = [
Project.from_yaml(metadata_file)
for metadata_file in repo_metadata.glob("projects-invent/**/metadata.yaml")
] + [
Project(id, None, project_path, None)
for project_path, id in THIRD_PARTY.items()
]
validate_unique(projects, "name")
validate_unique(projects, "project_path")
self = cls(
version=get_git_commit(repo_metadata),
projects=projects,
dep_graph={},
)
dep_specs = [
"dependency-data-common",
"dependency-data-kf6-qt6"
]
dep_graph = collections.defaultdict(set)
for spec in dep_specs:
spec_path = repo_metadata / "dependencies" / spec
for line in spec_path.open():
line = line.strip()
if line.startswith("#"):
continue
if not line:
continue
dependent, dependency = line.split(": ")
dependent = self.try_lookup_package(dependent)
if dependent is None:
continue
dependency = self.try_lookup_package(dependency)
if dependency is None:
continue
dep_graph[dependent].add(dependency)
self.dep_graph = dep_graph
return self
def write_json(self, root: pathlib.Path):
root.mkdir(parents=True, exist_ok=True)
with (root / "projects.json").open("w") as fd:
json.dump(self.projects_by_name, fd, cls=DataclassEncoder, sort_keys=True, indent=2)
with (root / "dependencies.json").open("w") as fd:
deps = {k.name: sorted(dep.name for dep in v) for k, v in self.dep_graph.items()}
json.dump({"version": self.version, "dependencies": deps}, fd, cls=DataclassEncoder, sort_keys=True, indent=2)
@classmethod
def from_json(cls, root: pathlib.Path):
projects = [
Project(**v) for v in json.load((root / "projects.json").open()).values()
]
deps = json.load((root / "dependencies.json").open())
self = cls(
version=deps["version"],
projects=projects,
dep_graph={},
)
dep_graph = collections.defaultdict(set)
for dependent, dependencies in deps["dependencies"].items():
for dependency in dependencies:
dep_graph[self.projects_by_name[dependent]].add(self.projects_by_name[dependency])
self.dep_graph = dep_graph
return self

View file

@ -176,7 +176,7 @@ with lib.maintainers; {
cosmopolitan = {
members = [
lourkeur
bbjubjub
tomberek
];
scope = "Maintain the Cosmopolitan LibC and related programs.";
@ -339,11 +339,9 @@ with lib.maintainers; {
geospatial = {
members = [
das-g
imincik
nh2
nialov
r-burns
sikmir
willcohen
];
@ -776,7 +774,6 @@ with lib.maintainers; {
members = [
aanderse
drupol
etu
ma27
talyz
];
@ -822,12 +819,18 @@ with lib.maintainers; {
qt-kde = {
members = [
ilya-fedin
k900
LunNova
mjm
nickcao
SuperSandro2000
ttuegel
];
githubTeams = [
"qt-kde"
];
scope = "Maintain the KDE desktop environment and Qt.";
scope = "Maintain the Qt framework, KDE application suite, Plasma desktop environment and related projects.";
shortName = "Qt / KDE";
enableFeatureFreezePing = true;
};

View file

@ -39,4 +39,5 @@ and non-critical by adding `options = [ "nofail" ];`.
```{=include=} sections
luks-file-systems.section.md
sshfs-file-systems.section.md
overlayfs.section.md
```

View file

@ -0,0 +1,27 @@
# Overlayfs {#sec-overlayfs}
NixOS offers a convenient abstraction to create both read-only as well writable
overlays.
```nix
fileSystems = {
"/writable-overlay" = {
overlay = {
lowerdir = [ writableOverlayLowerdir ];
upperdir = "/.rw-writable-overlay/upper";
workdir = "/.rw-writable-overlay/work";
};
# Mount the writable overlay in the initrd.
neededForBoot = true;
};
"/readonly-overlay".overlay.lowerdir = [
writableOverlayLowerdir
writableOverlayLowerdir2
];
};
```
If `upperdir` and `workdir` are not null, they will be created before the
overlay is mounted.
To mount an overlay as read-only, you need to provide at least two `lowerdir`s.

View file

@ -326,7 +326,7 @@ Composed types are types that take a type as parameter. `listOf
`types.uniq` *`t`*
: Ensures that type *`t`* cannot be merged. It is used to ensure option
definitions are declared only once.
definitions are provided only once.
`types.unique` `{ message = m }` *`t`*

View file

@ -73,6 +73,34 @@ have a predefined type and string generator already declared under
It returns a set with INI-specific attributes `type` and `generate`
as specified [below](#pkgs-formats-result).
The type of the input is an *attrset* of sections; key-value pairs where
the key is the section name and the value is the corresponding content
which is also an *attrset* of key-value pairs for the actual key-value
mappings of the INI format.
The values of the INI atoms are subject to the above parameters (e.g. lists
may be transformed into multiple key-value pairs depending on
`listToValue`).
`pkgs.formats.iniWithGlobalSection` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \.\.\. }
: A function taking an attribute set with values
`listsAsDuplicateKeys`
: A boolean for controlling whether list values can be used to
represent duplicate INI keys
`listToValue`
: A function for turning a list of values into a single value.
It returns a set with INI-specific attributes `type` and `generate`
as specified [below](#pkgs-formats-result).
The type of the input is an *attrset* of the structure
`{ sections = {}; globalSection = {}; }` where *sections* are several
sections as with *pkgs.formats.ini* and *globalSection* being just a single
attrset of key-value pairs for a single section, the global section which
preceedes the section definitions.
`pkgs.formats.toml` { }

View file

@ -75,9 +75,10 @@ image with a new one or by updating partitions via an A/B scheme. See the
[Chrome OS update process][chrome-os-update] for an example of how to achieve
this. The appliance image built in the following example does not contain a
`configuration.nix` and thus you will not be able to call `nixos-rebuild` from
this system.
this system. Furthermore, it uses a [Unified Kernel Image][unified-kernel-image].
[chrome-os-update]: https://chromium.googlesource.com/aosp/platform/system/update_engine/+/HEAD/README.md
[unified-kernel-image]: https://uapi-group.org/specifications/specs/unified_kernel_image/
```nix
let
@ -101,18 +102,8 @@ in
"/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
"${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
"/loader/entries/nixos.conf".source = pkgs.writeText "nixos.conf" ''
title NixOS
linux /EFI/nixos/kernel.efi
initrd /EFI/nixos/initrd.efi
options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
'';
"/EFI/nixos/kernel.efi".source =
"${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
"/EFI/nixos/initrd.efi".source =
"${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
"/EFI/Linux/${config.system.boot.loader.ukiFile}".source =
"${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
};
repartConfig = {
Type = "esp";

View file

@ -8,19 +8,37 @@ In addition to numerous new and upgraded packages, this release has the followin
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
- `cryptsetup` has been upgraded from 2.6.1 to 2.7.0. Cryptsetup is a critical component enabling LUKS-based (but not only) full disk encryption.
Take the time to review [the release notes](https://gitlab.com/cryptsetup/cryptsetup/-/raw/v2.7.0/docs/v2.7.0-ReleaseNotes).
One of the highlight is that it is now possible to use hardware OPAL-based encryption of your disk with `cryptsetup`, it has a lot of caveats, see the above notes for the full details.
- `screen`'s module has been cleaned, and will now require you to set `programs.screen.enable` in order to populate `screenrc` and add the program to the environment.
- `linuxPackages_testing_bcachefs` is now fully deprecated by `linuxPackages_latest`, and is therefore no longer available.
- The default kernel package has been updated from 6.1 to 6.6. All supported kernels remain available.
- NixOS now installs a stub ELF loader that prints an informative error message when users attempt to run binaries not made for NixOS.
- This can be disabled through the `environment.stub-ld.enable` option.
- If you use `programs.nix-ld.enable`, no changes are needed. The stub will be disabled automatically.
- On flake-based NixOS configurations using `nixpkgs.lib.nixosSystem`, NixOS will automatically set `NIX_PATH` and the system-wide flake registry (`/etc/nix/registry.json`) to point `<nixpkgs>` and the unqualified flake path `nixpkgs` to the version of nixpkgs used to build the system.
This makes `nix run nixpkgs#hello` and `nix-build '<nixpkgs>' -A hello` work out of the box with no added configuration, reusing dependencies already on the system.
This may be undesirable if nix commands are not going to be run on the built system since it adds nixpkgs to the system closure. For such closure-size-constrained non-interactive systems, this setting should be disabled.
To disable this, set [nixpkgs.flake.setNixPath](#opt-nixpkgs.flake.setNixPath) and [nixpkgs.flake.setFlakeRegistry](#opt-nixpkgs.flake.setFlakeRegistry) to false.
- Julia environments can now be built with arbitrary packages from the ecosystem using the `.withPackages` function. For example: `julia.withPackages ["Plots"]`.
- A new option `systemd.sysusers.enable` was added. If enabled, users and
groups are created with systemd-sysusers instead of with a custom perl script.
- A new option `virtualisation.containers.cdi` was added. It contains `static` and `dynamic` attributes (corresponding to `/etc/cdi` and `/run/cdi` respectively) to configure the Container Device Interface (CDI).
- `virtualisation.docker.enableNvidia` and `virtualisation.podman.enableNvidia` options are deprecated. `virtualisation.containers.cdi.dynamic.nvidia.enable` should be used instead. This option will expose GPUs on containers with the `--device` CLI option. This is supported by Docker 25, Podman 3.2.0 and Singularity 4. Any container runtime that supports the CDI specification will take advantage of this feature.
- A new option `system.etc.overlay.enable` was added. If enabled, `/etc` is
mounted via an overlayfs instead of being created by a custom perl script.
@ -34,6 +52,8 @@ In addition to numerous new and upgraded packages, this release has the followin
}
```
- Plasma 6 is now available and can be installed with `services.xserver.desktopManager.plasma6.enable = true;`. Plasma 5 will likely be deprecated in the next release (24.11). Note that Plasma 6 runs as Wayland by default, and the X11 session needs to be explicitly selected if necessary.
## New Services {#sec-release-24.05-new-services}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
@ -67,6 +87,10 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- [TigerBeetle](https://tigerbeetle.com/), a distributed financial accounting database designed for mission critical safety and performance. Available as [services.tigerbeetle](#opt-services.tigerbeetle.enable).
- [go-camo](https://github.com/cactus/go-camo), a secure image proxy server. Available as [services.go-camo](#opt-services.go-camo.enable).
- [Monado](https://monado.freedesktop.org/), an open source XR runtime. Available as [services.monado](#opt-services.monado.enable).
- [Clevis](https://github.com/latchset/clevis), a pluggable framework for automated decryption, used to unlock encrypted devices in initrd. Available as [boot.initrd.clevis.enable](#opt-boot.initrd.clevis.enable).
- [TuxClocker](https://github.com/Lurkki14/tuxclocker), a hardware control and monitoring program. Available as [programs.tuxclocker](#opt-programs.tuxclocker.enable).
@ -75,13 +99,17 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- [RustDesk](https://rustdesk.com), a full-featured open source remote control alternative for self-hosting and security with minimal configuration. Alternative to TeamViewer.
- [Scrutiny](https://github.com/AnalogJ/scrutiny), a S.M.A.R.T monitoring tool for hard disks with a web frontend.
- [systemd-lock-handler](https://git.sr.ht/~whynothugo/systemd-lock-handler/), a bridge between logind D-Bus events and systemd targets. Available as [services.systemd-lock-handler.enable](#opt-services.systemd-lock-handler.enable).
- [Mealie](https://nightly.mealie.io/), a self-hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in NuxtJS for a pleasant user experience for the whole family. Available as [services.mealie](#opt-services.mealie.enable)
## Backward Incompatibilities {#sec-release-24.05-incompatibilities}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
- `himalaya` was updated to v1.0.0-beta, which introduces breaking changes. Check out the [release note](https://github.com/soywod/himalaya/releases/tag/v1.0.0-beta) for details.
- `himalaya` was updated to `v1.0.0-beta.3`, which introduces breaking changes. Check out the [release note](https://github.com/soywod/himalaya/releases/tag/v1.0.0-beta.3) for details.
- The `power.ups` module now generates `upsd.conf`, `upsd.users` and `upsmon.conf` automatically from a set of new configuration options. This breaks compatibility with existing `power.ups` setups where these files were created manually. Back up these files before upgrading NixOS.
@ -99,6 +127,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- `nitter` requires a `guest_accounts.jsonl` to be provided as a path or loaded into the default location at `/var/lib/nitter/guest_accounts.jsonl`. See [Guest Account Branch Deployment](https://github.com/zedeus/nitter/wiki/Guest-Account-Branch-Deployment) for details.
- `boot.supportedFilesystems` and `boot.initrd.supportedFilesystems` are now attribute sets instead of lists. Assignment from lists as done previously is still supported, but checking whether a filesystem is enabled must now by done using `supportedFilesystems.fs or false` instead of using `lib.elem "fs" supportedFilesystems` as was done previously.
- `services.aria2.rpcSecret` has been replaced with `services.aria2.rpcSecretFile`.
This was done so that secrets aren't stored in the world-readable nix store.
To migrate, you will have create a file with the same exact string, and change
@ -149,6 +179,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- The bundled Lua was updated to Lua v5.2, which includes breaking changes. See the [Lua manual](https://www.lua.org/manual/5.2/manual.html#8) for more information.
- The WebSocket API [was rewritten](https://github.com/MCJack123/craftos2/issues/337), which introduced breaking changes.
- The `gtest` package has been updated past v1.13.0, which requires C++14 or higher.
- The latest available version of Nextcloud is v28 (available as `pkgs.nextcloud28`). The installation logic is as follows:
- If [`services.nextcloud.package`](#opt-services.nextcloud.package) is specified explicitly, this package will be installed (**recommended**)
- If [`system.stateVersion`](#opt-system.stateVersion) is >=24.05, `pkgs.nextcloud28` will be installed by default.
@ -159,10 +191,18 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- The `cudaPackages` package scope has been updated to `cudaPackages_12`.
- Ada packages (libraries and tools) have been moved into the `gnatPackages` scope. `gnatPackages` uses the default GNAT compiler, `gnat12Packages` and `gnat13Packages` use the respective matching compiler version.
- `spark2014` has been renamed to `gnatprove`. A version of `gnatprove` matching different GNAT versions is available from the different `gnatPackages` sets.
- `services.resolved.fallbackDns` can now be used to disable the upstream fallback servers entirely by setting it to an empty list. To get the previous behaviour of the upstream defaults set it to null, the new default, instead.
- `xxd` has been moved from `vim` default output to its own output to reduce closure size. The canonical way to reference it across all platforms is `unixtools.xxd`.
- The `stalwart-mail` package has been updated to v0.5.3, which includes [breaking changes](https://github.com/stalwartlabs/mail-server/blob/v0.5.3/UPGRADING.md).
- `services.zope2` has been removed as `zope2` is unmaintained and was relying on Python2.
- `services.avahi.nssmdns` got split into `services.avahi.nssmdns4` and `services.avahi.nssmdns6` which enable the mDNS NSS switch for IPv4 and IPv6 respectively.
Since most mDNS responders only register IPv4 addresses, most users want to keep the IPv6 support disabled to avoid long timeouts.
@ -171,6 +211,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
`wants`), because the dependency that `multi-user.target` has on
`network-online.target` is planned for removal.
- `services.pgbouncer` now has systemd support enabled and will log to journald. The default setting for `services.pgbouncer.logFile` is now `null` to disable logging to a separate log file.
- `services.archisteamfarm` no longer uses the abbreviation `asf` for its state directory (`/var/lib/asf`), user and group (both `asf`). Instead the long name `archisteamfarm` is used.
Configurations with `system.stateVersion` 23.11 or earlier, default to the old stateDirectory until the 24.11 release and must either set the option explicitly or move the data to the new directory.
@ -243,9 +285,16 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- Cinnamon has been updated to 6.0. Please beware that the [Wayland session](https://blog.linuxmint.com/?p=4591) is still experimental in this release.
- New `boot.loader.systemd-boot.xbootldrMountPoint` allows setting up a separate [XBOOTLDR partition](https://uapi-group.org/specifications/specs/boot_loader_specification/) to store boot files. Useful on systems with a small EFI System partition that cannot be easily repartitioned.
- `boot.loader.systemd-boot` will now verify that `efiSysMountPoint` (and `xbootldrMountPoint` if configured) are mounted partitions.
- `services.postgresql.extraPlugins` changed its type from just a list of packages to also a function that returns such a list.
For example a config line like ``services.postgresql.extraPlugins = with pkgs.postgresql_11.pkgs; [ postgis ];`` is recommended to be changed to ``services.postgresql.extraPlugins = ps: with ps; [ postgis ];``;
- The Matrix homeserver [Synapse](https://element-hq.github.io/synapse/) module now supports configuring UNIX domain socket [listeners](#opt-services.matrix-synapse.settings.listeners) through the `path` option.
The default replication worker on the main instance has been migrated away from TCP sockets to UNIX domain sockets.
- Programs written in [Nim](https://nim-lang.org/) are built with libraries selected by lockfiles.
The `nimPackages` and `nim2Packages` sets have been removed.
See https://nixos.org/manual/nixpkgs/unstable#nim for more information.
@ -255,6 +304,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
After upgrading, follow the instructions on the [upstream release notes](https://github.com/majewsky/portunus/releases/tag/v2.0.0) to upgrade all user accounts to strong password hashes.
Support for weak password hashes will be removed in NixOS 24.11.
- A stdenv's default set of hardening flags can now be set via its `bintools-wrapper`'s `defaultHardeningFlags` argument. A convenient stdenv adapter, `withDefaultHardeningFlags`, can be used to override an existing stdenv's `defaultHardeningFlags`.
- `libass` now uses the native CoreText backend on Darwin, which may fix subtitle rendering issues with `mpv`, `ffmpeg`, etc.
- [Lilypond](https://lilypond.org/index.html) and [Denemo](https://www.denemo.org) are now compiled with Guile 3.0.
@ -272,8 +323,19 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- The option [`services.nextcloud.config.dbport`] of the Nextcloud module was removed to match upstream.
The port can be specified in [`services.nextcloud.config.dbhost`](#opt-services.nextcloud.config.dbhost).
- A new abstraction to create both read-only as well as writable overlay file
systems was added. Available via
[fileSystems.overlay](#opt-fileSystems._name_.overlay.lowerdir). See also the
[NixOS docs](#sec-overlayfs).
- systemd units can now specify the `Upholds=` and `UpheldBy=` unit dependencies via the aptly
named `upholds` and `upheldBy` options. These options get systemd to enforce that the
dependencies remain continuosly running for as long as the dependent unit is in a running state.
- `stdenv`: The `--replace` flag in `substitute`, `substituteInPlace`, `substituteAll`, `substituteAllStream`, and `substituteStream` is now deprecated if favor of the new `--replace-fail`, `--replace-warn` and `--replace-quiet`. The deprecated `--replace` equates to `--replace-warn`.
- A new hardening flag, `zerocallusedregs` was made available, corresponding to the gcc/clang option `-fzero-call-used-regs=used-gpr`.
- New options were added to the dnsdist module to enable and configure a DNSCrypt endpoint (see `services.dnsdist.dnscrypt.enable`, etc.).
The module can generate the DNSCrypt provider key pair, certificates and also performs their rotation automatically with no downtime.
@ -290,6 +352,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
`globalRedirect` can now have redirect codes other than 301 through
`redirectCode`.
- `libjxl` 0.9.0 [dropped support for the butteraugli API](https://github.com/libjxl/libjxl/pull/2576). You will no longer be able to set `enableButteraugli` on `libaom`.
- The source of the `mockgen` package has changed to the [go.uber.org/mock](https://github.com/uber-go/mock) fork because [the original repository is no longer maintained](https://github.com/golang/mock#gomock).
- `security.pam.enableSSHAgentAuth` was renamed to `security.pam.sshAgentAuth.enable` and an `authorizedKeysFiles`
@ -298,6 +362,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- [](#opt-boot.kernel.sysctl._net.core.wmem_max_) changed from a string to an integer because of the addition of a custom merge option (taking the highest value defined to avoid conflicts between 2 services trying to set that value), just as [](#opt-boot.kernel.sysctl._net.core.rmem_max_) since 22.11.
- A new top-level package set, `pkgsExtraHardening` is added. This is a set of packages built with stricter hardening flags - those that have not yet received enough testing to be applied universally, those that are more likely to cause build failures or those that have drawbacks to their use (e.g. performance or required hardware features).
- `services.zfs.zed.enableMail` now uses the global `sendmail` wrapper defined by an email module
(such as msmtp or Postfix). It no longer requires using a special ZFS build with email support.
@ -311,8 +377,12 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- The `services.paperless` module no longer uses the previously downloaded NLTK data stored in `/var/cache/paperless/nltk`. This directory can be removed.
- The `services.teeworlds` module now has a wealth of configuration options, including a new `package` option.
- The `hardware.pulseaudio` module now sets permission of pulse user home directory to 755 when running in "systemWide" mode. It fixes [issue 114399](https://github.com/NixOS/nixpkgs/issues/114399).
- The module `services.github-runner` has been removed. To configure a single GitHub Actions Runner refer to `services.github-runners.*`. Note that this will trigger a new runner registration.
- The `btrbk` module now automatically selects and provides required compression
program depending on the configured `stream_compress` option. Since this
replaces the need for the `extraPackages` option, this option will be
@ -320,8 +390,14 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
- The `mpich` package expression now requires `withPm` to be a list, e.g. `"hydra:gforker"` becomes `[ "hydra" "gforker" ]`.
- When merging systemd unit options (of type `unitOption`),
if at least one definition is a list, all those which aren't are now lifted into a list,
making it possible to accumulate definitions without resorting to `mkForce`,
hence to retain the definitions not anticipating that need.
- YouTrack is bumped to 2023.3. The update is not performed automatically, it requires manual interaction. See the YouTrack section in the manual for details.
- QtMultimedia has changed its default backend to `QT_MEDIA_BACKEND=ffmpeg` (previously `gstreamer` on Linux or `darwin` on MacOS).
The previous native backends remain available but are now minimally maintained. Refer to [upstream documentation](https://doc.qt.io/qt-6/qtmultimedia-index.html#ffmpeg-as-the-default-backend) for further details about each platform.
- The oil shell is now using the c++ version by default. The python based build is still available as `oil-python`

View file

@ -56,6 +56,14 @@ This partition table type uses GPT and:
- creates an FAT32 ESP partition from 8MiB to specified `bootSize` parameter (256MiB by default), set it bootable ;
- creates an primary ext4 partition starting after the boot partition and extending to the full disk image
#### `efixbootldr`
This partition table type uses GPT and:
- creates an FAT32 ESP partition from 8MiB to 100MiB, set it bootable ;
- creates an FAT32 BOOT partition from 100MiB to specified `bootSize` parameter (256MiB by default), set `bls_boot` flag ;
- creates an primary ext4 partition starting after the boot partition and extending to the full disk image
#### `hybrid`
This partition table type uses GPT and:
@ -111,19 +119,7 @@ To solve this, you can run `fdisk -l $image` and generate `dd if=$image of=$imag
# When setting one of `user' or `group', the other needs to be set too.
contents ? []
, # Type of partition table to use; either "legacy", "efi", or "none".
# For "efi" images, the GPT partition table is used and a mandatory ESP
# partition of reasonable size is created in addition to the root partition.
# For "legacy", the msdos partition table is used and a single large root
# partition is created.
# For "legacy+gpt", the GPT partition table is used, a 1MiB no-fs partition for
# use by the bootloader is created, and a single large root partition is
# created.
# For "hybrid", the GPT partition table is used and a mandatory ESP
# partition of reasonable size is created in addition to the root partition.
# Also a legacy MBR will be present.
# For "none", no partition table is created. Enabling `installBootLoader`
# most likely fails as GRUB will probably refuse to install.
, # Type of partition table to use; described in the `Image Partitioning` section above.
partitionTableType ? "legacy"
, # Whether to invoke `switch-to-configuration boot` during image creation
@ -193,11 +189,11 @@ To solve this, you can run `fdisk -l $image` and generate `dd if=$image of=$imag
additionalPaths ? []
}:
assert (lib.assertOneOf "partitionTableType" partitionTableType [ "legacy" "legacy+gpt" "efi" "hybrid" "none" ]);
assert (lib.assertOneOf "partitionTableType" partitionTableType [ "legacy" "legacy+gpt" "efi" "efixbootldr" "hybrid" "none" ]);
assert (lib.assertMsg (fsType == "ext4" && deterministic -> rootFSUID != null) "In deterministic mode with a ext4 partition, rootFSUID must be non-null, by default, it is equal to rootGPUID.");
# We use -E offset=X below, which is only supported by e2fsprogs
assert (lib.assertMsg (partitionTableType != "none" -> fsType == "ext4") "to produce a partition table, we need to use -E offset flag which is support only for fsType = ext4");
assert (lib.assertMsg (touchEFIVars -> partitionTableType == "hybrid" || partitionTableType == "efi" || partitionTableType == "legacy+gpt") "EFI variables can be used only with a partition table of type: hybrid, efi or legacy+gpt.");
assert (lib.assertMsg (touchEFIVars -> partitionTableType == "hybrid" || partitionTableType == "efi" || partitionTableType == "efixbootldr" || partitionTableType == "legacy+gpt") "EFI variables can be used only with a partition table of type: hybrid, efi, efixbootldr, or legacy+gpt.");
# If only Nix store image, then: contents must be empty, configFile must be unset, and we should no install bootloader.
assert (lib.assertMsg (onlyNixStore -> contents == [] && configFile == null && !installBootLoader) "In a only Nix store image, the contents must be empty, no configuration must be provided and no bootloader should be installed.");
# Either both or none of {user,group} need to be set
@ -225,6 +221,7 @@ let format' = format; in let
legacy = "1";
"legacy+gpt" = "2";
efi = "2";
efixbootldr = "3";
hybrid = "3";
}.${partitionTableType};
@ -266,6 +263,23 @@ let format' = format; in let
$diskImage
''}
'';
efixbootldr = ''
parted --script $diskImage -- \
mklabel gpt \
mkpart ESP fat32 8MiB 100MiB \
set 1 boot on \
mkpart BOOT fat32 100MiB ${bootSize} \
set 2 bls_boot on \
mkpart ROOT ext4 ${bootSize} -1
${optionalString deterministic ''
sgdisk \
--disk-guid=97FD5997-D90B-4AA3-8D16-C1723AEA73C \
--partition-guid=1:1C06F03B-704E-4657-B9CD-681A087A2FDC \
--partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \
--partition-guid=3:${rootGPUID} \
$diskImage
''}
'';
hybrid = ''
parted --script $diskImage -- \
mklabel gpt \
@ -436,7 +450,7 @@ let format' = format; in let
diskImage=nixos.raw
${if diskSize == "auto" then ''
${if partitionTableType == "efi" || partitionTableType == "hybrid" then ''
${if partitionTableType == "efi" || partitionTableType == "efixbootldr" || partitionTableType == "hybrid" then ''
# Add the GPT at the end
gptSpace=$(( 512 * 34 * 1 ))
# Normally we'd need to account for alignment and things, if bootSize
@ -536,6 +550,9 @@ let format' = format; in let
concatStringsSep " " (lib.optional useEFIBoot "-drive if=pflash,format=raw,unit=0,readonly=on,file=${efiFirmware}"
++ lib.optionals touchEFIVars [
"-drive if=pflash,format=raw,unit=1,file=$efiVars"
] ++ lib.optionals (OVMF.systemManagementModeRequired or false) [
"-machine" "q35,smm=on"
"-global" "driver=cfi.pflash01,property=secure,value=on"
]
);
inherit memSize;
@ -567,6 +584,15 @@ let format' = format; in let
${optionalString touchEFIVars "mount -t efivarfs efivarfs /sys/firmware/efi/efivars"}
''}
${optionalString (partitionTableType == "efixbootldr") ''
mkdir -p /mnt/{boot,efi}
mkfs.vfat -n ESP /dev/vda1
mkfs.vfat -n BOOT /dev/vda2
mount /dev/vda1 /mnt/efi
mount /dev/vda2 /mnt/boot
${optionalString touchEFIVars "mount -t efivarfs efivarfs /sys/firmware/efi/efivars"}
''}
# Install a configuration.nix
mkdir -p /mnt/etc/nixos

View file

@ -242,7 +242,7 @@ in rec {
ln -sfn '${name}' $out/'${name2}'
'') (unit.aliases or [])) units)}
# Create .wants and .requires symlinks from the wantedBy and
# Create .wants, .upholds and .requires symlinks from the wantedBy, upheldBy and
# requiredBy options.
${concatStrings (mapAttrsToList (name: unit:
concatMapStrings (name2: ''
@ -250,6 +250,12 @@ in rec {
ln -sfn '../${name}' $out/'${name2}.wants'/
'') (unit.wantedBy or [])) units)}
${concatStrings (mapAttrsToList (name: unit:
concatMapStrings (name2: ''
mkdir -p $out/'${name2}.upholds'
ln -sfn '../${name}' $out/'${name2}.upholds'/
'') (unit.upheldBy or [])) units)}
${concatStrings (mapAttrsToList (name: unit:
concatMapStrings (name2: ''
mkdir -p $out/'${name2}.requires'
@ -289,6 +295,8 @@ in rec {
{ Requires = toString config.requires; }
// optionalAttrs (config.wants != [])
{ Wants = toString config.wants; }
// optionalAttrs (config.upholds != [])
{ Upholds = toString config.upholds; }
// optionalAttrs (config.after != [])
{ After = toString config.after; }
// optionalAttrs (config.before != [])
@ -370,7 +378,7 @@ in rec {
'';
targetToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text =
''
[Unit]
@ -379,7 +387,7 @@ in rec {
};
serviceToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def (''
[Service]
'' + (let env = cfg.globalEnvironment // def.environment;
@ -400,7 +408,7 @@ in rec {
};
socketToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Socket]
${attrsToSection def.socketConfig}
@ -410,7 +418,7 @@ in rec {
};
timerToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Timer]
${attrsToSection def.timerConfig}
@ -418,7 +426,7 @@ in rec {
};
pathToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Path]
${attrsToSection def.pathConfig}
@ -426,7 +434,7 @@ in rec {
};
mountToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Mount]
${attrsToSection def.mountConfig}
@ -434,7 +442,7 @@ in rec {
};
automountToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Automount]
${attrsToSection def.automountConfig}
@ -442,7 +450,7 @@ in rec {
};
sliceToUnit = name: def:
{ inherit (def) aliases wantedBy requiredBy enable overrideStrategy;
{ inherit (def) aliases wantedBy requiredBy upheldBy enable overrideStrategy;
text = commonUnitText def ''
[Slice]
${attrsToSection def.sliceConfig}

View file

@ -6,7 +6,7 @@ with lib;
let
checkService = checkUnitConfig "Service" [
(assertValueOneOf "Type" [
"exec" "simple" "forking" "oneshot" "dbus" "notify" "idle"
"exec" "simple" "forking" "oneshot" "dbus" "notify" "notify-reload" "idle"
])
(assertValueOneOf "Restart" [
"no" "on-success" "on-failure" "on-abnormal" "on-abort" "always"
@ -21,14 +21,8 @@ in rec {
let
defs' = filterOverrides defs;
in
if isList (head defs').value
then concatMap (def:
if builtins.typeOf def.value == "list"
then def.value
else
throw "The definitions for systemd unit options should be either all lists, representing repeatable options, or all non-lists, but for the option ${showOption loc}, the definitions are a mix of list and non-list ${lib.options.showDefs defs'}"
) defs'
if any (def: isList def.value) defs'
then concatMap (def: toList def.value) defs'
else mergeEqualOption loc defs';
};
@ -74,6 +68,15 @@ in rec {
'';
};
upheldBy = mkOption {
default = [];
type = types.listOf unitNameType;
description = lib.mdDoc ''
Keep this unit running as long as the listed units are running. This is a continuously
enforced version of wantedBy.
'';
};
wantedBy = mkOption {
default = [];
type = types.listOf unitNameType;
@ -147,6 +150,14 @@ in rec {
'';
};
upholds = mkOption {
default = [];
type = types.listOf unitNameType;
description = lib.mdDoc ''
Keeps the specified running while this unit is running. A continuous version of `wants`.
'';
};
after = mkOption {
default = [];
type = types.listOf unitNameType;

View file

@ -37,7 +37,6 @@ target-version = ['py39']
include = '\.pyi?$'
[tool.mypy]
python_version = "3.10"
warn_redundant_casts = true
disallow_untyped_calls = true
disallow_untyped_defs = true

View file

@ -12,6 +12,8 @@ from test_driver.machine import Machine, NixStartScript, retry
from test_driver.polling_condition import PollingCondition
from test_driver.vlan import VLan
SENTINEL = object()
def get_tmp_dir() -> Path:
"""Returns a temporary directory that is defined by TMPDIR, TEMP, TMP or CWD
@ -187,23 +189,58 @@ class Driver:
# to swallow them and prevent itself from terminating.
os.kill(os.getpid(), signal.SIGTERM)
def create_machine(self, args: Dict[str, Any]) -> Machine:
def create_machine(
self,
start_command: str | dict,
*,
name: Optional[str] = None,
keep_vm_state: bool = False,
) -> Machine:
# Legacy args handling
# FIXME: remove after 24.05
if isinstance(start_command, dict):
if name is not None or keep_vm_state:
raise TypeError(
"Dictionary passed to create_machine must be the only argument"
)
args = start_command
start_command = args.pop("startCommand", SENTINEL)
if start_command is SENTINEL:
raise TypeError(
"Dictionary passed to create_machine must contain startCommand"
)
if not isinstance(start_command, str):
raise TypeError(
f"startCommand must be a string, got: {repr(start_command)}"
)
name = args.pop("name", None)
keep_vm_state = args.pop("keep_vm_state", False)
if args:
raise TypeError(
f"Unsupported arguments passed to create_machine: {args}"
)
rootlog.warning(
"Using create_machine with a single dictionary argument is deprecated, and will be removed in NixOS 24.11"
)
# End legacy args handling
tmp_dir = get_tmp_dir()
if args.get("startCommand"):
start_command: str = args.get("startCommand", "")
cmd = NixStartScript(start_command)
name = args.get("name", cmd.machine_name)
else:
cmd = Machine.create_startcommand(args) # type: ignore
name = args.get("name", "machine")
name = name or cmd.machine_name
return Machine(
tmp_dir=tmp_dir,
out_dir=self.out_dir,
start_command=cmd,
name=name,
keep_vm_state=args.get("keep_vm_state", False),
keep_vm_state=keep_vm_state,
)
def serial_stdout_on(self) -> None:

View file

@ -208,7 +208,6 @@ class StartCommand:
),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
cwd=state_dir,
env=self.build_environment(state_dir, shared_dir),
@ -235,77 +234,6 @@ class NixStartScript(StartCommand):
return name
class LegacyStartCommand(StartCommand):
"""Used in some places to create an ad-hoc machine instead of
using nix test instrumentation + module system for that purpose.
Legacy.
"""
def __init__(
self,
netBackendArgs: Optional[str] = None, # noqa: N803
netFrontendArgs: Optional[str] = None, # noqa: N803
hda: Optional[Tuple[Path, str]] = None,
cdrom: Optional[str] = None,
usb: Optional[str] = None,
bios: Optional[str] = None,
qemuBinary: Optional[str] = None, # noqa: N803
qemuFlags: Optional[str] = None, # noqa: N803
):
if qemuBinary is not None:
self._cmd = qemuBinary
else:
self._cmd = "qemu-kvm"
self._cmd += " -m 384"
# networking
net_backend = "-netdev user,id=net0"
net_frontend = "-device virtio-net-pci,netdev=net0"
if netBackendArgs is not None:
net_backend += "," + netBackendArgs
if netFrontendArgs is not None:
net_frontend += "," + netFrontendArgs
self._cmd += f" {net_backend} {net_frontend}"
# hda
hda_cmd = ""
if hda is not None:
hda_path = hda[0].resolve()
hda_interface = hda[1]
if hda_interface == "scsi":
hda_cmd += (
f" -drive id=hda,file={hda_path},werror=report,if=none"
" -device scsi-hd,drive=hda"
)
else:
hda_cmd += f" -drive file={hda_path},if={hda_interface},werror=report"
self._cmd += hda_cmd
# cdrom
if cdrom is not None:
self._cmd += f" -cdrom {cdrom}"
# usb
usb_cmd = ""
if usb is not None:
# https://github.com/qemu/qemu/blob/master/docs/usb2.txt
usb_cmd += (
" -device usb-ehci"
f" -drive id=usbdisk,file={usb},if=none,readonly"
" -device usb-storage,drive=usbdisk "
)
self._cmd += usb_cmd
# bios
if bios is not None:
self._cmd += f" -bios {bios}"
# qemu flags
if qemuFlags is not None:
self._cmd += f" {qemuFlags}"
class Machine:
"""A handle to the machine with this name, that also knows how to manage
the machine lifecycle with the help of a start script / command."""
@ -377,29 +305,6 @@ class Machine:
self.booted = False
self.connected = False
@staticmethod
def create_startcommand(args: Dict[str, str]) -> StartCommand:
rootlog.warning(
"Using legacy create_startcommand(), "
"please use proper nix test vm instrumentation, instead "
"to generate the appropriate nixos test vm qemu startup script"
)
hda = None
if args.get("hda"):
hda_arg: str = args.get("hda", "")
hda_arg_path: Path = Path(hda_arg)
hda = (hda_arg_path, args.get("hdaInterface", ""))
return LegacyStartCommand(
netBackendArgs=args.get("netBackendArgs"),
netFrontendArgs=args.get("netFrontendArgs"),
hda=hda,
cdrom=args.get("cdrom"),
usb=args.get("usb"),
bios=args.get("bios"),
qemuBinary=args.get("qemuBinary"),
qemuFlags=args.get("qemuFlags"),
)
def is_up(self) -> bool:
return self.booted and self.connected

View file

@ -26,6 +26,17 @@ class PollingConditionProtocol(Protocol):
raise Exception("This is just type information for the Nix test driver")
class CreateMachineProtocol(Protocol):
def __call__(
self,
start_command: str | dict,
*,
name: Optional[str] = None,
keep_vm_state: bool = False,
) -> Machine:
raise Exception("This is just type information for the Nix test driver")
start_all: Callable[[], None]
subtest: Callable[[str], ContextManager[None]]
retry: RetryProtocol
@ -34,7 +45,7 @@ machines: List[Machine]
vlans: List[VLan]
driver: Driver
log: Logger
create_machine: Callable[[Dict[str, Any]], Machine]
create_machine: CreateMachineProtocol
run_tests: Callable[[], None]
join_all: Callable[[], None]
serial_stdout_off: Callable[[], None]

View file

@ -16,7 +16,11 @@ in
# The human version (e.g. 21.05-pre) is left as is, because it is useful
# for external modules that test with e.g. testers.nixosTest and rely on that
# version number.
config.system.nixos.revision = mkForce "constant-nixos-revision";
config.system.nixos = {
revision = mkForce "constant-nixos-revision";
versionSuffix = mkForce "test";
label = mkForce "test";
};
}
];

View file

@ -0,0 +1,7 @@
# Amazon images
* The `create-amis.sh` script will be replaced by https://github.com/NixOS/amis which will regularly upload AMIs per NixOS channel bump.
* @arianvp is planning to drop zfs support
* @arianvp is planning to rewrite the image builder to use the repart-based image builder.

View file

@ -157,4 +157,6 @@ in {
'';
};
in if config.ec2.zfs.enable then zfsBuilder else extBuilder;
meta.maintainers = with maintainers; [ arianvp ];
}

View file

@ -13,8 +13,23 @@
./lxd.nix
];
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-eth0" = {
matchConfig.Name = "eth0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
system.stateVersion = "@stateVersion@"; # Did you read the comment?
}

View file

@ -20,12 +20,25 @@
};
in ''
if [ ! -e /etc/nixos/configuration.nix ]; then
mkdir -p /etc/nixos
cp ${config} /etc/nixos/configuration.nix
install -m 644 -D ${config} /etc/nixos/configuration.nix
fi
'';
# Network
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-eth0" = {
matchConfig.Name = "eth0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
}

View file

@ -13,8 +13,23 @@
./lxd.nix
];
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-enp5s0" = {
matchConfig.Name = "enp5s0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
system.stateVersion = "@stateVersion@"; # Did you read the comment?
}

View file

@ -26,6 +26,21 @@
'';
# Network
networking.useDHCP = false;
networking.interfaces.enp5s0.useDHCP = true;
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-enp5s0" = {
matchConfig.Name = "enp5s0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
}

View file

@ -6,9 +6,9 @@ let
libDir = pkgs.stdenv.hostPlatform.libDir;
ldsoBasename = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs.stdenv.cc.bintools.dynamicLinker));
pkgs32 = pkgs.pkgsi686Linux;
libDir32 = pkgs32.stdenv.hostPlatform.libDir;
ldsoBasename32 = builtins.unsafeDiscardStringContext (last (splitString "/" pkgs32.stdenv.cc.bintools.dynamicLinker));
# Hard-code to avoid creating another instance of nixpkgs. Also avoids eval errors in some cases.
libDir32 = "lib"; # pkgs.pkgsi686Linux.stdenv.hostPlatform.libDir
ldsoBasename32 = "ld-linux.so.2"; # last (splitString "/" pkgs.pkgsi686Linux.stdenv.cc.bintools.dynamicLinker)
in {
options = {
environment.ldso = mkOption {

View file

@ -1,5 +1,5 @@
/*
Manages /etc/nix.conf.
Manages /etc/nix/nix.conf.
See also
- ./nix-channel.nix

View file

@ -67,7 +67,7 @@ with lib;
networkmanager-vpnc = super.networkmanager-vpnc.override { withGnome = false; };
pango = super.pango.override { x11Support = false; };
pinentry = super.pinentry.override { enabledFlavors = [ "curses" "tty" "emacs" ]; withLibsecret = false; };
pipewire = super.pipewire.override { x11Support = false; };
pipewire = super.pipewire.override { vulkanSupport = false; x11Support = false; };
pythonPackagesExtensions = super.pythonPackagesExtensions ++ [
(python-final: python-prev: {
# tk feature requires wayland which fails to compile
@ -83,6 +83,7 @@ with lib;
# 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

@ -649,7 +649,6 @@ in {
home = "/root";
shell = mkDefault cfg.defaultUserShell;
group = "root";
initialHashedPassword = mkDefault "!";
};
nobody = {
uid = ids.uids.nobody;
@ -897,7 +896,26 @@ in {
));
warnings =
builtins.filter (x: x != null) (
flip concatMap (attrValues cfg.users) (user: let
unambiguousPasswordConfiguration = 1 >= length (filter (x: x != null) ([
user.hashedPassword
user.hashedPasswordFile
user.password
] ++ optionals cfg.mutableUsers [
# For immutable users, initialHashedPassword is set to hashedPassword,
# so using these options would always trigger the assertion.
user.initialHashedPassword
user.initialPassword
]));
in optional (!unambiguousPasswordConfiguration) ''
The user '${user.name}' has multiple of the options
`hashedPassword`, `password`, `hashedPasswordFile`, `initialPassword`
& `initialHashedPassword` set to a non-null value.
The options silently discard others by the order of precedence
given above which can lead to surprising results. To resolve this warning,
set at most one of the options above to a non-`null` value.
'')
++ builtins.filter (x: x != null) (
flip mapAttrsToList cfg.users (_: user:
# This regex matches a subset of the Modular Crypto Format (MCF)[1]
# informal standard. Since this depends largely on the OS or the

View file

@ -1,5 +1,3 @@
# VTE
{ config, pkgs, lib, ... }:
with lib;
@ -9,7 +7,7 @@ let
vteInitSnippet = ''
# Show current working directory in VTE terminals window title.
# Supports both bash and zsh, requires interactive shell.
. ${pkgs.vte}/etc/profile.d/vte.sh
. ${pkgs.vte.override { gtkVersion = null; }}/etc/profile.d/vte.sh
'';
in

View file

@ -119,19 +119,6 @@ in
let
cfg = config.xdg.portal;
packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
configPackages = cfg.configPackages;
joinedPortals = pkgs.buildEnv {
name = "xdg-portals";
paths = packages;
pathsToLink = [ "/share/xdg-desktop-portal/portals" "/share/applications" ];
};
joinedPortalConfigs = pkgs.buildEnv {
name = "xdg-portal-configs";
paths = configPackages;
pathsToLink = [ "/share/xdg-desktop-portal" ];
};
in
mkIf cfg.enable {
warnings = lib.optional (cfg.configPackages == [ ] && cfg.config == { }) ''
@ -158,17 +145,18 @@ in
systemd.packages = packages;
environment = {
# fixes screen sharing on plasmawayland on non-chromium apps by linking
# share/applications/*.desktop files
# see https://github.com/NixOS/nixpkgs/issues/145174
systemPackages = [ joinedPortals ];
pathsToLink = [ "/share/applications" ];
systemPackages = packages ++ cfg.configPackages;
pathsToLink = [
# Portal definitions and upstream desktop environment portal configurations.
"/share/xdg-desktop-portal"
# .desktop files to register fallback icon and app name.
"/share/applications"
];
sessionVariables = {
GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
NIXOS_XDG_OPEN_USE_PORTAL = mkIf cfg.xdgOpenUsePortal "1";
XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
NIXOS_XDG_DESKTOP_PORTAL_CONFIG_DIR = mkIf (cfg.configPackages != [ ]) "${joinedPortalConfigs}/share/xdg-desktop-portal";
NIX_XDG_DESKTOP_PORTAL_DIR = "/run/current-system/sw/share/xdg-desktop-portal/portals";
};
etc = lib.concatMapAttrs

View file

@ -2,18 +2,23 @@
with lib;
let
cfg = config.hardware.printers;
ppdOptionsString = options: optionalString (options != {})
(concatStringsSep " "
(mapAttrsToList (name: value: "-o '${name}'='${value}'") options)
);
ensurePrinter = p: ''
${pkgs.cups}/bin/lpadmin -p '${p.name}' -E \
${optionalString (p.location != null) "-L '${p.location}'"} \
${optionalString (p.description != null) "-D '${p.description}'"} \
-v '${p.deviceUri}' \
-m '${p.model}' \
${ppdOptionsString p.ppdOptions}
ensurePrinter = p: let
args = cli.toGNUCommandLineShell {} ({
p = p.name;
v = p.deviceUri;
m = p.model;
} // optionalAttrs (p.location != null) {
L = p.location;
} // optionalAttrs (p.description != null) {
D = p.description;
} // optionalAttrs (p.ppdOptions != {}) {
o = mapAttrsToList (name: value: "'${name}'='${value}'") p.ppdOptions;
});
in ''
${pkgs.cups}/bin/lpadmin ${args} -E
'';
ensureDefaultPrinter = name: ''
${pkgs.cups}/bin/lpadmin -d '${name}'
'';

View file

@ -1,18 +1,19 @@
{ config, pkgs, lib, ... }:
with lib;
let
pkg = [ pkgs.switcheroo-control ];
cfg = config.services.switcherooControl;
in {
options.services.switcherooControl = {
enable = mkEnableOption (lib.mdDoc "switcheroo-control, a D-Bus service to check the availability of dual-GPU");
enable = lib.mkEnableOption "switcheroo-control, a D-Bus service to check the availability of dual-GPU";
package = lib.mkPackageOption pkgs "switcheroo-control" { };
};
config = mkIf cfg.enable {
services.dbus.packages = pkg;
environment.systemPackages = pkg;
systemd.packages = pkg;
systemd.targets.multi-user.wants = [ "switcheroo-control.service" ];
config = lib.mkIf cfg.enable {
services.dbus.packages = [ cfg.package ];
environment.systemPackages = [ cfg.package ];
systemd = {
packages = [ cfg.package ];
targets.multi-user.wants = [ "switcheroo-control.service" ];
};
};
}

View file

@ -0,0 +1,46 @@
# This module defines a NixOS installation CD that contains Plasma 6.
{ pkgs, ... }:
{
imports = [ ./installation-cd-graphical-calamares.nix ];
isoImage.edition = "plasma6";
services.xserver = {
desktopManager.plasma6.enable = true;
# Automatically login as nixos.
displayManager = {
sddm.enable = true;
autoLogin = {
enable = true;
user = "nixos";
};
};
};
environment.systemPackages = [
# FIXME: using Qt5 builds of Maliit as upstream has not ported to Qt6 yet
pkgs.maliit-framework
pkgs.maliit-keyboard
];
system.activationScripts.installerDesktop = let
# Comes from documentation.nix when xserver and nixos.enable are true.
manualDesktopFile = "/run/current-system/sw/share/applications/nixos-manual.desktop";
homeDir = "/home/nixos/";
desktopDir = homeDir + "Desktop/";
in ''
mkdir -p ${desktopDir}
chown nixos ${homeDir} ${desktopDir}
ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
ln -sfT ${pkgs.calamares-nixos}/share/applications/io.calamares.calamares.desktop ${desktopDir + "io.calamares.calamares.desktop"}
'';
}

View file

@ -1,15 +1,7 @@
{ pkgs, ... }:
{ lib, ... }:
{
imports = [ ./installation-cd-minimal-new-kernel.nix ];
# Makes `availableOn` fail for zfs, see <nixos/modules/profiles/base.nix>.
# This is a workaround since we cannot remove the `"zfs"` string from `supportedFilesystems`.
# The proper fix would be to make `supportedFilesystems` an attrset with true/false which we
# could then `lib.mkForce false`
nixpkgs.overlays = [(final: super: {
zfs = super.zfs.overrideAttrs(_: {
meta.platforms = [];
});
})];
boot.supportedFilesystems.zfs = lib.mkForce false;
}

View file

@ -62,19 +62,12 @@ with lib;
};
fileSystems."/nix/store" = mkImageMediaOverride
{ fsType = "overlay";
device = "overlay";
options = [
"lowerdir=/nix/.ro-store"
"upperdir=/nix/.rw-store/store"
"workdir=/nix/.rw-store/work"
];
depends = [
"/nix/.ro-store"
"/nix/.rw-store/store"
"/nix/.rw-store/work"
];
{ overlay = {
lowerdir = [ "/nix/.ro-store" ];
upperdir = "/nix/.rw-store/store";
workdir = "/nix/.rw-store/work";
};
neededForBoot = true;
};
boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];

View file

@ -1,15 +1,7 @@
{ pkgs, ... }:
{ lib, ... }:
{
imports = [ ./sd-image-aarch64-new-kernel-installer.nix ];
# Makes `availableOn` fail for zfs, see <nixos/modules/profiles/base.nix>.
# This is a workaround since we cannot remove the `"zfs"` string from `supportedFilesystems`.
# The proper fix would be to make `supportedFilesystems` an attrset with true/false which we
# could then `lib.mkForce false`
nixpkgs.overlays = [(final: super: {
zfs = super.zfs.overrideAttrs(_: {
meta.platforms = [];
});
})];
boot.supportedFilesystems.zfs = lib.mkForce false;
}

View file

@ -313,7 +313,7 @@ in
kanboard = 281;
# pykms = 282; # DynamicUser = true
kodi = 283;
restya-board = 284;
# restya-board = 284; # removed 2024-01-22
mighttpd2 = 285;
hass = 286;
#monero = 287; # dynamically allocated as of 2021-05-08
@ -623,7 +623,7 @@ in
kanboard = 281;
# pykms = 282; # DynamicUser = true
kodi = 283;
restya-board = 284;
# restya-board = 284; # removed 2024-01-22
mighttpd2 = 285;
hass = 286;
# monero = 287; # dynamically allocated as of 2021-05-08

View file

@ -0,0 +1,105 @@
{ config, options, lib, pkgs, ... }:
with lib;
let
cfg = config.nixpkgs.flake;
in
{
options.nixpkgs.flake = {
source = mkOption {
# In newer Nix versions, particularly with lazy trees, outPath of
# flakes becomes a Nix-language path object. We deliberately allow this
# to gracefully come through the interface in discussion with @roberth.
#
# See: https://github.com/NixOS/nixpkgs/pull/278522#discussion_r1460292639
type = types.nullOr (types.either types.str types.path);
default = null;
defaultText = "if (using nixpkgsFlake.lib.nixosSystem) then self.outPath else null";
example = ''builtins.fetchTarball { name = "source"; sha256 = "${lib.fakeHash}"; url = "https://github.com/nixos/nixpkgs/archive/somecommit.tar.gz"; }'';
description = mdDoc ''
The path to the nixpkgs sources used to build the system. This is automatically set up to be
the store path of the nixpkgs flake used to build the system if using
`nixpkgs.lib.nixosSystem`, and is otherwise null by default.
This can also be optionally set if the NixOS system is not built with a flake but still uses
pinned sources: set this to the store path for the nixpkgs sources used to build the system,
as may be obtained by `builtins.fetchTarball`, for example.
Note: the name of the store path must be "source" due to
<https://github.com/NixOS/nix/issues/7075>.
'';
};
setNixPath = mkOption {
type = types.bool;
default = cfg.source != null;
defaultText = "config.nixpkgs.flake.source != null";
description = mdDoc ''
Whether to set {env}`NIX_PATH` to include `nixpkgs=flake:nixpkgs` such that `<nixpkgs>`
lookups receive the version of nixpkgs that the system was built with, in concert with
{option}`nixpkgs.flake.setFlakeRegistry`.
This is on by default for NixOS configurations built with flakes.
This makes {command}`nix-build '<nixpkgs>' -A hello` work out of the box on flake systems.
Note that this option makes the NixOS closure depend on the nixpkgs sources, which may add
undesired closure size if the system will not have any nix commands run on it.
'';
};
setFlakeRegistry = mkOption {
type = types.bool;
default = cfg.source != null;
defaultText = "config.nixpkgs.flake.source != null";
description = mdDoc ''
Whether to pin nixpkgs in the system-wide flake registry (`/etc/nix/registry.json`) to the
store path of the sources of nixpkgs used to build the NixOS system.
This is on by default for NixOS configurations built with flakes.
This option makes {command}`nix run nixpkgs#hello` reuse dependencies from the system, avoid
refetching nixpkgs, and have a consistent result every time.
Note that this option makes the NixOS closure depend on the nixpkgs sources, which may add
undesired closure size if the system will not have any nix commands run on it.
'';
};
};
config = mkIf (cfg.source != null) (mkMerge [
{
assertions = [
{
assertion = cfg.setNixPath -> cfg.setFlakeRegistry;
message = ''
Setting `nixpkgs.flake.setNixPath` requires that `nixpkgs.flake.setFlakeRegistry` also
be set, since it is implemented in terms of indirection through the flake registry.
'';
}
];
}
(mkIf cfg.setFlakeRegistry {
nix.registry.nixpkgs.to = mkDefault {
type = "path";
path = cfg.source;
};
})
(mkIf cfg.setNixPath {
# N.B. This does not include nixos-config in NIX_PATH unlike modules/config/nix-channel.nix
# because we would need some kind of evil shim taking the *calling* flake's self path,
# perhaps, to ever make that work (in order to know where the Nix expr for the system came
# from and how to call it).
nix.nixPath = mkDefault ([ "nixpkgs=flake:nixpkgs" ]
++ optional config.nix.channel.enable "/nix/var/nix/profiles/per-user/root/channels");
})
]);
}

View file

@ -5,17 +5,21 @@ let
opt = options.system.nixos;
inherit (lib)
concatStringsSep mapAttrsToList toLower
concatStringsSep mapAttrsToList toLower optionalString
literalExpression mkRenamedOptionModule mkDefault mkOption trivial types;
needsEscaping = s: null != builtins.match "[a-zA-Z0-9]+" s;
escapeIfNecessary = s: if needsEscaping s then s else ''"${lib.escape [ "\$" "\"" "\\" "\`" ] s}"'';
attrsToText = attrs:
concatStringsSep "\n" (
mapAttrsToList (n: v: ''${n}=${escapeIfNecessary (toString v)}'') attrs
) + "\n";
concatStringsSep "\n"
(mapAttrsToList (n: v: ''${n}=${escapeIfNecessary (toString v)}'') attrs)
+ "\n";
osReleaseContents = {
osReleaseContents =
let
isNixos = cfg.distroId == "nixos";
in
{
NAME = "${cfg.distroName}";
ID = "${cfg.distroId}";
VERSION = "${cfg.release} (${cfg.codeName})";
@ -24,12 +28,13 @@ let
BUILD_ID = cfg.version;
PRETTY_NAME = "${cfg.distroName} ${cfg.release} (${cfg.codeName})";
LOGO = "nix-snowflake";
HOME_URL = lib.optionalString (cfg.distroId == "nixos") "https://nixos.org/";
DOCUMENTATION_URL = lib.optionalString (cfg.distroId == "nixos") "https://nixos.org/learn.html";
SUPPORT_URL = lib.optionalString (cfg.distroId == "nixos") "https://nixos.org/community.html";
BUG_REPORT_URL = lib.optionalString (cfg.distroId == "nixos") "https://github.com/NixOS/nixpkgs/issues";
IMAGE_ID = lib.optionalString (config.system.image.id != null) config.system.image.id;
IMAGE_VERSION = lib.optionalString (config.system.image.version != null) config.system.image.version;
HOME_URL = optionalString isNixos "https://nixos.org/";
DOCUMENTATION_URL = optionalString isNixos "https://nixos.org/learn.html";
SUPPORT_URL = optionalString isNixos "https://nixos.org/community.html";
BUG_REPORT_URL = optionalString isNixos "https://github.com/NixOS/nixpkgs/issues";
ANSI_COLOR = optionalString isNixos "1;34";
IMAGE_ID = optionalString (config.system.image.id != null) config.system.image.id;
IMAGE_VERSION = optionalString (config.system.image.version != null) config.system.image.version;
} // lib.optionalAttrs (cfg.variant_id != null) {
VARIANT_ID = cfg.variant_id;
};
@ -56,61 +61,62 @@ in
};
options.system = {
nixos.version = mkOption {
nixos = {
version = mkOption {
internal = true;
type = types.str;
description = lib.mdDoc "The full NixOS version (e.g. `16.03.1160.f2d4ee1`).";
};
nixos.release = mkOption {
release = mkOption {
readOnly = true;
type = types.str;
default = trivial.release;
description = lib.mdDoc "The NixOS release (e.g. `16.03`).";
};
nixos.versionSuffix = mkOption {
versionSuffix = mkOption {
internal = true;
type = types.str;
default = trivial.versionSuffix;
description = lib.mdDoc "The NixOS version suffix (e.g. `1160.f2d4ee1`).";
};
nixos.revision = mkOption {
revision = mkOption {
internal = true;
type = types.nullOr types.str;
default = trivial.revisionWithDefault null;
description = lib.mdDoc "The Git revision from which this NixOS configuration was built.";
};
nixos.codeName = mkOption {
codeName = mkOption {
readOnly = true;
type = types.str;
default = trivial.codeName;
description = lib.mdDoc "The NixOS release code name (e.g. `Emu`).";
};
nixos.distroId = mkOption {
distroId = mkOption {
internal = true;
type = types.str;
default = "nixos";
description = lib.mdDoc "The id of the operating system";
};
nixos.distroName = mkOption {
distroName = mkOption {
internal = true;
type = types.str;
default = "NixOS";
description = lib.mdDoc "The name of the operating system";
};
nixos.variant_id = mkOption {
variant_id = mkOption {
type = types.nullOr (types.strMatching "^[a-z0-9._-]+$");
default = null;
description = lib.mdDoc "A lower-case string identifying a specific variant or edition of the operating system";
example = "installer";
};
};
image = {

View file

@ -133,6 +133,7 @@
./misc/meta.nix
./misc/nixops-autoluks.nix
./misc/nixpkgs.nix
./misc/nixpkgs-flake.nix
./misc/passthru.nix
./misc/version.nix
./misc/wordlist.nix
@ -241,6 +242,7 @@
./programs/proxychains.nix
./programs/qdmr.nix
./programs/qt5ct.nix
./programs/quark-goldleaf.nix
./programs/regreet.nix
./programs/rog-control-center.nix
./programs/rust-motd.nix
@ -317,7 +319,6 @@
./security/oath.nix
./security/pam.nix
./security/pam_mount.nix
./security/pam_usb.nix
./security/please.nix
./security/polkit.nix
./security/rngd.nix
@ -411,7 +412,6 @@
./services/continuous-integration/buildbot/worker.nix
./services/continuous-integration/buildkite-agents.nix
./services/continuous-integration/gitea-actions-runner.nix
./services/continuous-integration/github-runner.nix
./services/continuous-integration/github-runners.nix
./services/continuous-integration/gitlab-runner.nix
./services/continuous-integration/gocd-agent/default.nix
@ -547,6 +547,8 @@
./services/hardware/kanata.nix
./services/hardware/lcd.nix
./services/hardware/lirc.nix
./services/hardware/nvidia-container-toolkit-cdi-generator
./services/hardware/monado.nix
./services/hardware/nvidia-optimus.nix
./services/hardware/openrgb.nix
./services/hardware/pcscd.nix
@ -579,6 +581,7 @@
./services/home-automation/ebusd.nix
./services/home-automation/esphome.nix
./services/home-automation/evcc.nix
./services/home-automation/govee2mqtt.nix
./services/home-automation/home-assistant.nix
./services/home-automation/homeassistant-satellite.nix
./services/home-automation/zigbee2mqtt.nix
@ -840,6 +843,7 @@
./services/monitoring/riemann.nix
./services/monitoring/rustdesk-server.nix
./services/monitoring/scollector.nix
./services/monitoring/scrutiny.nix
./services/monitoring/smartd.nix
./services/monitoring/snmpd.nix
./services/monitoring/statsd.nix
@ -898,7 +902,6 @@
./services/networking/autossh.nix
./services/networking/avahi-daemon.nix
./services/networking/babeld.nix
./services/networking/bee-clef.nix
./services/networking/bee.nix
./services/networking/biboumi.nix
./services/networking/bind.nix
@ -963,6 +966,7 @@
./services/networking/gns3-server.nix
./services/networking/gnunet.nix
./services/networking/go-autoconfig.nix
./services/networking/go-camo.nix
./services/networking/go-neb.nix
./services/networking/go-shadowsocks2.nix
./services/networking/gobgpd.nix
@ -1320,6 +1324,7 @@
./services/web-apps/mastodon.nix
./services/web-apps/matomo.nix
./services/web-apps/mattermost.nix
./services/web-apps/mealie.nix
./services/web-apps/mediawiki.nix
./services/web-apps/meme-bingo-web.nix
./services/web-apps/microbin.nix
@ -1348,7 +1353,6 @@
./services/web-apps/powerdns-admin.nix
./services/web-apps/pretalx.nix
./services/web-apps/prosody-filer.nix
./services/web-apps/restya-board.nix
./services/web-apps/rimgo.nix
./services/web-apps/sftpgo.nix
./services/web-apps/suwayomi-server.nix
@ -1402,7 +1406,6 @@
./services/web-servers/unit/default.nix
./services/web-servers/uwsgi.nix
./services/web-servers/varnish/default.nix
./services/web-servers/zope2.nix
./services/x11/clight.nix
./services/x11/colord.nix
./services/x11/desktop-managers/default.nix
@ -1527,6 +1530,7 @@
./tasks/filesystems/jfs.nix
./tasks/filesystems/nfs.nix
./tasks/filesystems/ntfs.nix
./tasks/filesystems/overlayfs.nix
./tasks/filesystems/reiserfs.nix
./tasks/filesystems/sshfs.nix
./tasks/filesystems/squashfs.nix

View file

@ -1,35 +1,43 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.programs.ccache;
in {
options.programs.ccache = {
# host configuration
enable = mkEnableOption (lib.mdDoc "CCache");
cacheDir = mkOption {
type = types.path;
enable = lib.mkEnableOption (lib.mdDoc "CCache");
cacheDir = lib.mkOption {
type = lib.types.path;
description = lib.mdDoc "CCache directory";
default = "/var/cache/ccache";
};
# target configuration
packageNames = mkOption {
type = types.listOf types.str;
packageNames = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = lib.mdDoc "Nix top-level packages to be compiled using CCache";
default = [];
example = [ "wxGTK32" "ffmpeg" "libav_all" ];
};
owner = lib.mkOption {
type = lib.types.str;
default = "root";
description = lib.mdDoc "Owner of CCache directory";
};
group = lib.mkOption {
type = lib.types.str;
default = "nixbld";
description = lib.mdDoc "Group owner of CCache directory";
};
};
config = mkMerge [
config = lib.mkMerge [
# host configuration
(mkIf cfg.enable {
systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 root nixbld -" ];
(lib.mkIf cfg.enable {
systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 ${cfg.owner} ${cfg.group} -" ];
# "nix-ccache --show-stats" and "nix-ccache --clear"
security.wrappers.nix-ccache = {
owner = "root";
group = "nixbld";
inherit (cfg) owner group;
setuid = false;
setgid = true;
source = pkgs.writeScript "nix-ccache.pl" ''
@ -50,9 +58,9 @@ in {
})
# target configuration
(mkIf (cfg.packageNames != []) {
(lib.mkIf (cfg.packageNames != []) {
nixpkgs.overlays = [
(self: super: genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; }))
(self: super: lib.genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; }))
(self: super: {
ccacheWrapper = super.ccacheWrapper.override {
@ -65,7 +73,7 @@ in {
echo "Directory '$CCACHE_DIR' does not exist"
echo "Please create it with:"
echo " sudo mkdir -m0770 '$CCACHE_DIR'"
echo " sudo chown root:nixbld '$CCACHE_DIR'"
echo " sudo chown ${cfg.owner}:${cfg.group} '$CCACHE_DIR'"
echo "====="
exit 1
fi

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
with lib;
@ -21,8 +21,12 @@ in
programs.chromium = {
enable = mkEnableOption (lib.mdDoc "{command}`chromium` policies");
enablePlasmaBrowserIntegration = mkEnableOption (lib.mdDoc "Native Messaging Host for Plasma Browser Integration");
plasmaBrowserIntegrationPackage = mkPackageOption pkgs [ "plasma5Packages" "plasma-browser-integration" ] { };
extensions = mkOption {
type = types.listOf types.str;
type = with types; nullOr (listOf str);
description = lib.mdDoc ''
List of chromium extensions to install.
For list of plugins ids see id in url of extensions on
@ -33,7 +37,7 @@ in
[ExtensionInstallForcelist](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ExtensionInstallForcelist)
for additional details.
'';
default = [];
default = null;
example = literalExpression ''
[
"chlffgpmiacpedhhbkiomidkjlcfhogd" # pushbullet
@ -62,16 +66,14 @@ in
type = types.nullOr types.str;
description = lib.mdDoc "Chromium default search provider url.";
default = null;
example =
"https://encrypted.google.com/search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}";
example = "https://encrypted.google.com/search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}";
};
defaultSearchProviderSuggestURL = mkOption {
type = types.nullOr types.str;
description = lib.mdDoc "Chromium default search provider url for suggestions.";
default = null;
example =
"https://encrypted.google.com/complete/search?output=chrome&q={searchTerms}";
example = "https://encrypted.google.com/complete/search?output=chrome&q={searchTerms}";
};
extraOpts = mkOption {
@ -101,15 +103,21 @@ in
###### implementation
config = lib.mkIf cfg.enable {
config = {
environment.etc = lib.mkIf cfg.enable {
# for chromium
environment.etc."chromium/policies/managed/default.json".text = builtins.toJSON defaultProfile;
environment.etc."chromium/policies/managed/extra.json".text = builtins.toJSON cfg.extraOpts;
"chromium/native-messaging-hosts/org.kde.plasma.browser_integration.json" = lib.mkIf cfg.enablePlasmaBrowserIntegration
{ source = "${cfg.plasmaBrowserIntegrationPackage}/etc/chromium/native-messaging-hosts/org.kde.plasma.browser_integration.json"; };
"chromium/policies/managed/default.json" = lib.mkIf (defaultProfile != {}) { text = builtins.toJSON defaultProfile; };
"chromium/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != {}) { text = builtins.toJSON cfg.extraOpts; };
# for google-chrome https://www.chromium.org/administrators/linux-quick-start
environment.etc."opt/chrome/policies/managed/default.json".text = builtins.toJSON defaultProfile;
environment.etc."opt/chrome/policies/managed/extra.json".text = builtins.toJSON cfg.extraOpts;
"opt/chrome/native-messaging-hosts/org.kde.plasma.browser_integration.json" = lib.mkIf cfg.enablePlasmaBrowserIntegration
{ source = "${cfg.plasmaBrowserIntegrationPackage}/etc/opt/chrome/native-messaging-hosts/org.kde.plasma.browser_integration.json"; };
"opt/chrome/policies/managed/default.json" = lib.mkIf (defaultProfile != {}) { text = builtins.toJSON defaultProfile; };
"opt/chrome/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != {}) { text = builtins.toJSON cfg.extraOpts; };
# for brave
environment.etc."brave/policies/managed/default.json".text = builtins.toJSON defaultProfile;
environment.etc."brave/policies/managed/extra.json".text = builtins.toJSON cfg.extraOpts;
"brave/policies/managed/default.json" = lib.mkIf (defaultProfile != {}) { text = builtins.toJSON defaultProfile; };
"brave/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != {}) { text = builtins.toJSON cfg.extraOpts; };
};
};
}

View file

@ -15,6 +15,7 @@ let
defaultPinentryFlavor =
if xserverCfg.desktopManager.lxqt.enable
|| xserverCfg.desktopManager.plasma5.enable
|| xserverCfg.desktopManager.plasma6.enable
|| xserverCfg.desktopManager.deepin.enable then
"qt"
else if xserverCfg.desktopManager.xfce.enable then

View file

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.quark-goldleaf;
in
{
options = {
programs.quark-goldleaf = {
enable = lib.mkEnableOption "quark-goldleaf with udev rules applied";
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ pkgs.quark-goldleaf ];
services.udev.packages = [ pkgs.quark-goldleaf ];
};
meta.maintainers = pkgs.quark-goldleaf.meta.maintainers;
}

View file

@ -82,6 +82,14 @@ in {
'';
};
localNetworkGameTransfers.openFirewall = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Open ports in the firewall for Steam Local Network Game Transfers.
'';
};
gamescopeSession = mkOption {
description = mdDoc "Run a GameScope driven Steam session from your display-manager";
default = {};
@ -139,15 +147,23 @@ in {
] ++ lib.optional cfg.gamescopeSession.enable steam-gamescope;
networking.firewall = lib.mkMerge [
(mkIf (cfg.remotePlay.openFirewall || cfg.localNetworkGameTransfers.openFirewall) {
allowedUDPPorts = [ 27036 ]; # Peer discovery
})
(mkIf cfg.remotePlay.openFirewall {
allowedTCPPorts = [ 27036 ];
allowedUDPPortRanges = [ { from = 27031; to = 27036; } ];
allowedUDPPortRanges = [ { from = 27031; to = 27035; } ];
})
(mkIf cfg.dedicatedServer.openFirewall {
allowedTCPPorts = [ 27015 ]; # SRCDS Rcon port
allowedUDPPorts = [ 27015 ]; # Gameplay traffic
})
(mkIf cfg.localNetworkGameTransfers.openFirewall {
allowedTCPPorts = [ 27040 ]; # Data transfers
})
];
};

View file

@ -119,10 +119,10 @@ in {
extraPackages = mkOption {
type = with types; listOf package;
default = with pkgs; [
swaylock swayidle foot dmenu
swaylock swayidle foot dmenu wmenu
];
defaultText = literalExpression ''
with pkgs; [ swaylock swayidle foot dmenu ];
with pkgs; [ swaylock swayidle foot dmenu wmenu ];
'';
example = literalExpression ''
with pkgs; [

View file

@ -22,7 +22,7 @@ in
description = lib.mdDoc ''
Configuration included in `${name}.toml`.
See https://github.com/sxyazi/yazi/blob/v${cfg.package.version}/config/docs/${name}.md for documentation.
See https://yazi-rs.github.io/docs/configuration/${name}/ for documentation.
'';
}))
names);
@ -47,7 +47,5 @@ in
};
meta = {
maintainers = with lib.maintainers; [ linsui ];
# The version of the package is used in the doc.
buildDocsInSandbox = false;
};
}

View file

@ -112,6 +112,7 @@ in
(mkRemovedOptionModule [ "services" "cryptpad" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "rtsp-simple-server" ] "Package has been completely rebranded by upstream as mediamtx, and thus the service and the package were renamed in NixOS as well.")
(mkRemovedOptionModule [ "services" "prayer" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "restya-board" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "i18n" "inputMethod" "fcitx" ] "The fcitx module has been removed. Please use fcitx5 instead")
(mkRemovedOptionModule [ "services" "dhcpd4" ] ''

View file

@ -11,7 +11,8 @@ let
extraCertificateFiles = cfg.certificateFiles;
extraCertificateStrings = cfg.certificates;
};
caBundle = "${cacertPackage}/etc/ssl/certs/ca-bundle.crt";
caBundleName = if cfg.useCompatibleBundle then "ca-no-trust-rules-bundle.crt" else "ca-bundle.crt";
caBundle = "${cacertPackage}/etc/ssl/certs/${caBundleName}";
in
@ -23,6 +24,17 @@ in
internal = true;
};
security.pki.useCompatibleBundle = mkEnableOption ''usage of a compatibility bundle.
Such a bundle consist exclusively of `BEGIN CERTIFICATE` and no `BEGIN TRUSTED CERTIFICATE`,
which is a OpenSSL specific PEM format.
It is known to be incompatible with certain software stacks.
Nevertheless, enabling this will strip all additional trust rules provided by the
certificates themselves, this can have security consequences depending on your usecases.
'';
security.pki.certificateFiles = mkOption {
type = types.listOf types.path;
default = [];

View file

@ -96,6 +96,10 @@ let
pamOpts = { config, name, ... }: let cfg = config; in let config = parentConfig; in {
imports = [
(lib.mkRenamedOptionModule [ "enableKwallet" ] [ "kwallet" "enable" ])
];
options = {
name = mkOption {
@ -205,17 +209,6 @@ let
};
};
usbAuth = mkOption {
default = config.security.pam.usb.enable;
defaultText = literalExpression "config.security.pam.usb.enable";
type = types.bool;
description = lib.mdDoc ''
If set, users listed in
{file}`/etc/pamusb.conf` are able to log in
with the associated USB key.
'';
};
otpwAuth = mkOption {
default = config.security.pam.enableOTPW;
defaultText = literalExpression "config.security.pam.enableOTPW";
@ -473,7 +466,8 @@ let
'';
};
enableKwallet = mkOption {
kwallet = {
enable = mkOption {
default = false;
type = types.bool;
description = lib.mdDoc ''
@ -483,6 +477,12 @@ let
password, KDE will prompt separately after login.
'';
};
package = mkPackageOption pkgs.plasma5Packages "kwallet-pam" {
pkgsText = "pkgs.plasma5Packages";
};
};
sssdStrictAccess = mkOption {
default = false;
type = types.bool;
@ -665,7 +665,6 @@ let
authfile = u2f.authFile;
appid = u2f.appId;
}; })
{ name = "usb"; enable = cfg.usbAuth; control = "sufficient"; modulePath = "${pkgs.pam_usb}/lib/security/pam_usb.so"; }
(let ussh = config.security.pam.ussh; in { name = "ussh"; enable = config.security.pam.ussh.enable && cfg.usshAuth; control = ussh.control; modulePath = "${pkgs.pam_ussh}/lib/security/pam_ussh.so"; settings = {
ca_file = ussh.caFile;
authorized_principals = ussh.authorizedPrincipals;
@ -698,7 +697,7 @@ let
(config.security.pam.enableEcryptfs
|| config.security.pam.enableFscrypt
|| cfg.pamMount
|| cfg.enableKwallet
|| cfg.kwallet.enable
|| cfg.enableGnomeKeyring
|| config.services.intune.enable
|| cfg.googleAuthenticator.enable
@ -723,9 +722,7 @@ let
{ name = "mount"; enable = cfg.pamMount; control = "optional"; modulePath = "${pkgs.pam_mount}/lib/security/pam_mount.so"; settings = {
disable_interactive = true;
}; }
{ name = "kwallet5"; enable = cfg.enableKwallet; control = "optional"; modulePath = "${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so"; settings = {
kwalletd = "${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5";
}; }
{ name = "kwallet"; enable = cfg.kwallet.enable; control = "optional"; modulePath = "${cfg.kwallet.package}/lib/security/pam_kwallet5.so"; }
{ name = "gnome_keyring"; enable = cfg.enableGnomeKeyring; control = "optional"; modulePath = "${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"; }
{ name = "intune"; enable = config.services.intune.enable; control = "optional"; modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so"; }
{ name = "gnupg"; enable = cfg.gnupg.enable; control = "optional"; modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"; settings = {
@ -860,9 +857,7 @@ let
order = "user,group,default";
debug = true;
}; }
{ name = "kwallet5"; enable = cfg.enableKwallet; control = "optional"; modulePath = "${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so"; settings = {
kwalletd = "${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5";
}; }
{ name = "kwallet"; enable = cfg.kwallet.enable; control = "optional"; modulePath = "${cfg.kwallet.package}/lib/security/pam_kwallet5.so"; }
{ name = "gnome_keyring"; enable = cfg.enableGnomeKeyring; control = "optional"; modulePath = "${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"; settings = {
auto_start = true;
}; }

View file

@ -1,51 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.security.pam.usb;
anyUsbAuth = any (attrByPath ["usbAuth"] false) (attrValues config.security.pam.services);
in
{
options = {
security.pam.usb = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Enable USB login for all login systems that support it. For
more information, visit <https://github.com/aluzzardi/pam_usb/wiki/Getting-Started#setting-up-devices-and-users>.
'';
};
};
};
config = mkIf (cfg.enable || anyUsbAuth) {
# Make sure pmount and pumount are setuid wrapped.
security.wrappers = {
pmount =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount.out}/bin/pmount";
};
pumount =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount.out}/bin/pumount";
};
};
environment.systemPackages = [ pkgs.pmount ];
};
}

View file

@ -285,7 +285,7 @@ in {
systemd.tmpfiles.rules = [
"d /opt/cni/bin 0755 root root -"
"d /run/kubernetes 0755 kubernetes kubernetes -"
"d /var/lib/kubernetes 0755 kubernetes kubernetes -"
"d ${cfg.dataDir} 0755 kubernetes kubernetes -"
];
users.users.kubernetes = {
@ -294,6 +294,7 @@ in {
group = "kubernetes";
home = cfg.dataDir;
createHome = true;
homeMode = "755";
};
users.groups.kubernetes.gid = config.ids.gids.kubernetes;

View file

@ -33,6 +33,41 @@ let
kubeconfig = top.lib.mkKubeConfig "kubelet" cfg.kubeconfig;
# Flag based settings are deprecated, use the `--config` flag with a
# `KubeletConfiguration` struct.
# https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/
#
# NOTE: registerWithTaints requires a []core/v1.Taint, therefore requires
# additional work to be put in config format.
#
kubeletConfig = pkgs.writeText "kubelet-config" (builtins.toJSON ({
apiVersion = "kubelet.config.k8s.io/v1beta1";
kind = "KubeletConfiguration";
address = cfg.address;
port = cfg.port;
authentication = {
x509 = lib.optionalAttrs (cfg.clientCaFile != null) { clientCAFile = cfg.clientCaFile; };
webhook = {
enabled = true;
cacheTTL = "10s";
};
};
authorization = {
mode = "Webhook";
};
cgroupDriver = "systemd";
hairpinMode = "hairpin-veth";
registerNode = cfg.registerNode;
containerRuntimeEndpoint = cfg.containerRuntimeEndpoint;
healthzPort = cfg.healthz.port;
healthzBindAddress = cfg.healthz.bind;
} // lib.optionalAttrs (cfg.tlsCertFile != null) { tlsCertFile = cfg.tlsCertFile; }
// lib.optionalAttrs (cfg.tlsKeyFile != null) { tlsPrivateKeyFile = cfg.tlsKeyFile; }
// lib.optionalAttrs (cfg.clusterDomain != "") { clusterDomain = cfg.clusterDomain; }
// lib.optionalAttrs (cfg.clusterDns != "") { clusterDNS = [ cfg.clusterDns ] ; }
// lib.optionalAttrs (cfg.featureGates != []) { featureGates = cfg.featureGates; }
));
manifestPath = "kubernetes/manifests";
taintOptions = with lib.types; { name, ... }: {
@ -294,21 +329,7 @@ in
Restart = "on-failure";
RestartSec = "1000ms";
ExecStart = ''${top.package}/bin/kubelet \
--address=${cfg.address} \
--authentication-token-webhook \
--authentication-token-webhook-cache-ttl="10s" \
--authorization-mode=Webhook \
${optionalString (cfg.clientCaFile != null)
"--client-ca-file=${cfg.clientCaFile}"} \
${optionalString (cfg.clusterDns != "")
"--cluster-dns=${cfg.clusterDns}"} \
${optionalString (cfg.clusterDomain != "")
"--cluster-domain=${cfg.clusterDomain}"} \
${optionalString (cfg.featureGates != [])
"--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
--hairpin-mode=hairpin-veth \
--healthz-bind-address=${cfg.healthz.bind} \
--healthz-port=${toString cfg.healthz.port} \
--config=${kubeletConfig} \
--hostname-override=${cfg.hostname} \
--kubeconfig=${kubeconfig} \
${optionalString (cfg.nodeIp != null)
@ -316,18 +337,10 @@ in
--pod-infra-container-image=pause \
${optionalString (cfg.manifests != {})
"--pod-manifest-path=/etc/${manifestPath}"} \
--port=${toString cfg.port} \
--register-node=${boolToString cfg.registerNode} \
${optionalString (taints != "")
"--register-with-taints=${taints}"} \
--root-dir=${top.dataDir} \
${optionalString (cfg.tlsCertFile != null)
"--tls-cert-file=${cfg.tlsCertFile}"} \
${optionalString (cfg.tlsKeyFile != null)
"--tls-private-key-file=${cfg.tlsKeyFile}"} \
${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
--container-runtime-endpoint=${cfg.containerRuntimeEndpoint} \
--cgroup-driver=systemd \
${cfg.extraOpts}
'';
WorkingDirectory = top.dataDir;

View file

@ -174,7 +174,7 @@ in
'')
(optionalString cfg.genCfsslAPIToken ''
if [ ! -f "${cfsslAPITokenPath}" ]; then
install -u cfssl -m 400 <(head -c ${toString (cfsslAPITokenLength / 2)} /dev/urandom | od -An -t x | tr -d ' ') "${cfsslAPITokenPath}"
install -o cfssl -m 400 <(head -c ${toString (cfsslAPITokenLength / 2)} /dev/urandom | od -An -t x | tr -d ' ') "${cfsslAPITokenPath}"
fi
'')]);
@ -192,7 +192,8 @@ in
mkdir -p "$(dirname "${certmgrAPITokenPath}")"
if [ -f "${cfsslAPITokenPath}" ]; then
ln -fs "${cfsslAPITokenPath}" "${certmgrAPITokenPath}"
else
elif [ ! -f "${certmgrAPITokenPath}" ]; then
# Don't remove the token if it already exists
install -m 600 /dev/null "${certmgrAPITokenPath}"
fi
''
@ -219,7 +220,6 @@ in
inherit (cert) action;
authority = {
inherit remote;
file.path = cert.caCert;
root_ca = cert.caCert;
profile = "default";
auth_key_file = certmgrAPITokenPath;

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