Project import generated by Copybara.

GitOrigin-RevId: d42cd445dde587e9a993cd9434cb43da07c4c5de
This commit is contained in:
Default email 2021-05-20 18:08:51 -05:00
parent 315dd253af
commit 3e2acf8aff
3247 changed files with 98787 additions and 50318 deletions

View file

@ -79,11 +79,13 @@
/pkgs/development/tools/poetry2nix @adisbladis
# Haskell
/pkgs/development/compilers/ghc @cdepillabout @sternenseemann
/pkgs/development/haskell-modules @cdepillabout @sternenseemann
/pkgs/development/haskell-modules/default.nix @cdepillabout @sternenseemann
/pkgs/development/haskell-modules/generic-builder.nix @cdepillabout @sternenseemann
/pkgs/development/haskell-modules/hoogle.nix @cdepillabout @sternenseemann
/doc/languages-frameworks/haskell.section.md @cdepillabout @sternenseemann @maralorn
/maintainers/scripts/haskell @cdepillabout @sternenseemann @maralorn
/pkgs/development/compilers/ghc @cdepillabout @sternenseemann @maralorn
/pkgs/development/haskell-modules @cdepillabout @sternenseemann @maralorn
/pkgs/test/haskell @cdepillabout @sternenseemann @maralorn
/pkgs/top-level/release-haskell.nix @cdepillabout @sternenseemann @maralorn
/pkgs/top-level/haskell-packages.nix @cdepillabout @sternenseemann @maralorn
# Perl
/pkgs/development/interpreters/perl @volth @stigtsp

View file

@ -36,11 +36,11 @@
"6.topic: GNOME":
- doc/languages-frameworks/gnome.section.md
- nixos/modules/services/desktops/gnome3/**/*
- nixos/modules/services/x11/desktop-managers/gnome3.nix
- nixos/tests/gnome3-xorg.nix
- nixos/tests/gnome3.nix
- pkgs/desktops/gnome-3/**/*
- nixos/modules/services/desktops/gnome/**/*
- nixos/modules/services/x11/desktop-managers/gnome.nix
- nixos/tests/gnome-xorg.nix
- nixos/tests/gnome.nix
- pkgs/desktops/gnome/**/*
"6.topic: golang":
- doc/languages-frameworks/go.section.md
@ -50,10 +50,13 @@
"6.topic: haskell":
- doc/languages-frameworks/haskell.section.md
- maintainers/scripts/haskell/**/*
- pkgs/development/compilers/ghc/**/*
- pkgs/development/haskell-modules/**/*
- pkgs/development/tools/haskell/**/*
- pkgs/test/haskell/**/*
- pkgs/top-level/haskell-packages.nix
- pkgs/top-level/release-haskell.nix
"6.topic: kernel":
- pkgs/build-support/kernel/**/*

View file

@ -14,6 +14,7 @@ jobs:
- uses: actions/checkout@v2
- name: Merge master into staging-next
id: staging_next
uses: devmasx/merge-branch@v1.3.1
with:
type: now
@ -22,6 +23,7 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Merge staging-next into staging
id: staging
uses: devmasx/merge-branch@v1.3.1
with:
type: now
@ -35,5 +37,5 @@ jobs:
with:
issue-number: 105153
body: |
An automatic merge [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).
An automatic merge${{ (steps.staging_next.outcome == 'failure' && ' from master to staging-next') || ((steps.staging.outcome == 'failure' && ' from staging-next to staging') || '') }} [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).

View file

@ -1,15 +1,17 @@
# pkgs.mkShell {#sec-pkgs-mkShell}
`pkgs.mkShell` is a special kind of derivation that is only useful when using it combined with `nix-shell`. It will in fact fail to instantiate when invoked with `nix-build`.
`pkgs.mkShell` is a special kind of derivation that is only useful when using
it combined with `nix-shell`. It will in fact fail to instantiate when invoked
with `nix-build`.
## Usage {#sec-pkgs-mkShell-usage}
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar
# available to the shell environment
# specify which packages to add to the shell environment
packages = [ pkgs.gnumake ];
# add all the dependencies, of the given packages, to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
```

View file

@ -50,3 +50,50 @@ Many more commands wrap `writeTextFile` including `writeText`, `writeTextDir`, `
## `symlinkJoin` {#trivial-builder-symlinkJoin}
This can be used to put many derivations into the same directory structure. It works by creating a new derivation and adding symlinks to each of the paths listed. It expects two arguments, `name`, and `paths`. `name` is the name used in the Nix store path for the created derivation. `paths` is a list of paths that will be symlinked. These paths can be to Nix store derivations or any other subdirectory contained within.
## `writeReferencesToFile` {#trivial-builder-writeReferencesToFile}
Writes the closure of transitive dependencies to a file.
This produces the equivalent of `nix-store -q --requisites`.
For example,
```nix
writeReferencesToFile (writeScriptBin "hi" ''${hello}/bin/hello'')
```
produces an output path `/nix/store/<hash>-runtime-deps` containing
```nix
/nix/store/<hash>-hello-2.10
/nix/store/<hash>-hi
/nix/store/<hash>-libidn2-2.3.0
/nix/store/<hash>-libunistring-0.9.10
/nix/store/<hash>-glibc-2.32-40
```
You can see that this includes `hi`, the original input path,
`hello`, which is a direct reference, but also
the other paths that are indirectly required to run `hello`.
## `writeDirectReferencesToFile` {#trivial-builder-writeDirectReferencesToFile}
Writes the set of references to the output file, that is, their immediate dependencies.
This produces the equivalent of `nix-store -q --references`.
For example,
```nix
writeDirectReferencesToFile (writeScriptBin "hi" ''${hello}/bin/hello'')
```
produces an output path `/nix/store/<hash>-runtime-references` containing
```nix
/nix/store/<hash>-hello-2.10
```
but none of `hello`'s dependencies, because those are not referenced directly
by `hi`'s output.

View file

@ -169,6 +169,18 @@
})
```
- Unnecessary string conversions should be avoided. Do
```nix
rev = version;
```
instead of
```nix
rev = "${version}";
```
- Arguments should be listed in the order they are used, with the exception of `lib`, which always goes first.
- The top-level `lib` must be used in the master and 21.05 branch over its alias `stdenv.lib` as it now causes evaluation errors when aliases are disabled which is the case for ofborg.

View file

@ -855,7 +855,7 @@ lib.attrsets.mapAttrs' (name: value: lib.attrsets.nameValuePair ("foo_" + name)
<title><function>lib.attrsets.mapAttrsToList</function></title>
<subtitle><literal>mapAttrsToList :: (String -> Any -> Any) ->
AttrSet -> Any</literal>
AttrSet -> [Any]</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.mapAttrsToList" />

View file

@ -24,12 +24,18 @@ Many Erlang/OTP distributions available in `beam.interpreters` have versions wit
We provide a version of Rebar3, under `rebar3`. We also provide a helper to fetch Rebar3 dependencies from a lockfile under `fetchRebar3Deps`.
We also provide a version on Rebar3 with plugins included, under `rebar3WithPlugins`. This package is a function which takes two arguments: `plugins`, a list of nix derivations to include as plugins (loaded only when specified in `rebar.config`), and `globalPlugins`, which should always be loaded by rebar3. Example: `rebar3WithPlugins { globalPlugins = [beamPackages.pc]; }`.
When adding a new plugin it is important that the `packageName` attribute is the same as the atom used by rebar3 to refer to the plugin.
### Mix & Erlang.mk {#build-tools-other}
Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation.
For Elixir applications use `mixRelease` to make a release. See examples for more details.
There is also a `buildMix` helper, whose behavior is closer to that of `buildErlangMk` and `buildRebar3`. The primary difference is that mixRelease makes a release, while buildMix only builds the package, making it useful for libraries and other dependencies.
## How to Install BEAM Packages {#how-to-install-beam-packages}
BEAM builders are not registered at the top level, simply because they are not relevant to the vast majority of Nix users. To install any of those builders into your profile, refer to them by their attribute path `beamPackages.rebar3`:

View file

@ -0,0 +1,432 @@
# Dhall {#sec-language-dhall}
The Nixpkgs support for Dhall assumes some familiarity with Dhall's language
support for importing Dhall expressions, which is documented here:
* [`dhall-lang.org` - Installing packages](https://docs.dhall-lang.org/tutorials/Language-Tour.html#installing-packages)
## Remote imports {#ssec-dhall-remote-imports}
Nixpkgs bypasses Dhall's support for remote imports using Dhall's
semantic integrity checks. Specifically, any Dhall import can be protected by
an integrity check like:
```dhall
https://prelude.dhall-lang.org/v20.1.0/package.dhall
sha256:26b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
```
… and if the import is cached then the interpreter will load the import from
cache instead of fetching the URL.
Nixpkgs uses this trick to add all of a Dhall expression's dependencies into the
cache so that the Dhall interpreter never needs to resolve any remote URLs. In
fact, Nixpkgs uses a Dhall interpreter with remote imports disabled when
packaging Dhall expressions to enforce that the interpreter never resolves a
remote import. This means that Nixpkgs only supports building Dhall expressions
if all of their remote imports are protected by semantic integrity checks.
Instead of remote imports, Nixpkgs uses Nix to fetch remote Dhall code. For
example, the Prelude Dhall package uses `pkgs.fetchFromGitHub` to fetch the
`dhall-lang` repository containing the Prelude. Relying exclusively on Nix
to fetch Dhall code ensures that Dhall packages built using Nix remain pure and
also behave well when built within a sandbox.
## Packaging a Dhall expression from scratch {#ssec-dhall-packaging-expression}
We can illustrate how Nixpkgs integrates Dhall by beginning from the following
trivial Dhall expression with one dependency (the Prelude):
```dhall
-- ./true.dhall
let Prelude = https://prelude.dhall-lang.org/v20.1.0/package.dhall
in Prelude.Bool.not False
```
As written, this expression cannot be built using Nixpkgs because the
expression does not protect the Prelude import with a semantic integrity
check, so the first step is to freeze the expression using `dhall freeze`,
like this:
```bash
$ dhall freeze --inplace ./true.dhall
```
… which gives us:
```dhall
-- ./true.dhall
let Prelude =
https://prelude.dhall-lang.org/v20.1.0/package.dhall
sha256:26b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
in Prelude.Bool.not False
```
To package that expression, we create a `./true.nix` file containing the
following specification for the Dhall package:
```nix
# ./true.nix
{ buildDhallPackage, Prelude }:
buildDhallPackage {
name = "true";
code = ./true.dhall;
dependencies = [ Prelude ];
source = true;
}
```
… and we complete the build by incorporating that Dhall package into the
`pkgs.dhallPackages` hierarchy using an overlay, like this:
```nix
# ./example.nix
let
nixpkgs = builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/94b2848559b12a8ed1fe433084686b2a81123c99.tar.gz";
sha256 = "1pbl4c2dsaz2lximgd31m96jwbps6apn3anx8cvvhk1gl9rkg107";
};
dhallOverlay = self: super: {
true = self.callPackage ./true.nix { };
};
overlay = self: super: {
dhallPackages = super.dhallPackages.override (old: {
overrides =
self.lib.composeExtensions (old.overrides or (_: _: {})) dhallOverlay;
});
};
pkgs = import nixpkgs { config = {}; overlays = [ overlay ]; };
in
pkgs
```
… which we can then build using this command:
```bash
$ nix build --file ./example.nix dhallPackages.true
```
## Contents of a Dhall package {#ssec-dhall-package-contents}
The above package produces the following directory tree:
```bash
$ tree -a ./result
result
├── .cache
│   └── dhall
│   └── 122027abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
├── binary.dhall
└── source.dhall
```
… where:
* `source.dhall` contains the result of interpreting our Dhall package:
```bash
$ cat ./result/source.dhall
True
```
* The `.cache` subdirectory contains one binary cache product encoding the
same result as `source.dhall`:
```bash
$ dhall decode < ./result/.cache/dhall/122027abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
True
```
* `binary.dhall` contains a Dhall expression which handles fetching and decoding
the same cache product:
```bash
$ cat ./result/binary.dhall
missing sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
$ cp -r ./result/.cache .cache
$ chmod -R u+w .cache
$ XDG_CACHE_HOME=.cache dhall --file ./result/binary.dhall
True
```
The `source.dhall` file is only present for packages that specify
`source = true;`. By default, Dhall packages omit the `source.dhall` in order
to conserve disk space when they are used exclusively as dependencies. For
example, if we build the Prelude package it will only contain the binary
encoding of the expression:
```bash
$ nix build --file ./example.nix dhallPackages.Prelude
$ tree -a result
result
├── .cache
│   └── dhall
│   └── 122026b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
└── binary.dhall
2 directories, 2 files
```
Typically, you only specify `source = true;` for the top-level Dhall expression
of interest (such as our example `true.nix` Dhall package). However, if you
wish to specify `source = true` for all Dhall packages, then you can amend the
Dhall overlay like this:
```nix
dhallOverrides = self: super: {
# Enable source for all Dhall packages
buildDhallPackage =
args: super.buildDhallPackage (args // { source = true; });
true = self.callPackage ./true.nix { };
};
```
… and now the Prelude will contain the fully decoded result of interpreting
the Prelude:
```bash
$ nix build --file ./example.nix dhallPackages.Prelude
$ tree -a result
result
├── .cache
│   └── dhall
│   └── 122026b0ef498663d269e4dc6a82b0ee289ec565d683ef4c00d0ebdd25333a5a3c98
├── binary.dhall
└── source.dhall
$ cat ./result/source.dhall
{ Bool =
{ and =
\(_ : List Bool) ->
List/fold Bool _ Bool (\(_ : Bool) -> \(_ : Bool) -> _@1 && _) True
, build = \(_ : Type -> _ -> _@1 -> _@2) -> _ Bool True False
, even =
\(_ : List Bool) ->
List/fold Bool _ Bool (\(_ : Bool) -> \(_ : Bool) -> _@1 == _) True
, fold =
\(_ : Bool) ->
```
## Packaging functions {#ssec-dhall-packaging-functions}
We already saw an example of using `buildDhallPackage` to create a Dhall
package from a single file, but most Dhall packages consist of more than one
file and there are two derived utilities that you may find more useful when
packaging multiple files:
* `buildDhallDirectoryPackage` - build a Dhall package from a local directory
* `buildDhallGitHubPackage` - build a Dhall package from a GitHub repository
The `buildDhallPackage` is the lowest-level function and accepts the following
arguments:
* `name`: The name of the derivation
* `dependencies`: Dhall dependencies to build and cache ahead of time
* `code`: The top-level expression to build for this package
Note that the `code` field accepts an arbitrary Dhall expression. You're
not limited to just a file.
* `source`: Set to `true` to include the decoded result as `source.dhall` in the
build product, at the expense of requiring more disk space
* `documentationRoot`: Set to the root directory of the package if you want
`dhall-docs` to generate documentation underneath the `docs` subdirectory of
the build product
The `buildDhallDirectoryPackage` is a higher-level function implemented in terms
of `buildDhallPackage` that accepts the following arguments:
* `name`: Same as `buildDhallPackage`
* `dependencies`: Same as `buildDhallPackage`
* `source`: Same as `buildDhallPackage`
* `src`: The directory containing Dhall code that you want to turn into a Dhall
package
* `file`: The top-level file (`package.dhall` by default) that is the entrypoint
to the rest of the package
* `document`: Set to `true` to generate documentation for the package
The `buildDhallGitHubPackage` is another higher-level function implemented in
terms of `buildDhallPackage` that accepts the following arguments:
* `name`: Same as `buildDhallPackage`
* `dependencies`: Same as `buildDhallPackage`
* `source`: Same as `buildDhallPackage`
* `owner`: The owner of the repository
* `repo`: The repository name
* `rev`: The desired revision (or branch, or tag)
* `directory`: The subdirectory of the Git repository to package (if a
directory other than the root of the repository)
* `file`: The top-level file (`${directory}/package.dhall` by default) that is
the entrypoint to the rest of the package
* `document`: Set to `true` to generate documentation for the package
Additionally, `buildDhallGitHubPackage` accepts the same arguments as
`fetchFromGitHub`, such as `sha256` or `fetchSubmodules`.
## `dhall-to-nixpkgs` {#ssec-dhall-dhall-to-nixpkgs}
You can use the `dhall-to-nixpkgs` command-line utility to automate
packaging Dhall code. For example:
```bash
$ nix-env --install --attr haskellPackages.dhall-nixpkgs
$ nix-env --install --attr nix-prefetch-git # Used by dhall-to-nixpkgs
$ dhall-to-nixpkgs github https://github.com/Gabriel439/dhall-semver.git
{ buildDhallGitHubPackage, Prelude }:
buildDhallGitHubPackage {
name = "dhall-semver";
githubBase = "github.com";
owner = "Gabriel439";
repo = "dhall-semver";
rev = "2d44ae605302ce5dc6c657a1216887fbb96392a4";
fetchSubmodules = false;
sha256 = "0y8shvp8srzbjjpmnsvz9c12ciihnx1szs0yzyi9ashmrjvd0jcz";
directory = "";
file = "package.dhall";
source = false;
document = false;
dependencies = [ (Prelude.overridePackage { file = "package.dhall"; }) ];
}
```
The utility takes care of automatically detecting remote imports and converting
them to package dependencies. You can also use the utility on local
Dhall directories, too:
```bash
$ dhall-to-nixpkgs directory ~/proj/dhall-semver
{ buildDhallDirectoryPackage, Prelude }:
buildDhallDirectoryPackage {
name = "proj";
src = /Users/gabriel/proj/dhall-semver;
file = "package.dhall";
source = false;
document = false;
dependencies = [ (Prelude.overridePackage { file = "package.dhall"; }) ];
}
```
## Overriding dependency versions {#ssec-dhall-overriding-dependency-versions}
Suppose that we change our `true.dhall` example expression to depend on an older
version of the Prelude (19.0.0):
```dhall
-- ./true.dhall
let Prelude =
https://prelude.dhall-lang.org/v19.0.0/package.dhall
sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2
in Prelude.Bool.not False
```
If we try to rebuild that expression the build will fail:
```
$ nix build --file ./example.nix dhallPackages.true
builder for '/nix/store/0f1hla7ff1wiaqyk1r2ky4wnhnw114fi-true.drv' failed with exit code 1; last 10 log lines:
Dhall was compiled without the 'with-http' flag.
The requested URL was: https://prelude.dhall-lang.org/v19.0.0/package.dhall
4│ https://prelude.dhall-lang.org/v19.0.0/package.dhall
5│ sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2
/nix/store/rsab4y99h14912h4zplqx2iizr5n4rc2-true.dhall:4:7
[1 built (1 failed), 0.0 MiB DL]
error: build of '/nix/store/0f1hla7ff1wiaqyk1r2ky4wnhnw114fi-true.drv' failed
```
… because the default Prelude selected by Nixpkgs revision
`94b2848559b12a8ed1fe433084686b2a81123c99is` is version 20.1.0, which doesn't
have the same integrity check as version 19.0.0. This means that version
19.0.0 is not cached and the interpreter is not allowed to fall back to
importing the URL.
However, we can override the default Prelude version by using `dhall-to-nixpkgs`
to create a Dhall package for our desired Prelude:
```bash
$ dhall-to-nixpkgs github https://github.com/dhall-lang/dhall-lang.git \
--name Prelude \
--directory Prelude \
--rev v19.0.0 \
> Prelude.nix
```
… and then referencing that package in our Dhall overlay, by either overriding
the Prelude globally for all packages, like this:
```bash
dhallOverrides = self: super: {
true = self.callPackage ./true.nix { };
Prelude = self.callPackage ./Prelude.nix { };
};
```
… or selectively overriding the Prelude dependency for just the `true` package,
like this:
```bash
dhallOverrides = self: super: {
true = self.callPackage ./true.nix {
Prelude = self.callPackage ./Prelude.nix { };
};
};
```
## Overrides {#ssec-dhall-overrides}
You can override any of the arguments to `buildDhallGitHubPackage` or
`buildDhallDirectoryPackage` using the `overridePackage` attribute of a package.
For example, suppose we wanted to selectively enable `source = true` just for the Prelude. We can do that like this:
```nix
dhallOverrides = self: super: {
Prelude = super.Prelude.overridePackage { source = true; };
};
```
[semantic-integrity-checks]: https://docs.dhall-lang.org/tutorials/Language-Tour.html#installing-packages

View file

@ -10,7 +10,7 @@ with import <nixpkgs> {};
mkShell {
name = "dotnet-env";
buildInputs = [
packages = [
dotnet-sdk_3
];
}
@ -25,7 +25,7 @@ with import <nixpkgs> {};
mkShell {
name = "dotnet-env";
buildInputs = [
packages = [
(with dotnetCorePackages; combinePackages [
sdk_3_1
sdk_3_0

View file

@ -68,7 +68,7 @@ preFixup = ''
Fortunately, there is [`wrapGAppsHook`]{#ssec-gnome-hooks-wrapgappshook}. It works in conjunction with other setup hooks that populate environment variables, and it will then wrap all executables in `bin` and `libexec` directories using said variables.
For convenience, it also adds `dconf.lib` for a GIO module implementing a GSettings backend using `dconf`, `gtk3` for GSettings schemas, and `librsvg` for GdkPixbuf loader to the closure. In case you are packaging a program without a graphical interface, you might want to use [`wrapGAppsNoGuiHook`]{#ssec-gnome-hooks-wrapgappsnoguihook}, which runs the same script as `wrapGAppsHook` but does not bring `gtk3` and `librsvg` into the closure.
For convenience, it also adds `dconf.lib` for a GIO module implementing a GSettings backend using `dconf`, `gtk3` for GSettings schemas, and `librsvg` for GdkPixbuf loader to the closure. There is also [`wrapGAppsHook4`]{#ssec-gnome-hooks-wrapgappshook4}, which replaces GTK 3 with GTK 4. And in case you are packaging a program without a graphical interface, you might want to use [`wrapGAppsNoGuiHook`]{#ssec-gnome-hooks-wrapgappsnoguihook}, which runs the same script as `wrapGAppsHook` but does not bring `gtk3` and `librsvg` into the closure.
- `wrapGAppsHook` itself will add the packages `share` directory to `XDG_DATA_DIRS`.
@ -88,7 +88,7 @@ For convenience, it also adds `dconf.lib` for a GIO module implementing a GSetti
The setup hook [currently](https://github.com/NixOS/nixpkgs/issues/56943) does not work in expressions with `strictDeps` enabled, like Python packages. In those cases, you will need to disable it with `strictDeps = false;`.
:::
- []{#ssec-gnome-hooks-gst-grl-plugins} Setup hooks of `gst_all_1.gstreamer` and `gnome3.grilo` will populate the `GST_PLUGIN_SYSTEM_PATH_1_0` and `GRL_PLUGIN_PATH` variables, respectively, which will then be added to the wrapper by `wrapGAppsHook`.
- []{#ssec-gnome-hooks-gst-grl-plugins} Setup hooks of `gst_all_1.gstreamer` and `grilo` will populate the `GST_PLUGIN_SYSTEM_PATH_1_0` and `GRL_PLUGIN_PATH` variables, respectively, which will then be added to the wrapper by `wrapGAppsHook`.
You can also pass additional arguments to `makeWrapper` using `gappsWrapperArgs` in `preFixup` hook:
@ -105,7 +105,7 @@ preFixup = ''
## Updating GNOME packages {#ssec-gnome-updating}
Most GNOME package offer [`updateScript`](#var-passthru-updateScript), it is therefore possible to update to latest source tarball by running `nix-shell maintainers/scripts/update.nix --argstr package gnome3.nautilus` or even en masse with `nix-shell maintainers/scripts/update.nix --argstr path gnome3`. Read the packages `NEWS` file to see what changed.
Most GNOME package offer [`updateScript`](#var-passthru-updateScript), it is therefore possible to update to latest source tarball by running `nix-shell maintainers/scripts/update.nix --argstr package gnome.nautilus` or even en masse with `nix-shell maintainers/scripts/update.nix --argstr path gnome`. Read the packages `NEWS` file to see what changed.
## Frequently encountered issues {#ssec-gnome-common-issues}

View file

@ -11,6 +11,7 @@
<xi:include href="bower.section.xml" />
<xi:include href="coq.section.xml" />
<xi:include href="crystal.section.xml" />
<xi:include href="dhall.section.xml" />
<xi:include href="emscripten.section.xml" />
<xi:include href="gnome.section.xml" />
<xi:include href="go.section.xml" />

View file

@ -245,7 +245,7 @@ let
ps.toolz
]);
in mkShell {
buildInputs = [
packages = [
pythonEnv
black

View file

@ -106,7 +106,7 @@ let
name = "gems-for-some-project";
gemdir = ./.;
};
in mkShell { buildInputs = [ gems gems.wrappedRuby ]; }
in mkShell { packages = [ gems gems.wrappedRuby ]; }
```
With this file in your directory, you can run `nix-shell` to build and use the gems. The important parts here are `bundlerEnv` and `wrappedRuby`.

View file

@ -243,6 +243,10 @@ rec {
/* Call a function for each attribute in the given set and return
the result in a list.
Type:
mapAttrsToList ::
(String -> a -> b) -> AttrSet -> [b]
Example:
mapAttrsToList (name: value: name + value)
{ x = "a"; y = "b"; }

View file

@ -219,16 +219,17 @@ rec {
/* Like the above, but aims to support cross compilation. It's still ugly, but
hopefully it helps a little bit. */
makeScopeWithSplicing = splicePackages: newScope: otherSplices: keep: f:
makeScopeWithSplicing = splicePackages: newScope: otherSplices: keep: extra: f:
let
spliced = splicePackages {
spliced0 = splicePackages {
pkgsBuildBuild = otherSplices.selfBuildBuild;
pkgsBuildHost = otherSplices.selfBuildHost;
pkgsBuildTarget = otherSplices.selfBuildTarget;
pkgsHostHost = otherSplices.selfHostHost;
pkgsHostTarget = self; # Not `otherSplices.selfHostTarget`;
pkgsTargetTarget = otherSplices.selfTargetTarget;
} // keep self;
};
spliced = extra spliced0 // spliced0 // keep self;
self = f self // {
newScope = scope: newScope (spliced // scope);
callPackage = newScope spliced; # == self.newScope {};
@ -239,6 +240,7 @@ rec {
newScope
otherSplices
keep
extra
(lib.fixedPoints.extends g f);
packages = f;
};

View file

@ -87,4 +87,16 @@ rec {
then { system = elem; }
else { parsed = elem; };
in lib.matchAttrs pattern platform;
/* Check if a package is available on a given platform.
A package is available on a platform if both
1. One of `meta.platforms` pattern matches the given platform.
2. None of `meta.badPlatforms` pattern matches the given platform.
*/
availableOn = platform: pkg:
lib.any (platformMatch platform) pkg.meta.platforms &&
lib.all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or []);
}

View file

@ -23,6 +23,7 @@ let
isAttrs
isBool
isFunction
isList
isString
length
mapAttrs
@ -127,7 +128,7 @@ rec {
let collected = collectModules
(specialArgs.modulesPath or "")
(modules ++ [ internalModule ])
({ inherit lib options config; } // specialArgs);
({ inherit lib options config specialArgs; } // specialArgs);
in mergeModules prefix (reverseList collected);
options = merged.matchedOptions;
@ -188,6 +189,9 @@ rec {
loadModule = args: fallbackFile: fallbackKey: m:
if isFunction m || isAttrs m then
unifyModuleSyntax fallbackFile fallbackKey (applyIfFunction fallbackKey m args)
else if isList m then
let defs = [{ file = fallbackFile; value = m; }]; in
throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}"
else unifyModuleSyntax (toString m) (toString m) (applyIfFunction (toString m) (import m) args);
/*
@ -295,13 +299,11 @@ rec {
# a module will resolve strictly the attributes used as argument but
# not their values. The values are forwarding the result of the
# evaluation of the option.
requiredArgs = builtins.attrNames (lib.functionArgs f);
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
value = builtins.addErrorContext (context name)
(args.${name} or config._module.args.${name});
}) requiredArgs);
extraArgs = builtins.mapAttrs (name: _:
builtins.addErrorContext (context name)
(args.${name} or config._module.args.${name})
) (lib.functionArgs f);
# Note: we append in the opposite order such that we can add an error
# context on the explicited arguments of "args" too. This update

View file

@ -659,7 +659,7 @@ rec {
Example:
isStorePath "/nix/store/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11/bin/python"
=> false
isStorePath "/nix/store/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11/"
isStorePath "/nix/store/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11"
=> true
isStorePath pkgs.python
=> true
@ -667,7 +667,7 @@ rec {
=> false
*/
isStorePath = x:
if isCoercibleToString x then
if !(isList x) && isCoercibleToString x then
let str = toString x; in
substring 0 1 str == "/"
&& dirOf str == storeDir

View file

@ -121,15 +121,20 @@ rec {
js = { bits = 32; significantByte = littleEndian; family = "js"; };
};
# Determine where two CPUs are compatible with each other. That is,
# can we run code built for system b on system a? For that to
# happen, then the set of all possible possible programs that system
# b accepts must be a subset of the set of all programs that system
# a accepts. This compatibility relation forms a category where each
# CPU is an object and each arrow from a to b represents
# compatibility. CPUs with multiple modes of Endianness are
# isomorphic while all CPUs are endomorphic because any program
# built for a CPU can run on that CPU.
# Determine when two CPUs are compatible with each other. That is,
# can code built for system B run on system A? For that to happen,
# the programs that system B accepts must be a subset of the
# programs that system A accepts.
#
# We have the following properties of the compatibility relation,
# which must be preserved when adding compatibility information for
# additional CPUs.
# - (reflexivity)
# Every CPU is compatible with itself.
# - (transitivity)
# If A is compatible with B and B is compatible with C then A is compatible with C.
# - (compatible under multiple endianness)
# CPUs with multiple modes of endianness are pairwise compatible.
isCompatible = a: b: with cpuTypes; lib.any lib.id [
# x86
(b == i386 && isCompatible a i486)

View file

@ -175,6 +175,9 @@ checkConfigOutput "true" config.submodule.config ./declare-submoduleWith-noshort
## submoduleWith should merge all modules in one swoop
checkConfigOutput "true" config.submodule.inner ./declare-submoduleWith-modules.nix
checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.nix
# Should also be able to evaluate the type name (which evaluates freeformType,
# which evaluates all the modules defined by the type)
checkConfigOutput "submodule" options.submodule.type.description ./declare-submoduleWith-modules.nix
## Paths should be allowed as values and work as expected
checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix

View file

@ -8,9 +8,6 @@
default = false;
};
}
{
outer = true;
}
];
};
default = {};
@ -25,6 +22,7 @@
})
{
inner = true;
outer = true;
}
];
}

View file

@ -147,9 +147,13 @@ rec {
, # The deprecation message to display when this type is used by an option
# If null, the type isn't deprecated
deprecationMessage ? null
, # The types that occur in the definition of this type. This is used to
# issue deprecation warnings recursively. Can also be used to reuse
# nested types
nestedTypes ? {}
}:
{ _type = "option-type";
inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage;
inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage nestedTypes;
description = if description == null then name else description;
};
@ -256,14 +260,14 @@ rec {
};
u8 = unsign 8 256;
u16 = unsign 16 65536;
# the biggest int a 64-bit Nix accepts is 2^63 - 1 (9223372036854775808), for a 32-bit Nix it is 2^31 - 1 (2147483647)
# the smallest int a 64-bit Nix accepts is -2^63 (-9223372036854775807), for a 32-bit Nix it is -2^31 (-2147483648)
# u32 = unsign 32 4294967296;
# the biggest int Nix accepts is 2^63 - 1 (9223372036854775808)
# the smallest int Nix accepts is -2^63 (-9223372036854775807)
u32 = unsign 32 4294967296;
# u64 = unsign 64 18446744073709551616;
s8 = sign 8 256;
s16 = sign 16 65536;
# s32 = sign 32 4294967296;
s32 = sign 32 4294967296;
};
# Alias of u16 for a port number
@ -365,6 +369,7 @@ rec {
getSubModules = elemType.getSubModules;
substSubModules = m: listOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
nonEmptyListOf = elemType:
@ -389,6 +394,7 @@ rec {
getSubModules = elemType.getSubModules;
substSubModules = m: attrsOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
# A version of attrsOf that's lazy in its values at the expense of
@ -413,6 +419,7 @@ rec {
getSubModules = elemType.getSubModules;
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
# TODO: drop this in the future:
@ -421,6 +428,7 @@ rec {
deprecationMessage = "Mixing lists with attribute values is no longer"
+ " possible; please use `types.attrsOf` instead. See"
+ " https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.";
nestedTypes.elemType = elemType;
};
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
@ -433,6 +441,7 @@ rec {
getSubModules = elemType.getSubModules;
substSubModules = m: uniq (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
# Null or value of ...
@ -451,6 +460,7 @@ rec {
getSubModules = elemType.getSubModules;
substSubModules = m: nullOr (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
nestedTypes.elemType = elemType;
};
functionTo = elemType: mkOptionType {
@ -535,6 +545,9 @@ rec {
substSubModules = m: submoduleWith (attrs // {
modules = m;
});
nestedTypes = lib.optionalAttrs (freeformType != null) {
freeformType = freeformType;
};
functor = defaultFunctor name // {
type = types.submoduleWith;
payload = {
@ -596,6 +609,8 @@ rec {
then functor.type mt1 mt2
else null;
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
nestedTypes.left = t1;
nestedTypes.right = t2;
};
# Any of the types in the given list
@ -627,6 +642,8 @@ rec {
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
typeMerge = t1: t2: null;
functor = (defaultFunctor name) // { wrapped = finalType; };
nestedTypes.coercedType = coercedType;
nestedTypes.finalType = finalType;
};
# Obsolete alternative to configOf. It takes its option

View file

@ -428,6 +428,12 @@
githubId = 782180;
name = "Alex Vorobiev";
};
alex-eyre = {
email = "A.Eyre@sms.ed.ac.uk";
github = "alex-eyre";
githubId = 38869148;
name = "Alex Eyre";
};
algorith = {
email = "dries_van_daele@telenet.be";
name = "Dries Van Daele";
@ -1316,6 +1322,12 @@
github = "bmilanov";
githubId = 30090366;
};
bmwalters = {
name = "Bradley Walters";
email = "oss@walters.app";
github = "bmwalters";
githubId = 4380777;
};
bobakker = {
email = "bobakk3r@gmail.com";
github = "bobakker";
@ -1382,12 +1394,6 @@
githubId = 302429;
name = "Marton Boros";
};
branwright1 = {
email = "branwright@protonmail.com";
github = "branwright1";
githubId = 71175207;
name = "Brandon Wright";
};
bramd = {
email = "bram@bramd.nl";
github = "bramd";
@ -2505,6 +2511,12 @@
githubId = 1316469;
name = "Naomi Morse";
};
dlesl = {
email = "dlesl@dlesl.com";
github = "dlesl";
githubId = 28980797;
name = "David Leslie";
};
dmalikov = {
email = "malikov.d.y@gmail.com";
github = "dmalikov";
@ -3345,6 +3357,12 @@
githubId = 10799507;
name = "Karl Fischer";
};
fitzgibbon = {
name = "Niall FitzGibbon";
email = "fitzgibbon.niall@gmail.com";
github = "fitzgibbon";
githubId = 617048;
};
Flakebi = {
email = "flakebi@t-online.de";
github = "Flakebi";
@ -3579,6 +3597,12 @@
githubId = 606000;
name = "Gabriel Adomnicai";
};
Gabriel439 = {
email = "Gabriel439@gmail.com";
github = "Gabriel439";
githubId = 1313787;
name = "Gabriel Gonzalez";
};
gal_bolle = {
email = "florent.becker@ens-lyon.org";
github = "FlorentBecker";
@ -3703,12 +3727,6 @@
githubId = 1447245;
name = "Robin Gloster";
};
gnidorah = {
email = "gnidorah@users.noreply.github.com";
github = "gnidorah";
githubId = 12064730;
name = "gnidorah";
};
gnxlxnxx = {
email = "gnxlxnxx@web.de";
github = "gnxlxnxx";
@ -4133,6 +4151,12 @@
githubId = 12491746;
name = "Masato Yonekawa";
};
hyzual = {
email = "hyzual@gmail.com";
github = "Hyzual";
githubId = 2051507;
name = "Joris Masson";
};
hzeller = {
email = "h.zeller@acm.org";
github = "hzeller";
@ -4753,12 +4777,6 @@
githubId = 1102396;
name = "Jussi Maki";
};
joaquinito2051 = {
email = "joaquinito2051@gmail.com";
github = "heroku-miraheze";
githubId = 61781343;
name = "Joaquín Rufo Gutierrez";
};
jobojeha = {
email = "jobojeha@jeppener.de";
github = "jobojeha";
@ -4999,7 +5017,7 @@
name = "Julien Dehos";
};
julm = {
email = "julm+nix@sourcephile.fr";
email = "julm+nixpkgs@sourcephile.fr";
github = "ju1m";
githubId = 21160136;
name = "Julien Moutinho";
@ -5874,6 +5892,12 @@
githubId = 10626;
name = "Andreas Wagner";
};
lromor = {
email = "leonardo.romor@gmail.com";
github = "lromor";
githubId = 1597330;
name = "Leonardo Romor";
};
lrworth = {
email = "luke@worth.id.au";
name = "Luke Worth";
@ -6080,6 +6104,12 @@
githubId = 2914269;
name = "Malo Bourgon";
};
malvo = {
email = "malte@malvo.org";
github = "malte-v";
githubId = 34393802;
name = "Malte Voos";
};
malyn = {
email = "malyn@strangeGizmo.com";
github = "malyn";
@ -6374,6 +6404,12 @@
fingerprint = "D709 03C8 0BE9 ACDC 14F0 3BFB 77BF E531 397E DE94";
}];
};
mdsp = {
github = "Mdsp9070";
githubId = 44469426;
name = "Matheus de Souza Pessanha";
email = "matheus_pessanha2001@outlook.com";
};
meatcar = {
email = "nixpkgs@denys.me";
github = "meatcar";
@ -7013,12 +7049,6 @@
githubId = 1222539;
name = "Roman Naumann";
};
nand0p = {
email = "nando@hex7.com";
github = "nand0p";
githubId = 1916245;
name = "Fernando Jose Pando";
};
nasirhm = {
email = "nasirhussainm14@gmail.com";
github = "nasirhm";
@ -7195,6 +7225,16 @@
githubId = 16385648;
name = "Niko Pavlinek";
};
nixbitcoin = {
email = "nixbitcoin@i2pmail.org";
github = "nixbitcoin";
githubId = 45737139;
name = "nixbitcoindev";
keys = [{
longkeyid = "rsa4096/0xDD11F9AD5308B3BA";
fingerprint = "577A 3452 7F3E 2A85 E80F E164 DD11 F9AD 5308 B3BA";
}];
};
nixinator = {
email = "33lockdown33@protonmail.com";
github = "nixinator";
@ -7249,6 +7289,12 @@
githubId = 40049608;
name = "Andy Chun";
};
noreferences = {
email = "norkus@norkus.net";
github = "noreferences";
githubId = 13085275;
name = "Juozas Norkus";
};
norfair = {
email = "syd@cs-syd.eu";
github = "NorfairKing";
@ -7301,6 +7347,12 @@
githubId = 1839979;
name = "Niklas Thörne";
};
nullx76 = {
email = "nix@xirion.net";
github = "NULLx76";
githubId = 1809198;
name = "Victor Roest";
};
numinit = {
email = "me@numin.it";
github = "numinit";
@ -7417,6 +7469,12 @@
githubId = 1538622;
name = "Michael Reilly";
};
onsails = {
email = "andrey@onsails.com";
github = "onsails";
githubId = 107261;
name = "Andrey Kuznetsov";
};
onny = {
email = "onny@project-insanity.org";
github = "onny";
@ -7679,12 +7737,6 @@
githubId = 152312;
name = "Periklis Tsirakidis";
};
pesterhazy = {
email = "pesterhazy@gmail.com";
github = "pesterhazy";
githubId = 106328;
name = "Paulus Esterhazy";
};
petabyteboy = {
email = "milan@petabyte.dev";
github = "petabyteboy";
@ -11425,6 +11477,16 @@
github = "pulsation";
githubId = 1838397;
};
ydlr = {
name = "ydlr";
email = "ydlr@ydlr.io";
github = "ydlr";
githubId = 58453832;
keys = [{
longkeyid = "rsa4096/0x43AB44130A29AD9D";
fingerprint = "FD0A C425 9EF5 4084 F99F 9B47 2ACC 9749 7C68 FAD4";
}];
};
zane = {
name = "Zane van Iperen";
email = "zane@zanevaniperen.com";
@ -11435,6 +11497,12 @@
fingerprint = "61AE D40F 368B 6F26 9DAE 3892 6861 6B2D 8AC4 DCC5";
}];
};
zeri = {
name = "zeri";
email = "68825133+zeri42@users.noreply.github.com";
github = "zeri42";
githubId = 68825133;
};
zseri = {
name = "zseri";
email = "zseri.devel@ytrizja.de";

View file

@ -1,10 +1,18 @@
{ maintainer }:
{ maintainer
, localSystem ? { system = args.system or builtins.currentSystem; }
, system ? localSystem.system
, crossSystem ? localSystem
, ...
}@args:
# based on update.nix
# nix-build build.nix --argstr maintainer <yourname>
# to build for aarch64-linux using boot.binfmt.emulatedSystems:
# nix-build build.nix --argstr maintainer <yourname> --argstr system aarch64-linux
let
pkgs = import ./../../default.nix {};
pkgs = import ./../../default.nix (removeAttrs args [ "maintainer" ]);
maintainer_ = pkgs.lib.maintainers.${maintainer};
packagesWith = cond: return: set:
(pkgs.lib.flatten

View file

@ -48,6 +48,7 @@ let
in
pkgs.stdenv.mkDerivation {
name = "nixpkgs-update-script";
buildInputs = [ pkgs.hydra-check ];
buildCommand = ''
echo ""
echo "----------------------------------------------------------------"

View file

@ -0,0 +1,408 @@
#! /usr/bin/env nix-shell
#! nix-shell -p "haskellPackages.ghcWithPackages (p: [p.aeson p.req])"
#! nix-shell -p hydra-unstable
#! nix-shell -i runhaskell
{-
The purpose of this script is
1) download the state of the nixpkgs/haskell-updates job from hydra (with get-report)
2) print a summary of the state suitable for pasting into a github comment (with ping-maintainers)
3) print a list of broken packages suitable for pasting into configuration-hackage2nix.yaml
Because step 1) is quite expensive and takes roughly ~5 minutes the result is cached in a json file in XDG_CACHE.
-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# OPTIONS_GHC -Wall #-}
import Control.Monad (forM_, (<=<))
import Control.Monad.Trans (MonadIO (liftIO))
import Data.Aeson (
FromJSON,
ToJSON,
decodeFileStrict',
eitherDecodeStrict',
encodeFile,
)
import Data.Foldable (Foldable (toList), foldl')
import Data.List.NonEmpty (NonEmpty, nonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe (fromMaybe, mapMaybe)
import Data.Monoid (Sum (Sum, getSum))
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Text.Encoding (encodeUtf8)
import Data.Time (defaultTimeLocale, formatTime, getCurrentTime)
import Data.Time.Clock (UTCTime)
import GHC.Generics (Generic)
import Network.HTTP.Req (
GET (GET),
NoReqBody (NoReqBody),
defaultHttpConfig,
header,
https,
jsonResponse,
req,
responseBody,
responseTimeout,
runReq,
(/:),
)
import System.Directory (XdgDirectory (XdgCache), getXdgDirectory)
import System.Environment (getArgs)
import System.Process (readProcess)
import Prelude hiding (id)
newtype JobsetEvals = JobsetEvals
{ evals :: Seq Eval
}
deriving (Generic, ToJSON, FromJSON, Show)
newtype Nixpkgs = Nixpkgs {revision :: Text}
deriving (Generic, ToJSON, FromJSON, Show)
newtype JobsetEvalInputs = JobsetEvalInputs {nixpkgs :: Nixpkgs}
deriving (Generic, ToJSON, FromJSON, Show)
data Eval = Eval
{ id :: Int
, jobsetevalinputs :: JobsetEvalInputs
}
deriving (Generic, ToJSON, FromJSON, Show)
data Build = Build
{ job :: Text
, buildstatus :: Maybe Int
, finished :: Int
, id :: Int
, nixname :: Text
, system :: Text
, jobsetevals :: Seq Int
}
deriving (Generic, ToJSON, FromJSON, Show)
main :: IO ()
main = do
args <- getArgs
case args of
["get-report"] -> getBuildReports
["ping-maintainers"] -> printMaintainerPing
["mark-broken-list"] -> printMarkBrokenList
_ -> putStrLn "Usage: get-report | ping-maintainers | mark-broken-list"
reportFileName :: IO FilePath
reportFileName = getXdgDirectory XdgCache "haskell-updates-build-report.json"
showT :: Show a => a -> Text
showT = Text.pack . show
getBuildReports :: IO ()
getBuildReports = runReq defaultHttpConfig do
evalMay <- Seq.lookup 0 . evals <$> myReq (https "hydra.nixos.org" /: "jobset" /: "nixpkgs" /: "haskell-updates" /: "evals") mempty
eval@Eval{id} <- maybe (liftIO $ fail "No Evalution found") pure evalMay
liftIO . putStrLn $ "Fetching evaluation " <> show id <> " from Hydra. This might take a few minutes..."
buildReports :: Seq Build <- myReq (https "hydra.nixos.org" /: "eval" /: showT id /: "builds") (responseTimeout 600000000)
liftIO do
fileName <- reportFileName
putStrLn $ "Finished fetching all builds from Hydra, saving report as " <> fileName
now <- getCurrentTime
encodeFile fileName (eval, now, buildReports)
where
myReq query option = responseBody <$> req GET query NoReqBody jsonResponse (header "User-Agent" "hydra-report.hs/v1 (nixpkgs;maintainers/scripts/haskell)" <> option)
hydraEvalCommand :: FilePath
hydraEvalCommand = "hydra-eval-jobs"
hydraEvalParams :: [String]
hydraEvalParams = ["-I", ".", "pkgs/top-level/release-haskell.nix"]
handlesCommand :: FilePath
handlesCommand = "nix-instantiate"
handlesParams :: [String]
handlesParams = ["--eval", "--strict", "--json", "-"]
handlesExpression :: String
handlesExpression = "with import ./. {}; with lib; zipAttrsWith (_: builtins.head) (mapAttrsToList (_: v: if v ? github then { \"${v.email}\" = v.github; } else {}) (import maintainers/maintainer-list.nix))"
-- | This newtype is used to parse a Hydra job output from @hydra-eval-jobs@.
-- The only field we are interested in is @maintainers@, which is why this
-- is just a newtype.
--
-- Note that there are occassionally jobs that don't have a maintainers
-- field, which is why this has to be @Maybe Text@.
newtype Maintainers = Maintainers { maintainers :: Maybe Text }
deriving stock (Generic, Show)
deriving anyclass (FromJSON, ToJSON)
-- | This is a 'Map' from Hydra job name to maintainer email addresses.
--
-- It has values similar to the following:
--
-- @@
-- fromList
-- [ ("arion.aarch64-linux", Maintainers (Just "robert@example.com"))
-- , ("bench.x86_64-linux", Maintainers (Just ""))
-- , ("conduit.x86_64-linux", Maintainers (Just "snoy@man.com, web@ber.com"))
-- , ("lens.x86_64-darwin", Maintainers (Just "ek@category.com"))
-- ]
-- @@
--
-- Note that Hydra jobs without maintainers will have an empty string for the
-- maintainer list.
type HydraJobs = Map Text Maintainers
-- | Map of email addresses to GitHub handles.
-- This is built from the file @../../maintainer-list.nix@.
--
-- It has values similar to the following:
--
-- @@
-- fromList
-- [ ("robert@example.com", "rob22")
-- , ("ek@category.com", "edkm")
-- ]
-- @@
type EmailToGitHubHandles = Map Text Text
-- | Map of Hydra jobs to maintainer GitHub handles.
--
-- It has values similar to the following:
--
-- @@
-- fromList
-- [ ("arion.aarch64-linux", ["rob22"])
-- , ("conduit.x86_64-darwin", ["snoyb", "webber"])
-- ]
-- @@
type MaintainerMap = Map Text (NonEmpty Text)
-- | Generate a mapping of Hydra job names to maintainer GitHub handles.
getMaintainerMap :: IO MaintainerMap
getMaintainerMap = do
hydraJobs :: HydraJobs <-
readJSONProcess hydraEvalCommand hydraEvalParams "" "Failed to decode hydra-eval-jobs output: "
handlesMap :: EmailToGitHubHandles <-
readJSONProcess handlesCommand handlesParams handlesExpression "Failed to decode nix output for lookup of github handles: "
pure $ Map.mapMaybe (splitMaintainersToGitHubHandles handlesMap) hydraJobs
where
-- Split a comma-spearated string of Maintainers into a NonEmpty list of
-- GitHub handles.
splitMaintainersToGitHubHandles
:: EmailToGitHubHandles -> Maintainers -> Maybe (NonEmpty Text)
splitMaintainersToGitHubHandles handlesMap (Maintainers maint) =
nonEmpty . mapMaybe (`Map.lookup` handlesMap) . Text.splitOn ", " $ fromMaybe "" maint
-- | Run a process that produces JSON on stdout and and decode the JSON to a
-- data type.
--
-- If the JSON-decoding fails, throw the JSON-decoding error.
readJSONProcess
:: FromJSON a
=> FilePath -- ^ Filename of executable.
-> [String] -- ^ Arguments
-> String -- ^ stdin to pass to the process
-> String -- ^ String to prefix to JSON-decode error.
-> IO a
readJSONProcess exe args input err = do
output <- readProcess exe args input
let eitherDecodedOutput = eitherDecodeStrict' . encodeUtf8 . Text.pack $ output
case eitherDecodedOutput of
Left decodeErr -> error $ err <> decodeErr <> "\nRaw: '" <> take 1000 output <> "'"
Right decodedOutput -> pure decodedOutput
-- BuildStates are sorted by subjective importance/concerningness
data BuildState
= Failed
| DependencyFailed
| OutputLimitExceeded
| Unknown (Maybe Int)
| TimedOut
| Canceled
| HydraFailure
| Unfinished
| Success
deriving stock (Show, Eq, Ord)
icon :: BuildState -> Text
icon = \case
Failed -> ":x:"
DependencyFailed -> ":heavy_exclamation_mark:"
OutputLimitExceeded -> ":warning:"
Unknown x -> "unknown code " <> showT x
TimedOut -> ":hourglass::no_entry_sign:"
Canceled -> ":no_entry_sign:"
Unfinished -> ":hourglass_flowing_sand:"
HydraFailure -> ":construction:"
Success -> ":heavy_check_mark:"
platformIcon :: Platform -> Text
platformIcon (Platform x) = case x of
"x86_64-linux" -> ":penguin:"
"aarch64-linux" -> ":iphone:"
"x86_64-darwin" -> ":apple:"
_ -> x
data BuildResult = BuildResult {state :: BuildState, id :: Int} deriving (Show, Eq, Ord)
newtype Platform = Platform {platform :: Text} deriving (Show, Eq, Ord)
newtype Table row col a = Table (Map (row, col) a)
type StatusSummary = Map Text (Table Text Platform BuildResult, Set Text)
instance (Ord row, Ord col, Semigroup a) => Semigroup (Table row col a) where
Table l <> Table r = Table (Map.unionWith (<>) l r)
instance (Ord row, Ord col, Semigroup a) => Monoid (Table row col a) where
mempty = Table Map.empty
instance Functor (Table row col) where
fmap f (Table a) = Table (fmap f a)
instance Foldable (Table row col) where
foldMap f (Table a) = foldMap f a
buildSummary :: MaintainerMap -> Seq Build -> StatusSummary
buildSummary maintainerMap = foldl (Map.unionWith unionSummary) Map.empty . fmap toSummary
where
unionSummary (Table l, l') (Table r, r') = (Table $ Map.union l r, l' <> r')
toSummary Build{finished, buildstatus, job, id, system} = Map.singleton name (Table (Map.singleton (set, Platform system) (BuildResult state id)), maintainers)
where
state :: BuildState
state = case (finished, buildstatus) of
(0, _) -> Unfinished
(_, Just 0) -> Success
(_, Just 1) -> Failed
(_, Just 2) -> DependencyFailed
(_, Just 3) -> HydraFailure
(_, Just 4) -> Canceled
(_, Just 7) -> TimedOut
(_, Just 11) -> OutputLimitExceeded
(_, i) -> Unknown i
packageName = fromMaybe job (Text.stripSuffix ("." <> system) job)
splitted = nonEmpty $ Text.splitOn "." packageName
name = maybe packageName NonEmpty.last splitted
set = maybe "" (Text.intercalate "." . NonEmpty.init) splitted
maintainers = maybe mempty (Set.fromList . toList) (Map.lookup job maintainerMap)
readBuildReports :: IO (Eval, UTCTime, Seq Build)
readBuildReports = do
file <- reportFileName
fromMaybe (error $ "Could not decode " <> file) <$> decodeFileStrict' file
sep :: Text
sep = " | "
joinTable :: [Text] -> Text
joinTable t = sep <> Text.intercalate sep t <> sep
type NumSummary = Table Platform BuildState Int
printTable :: (Ord rows, Ord cols) => Text -> (rows -> Text) -> (cols -> Text) -> (entries -> Text) -> Table rows cols entries -> [Text]
printTable name showR showC showE (Table mapping) = joinTable <$> (name : map showC cols) : replicate (length cols + sepsInName + 1) "---" : map printRow rows
where
sepsInName = Text.count "|" name
printRow row = showR row : map (\col -> maybe "" showE (Map.lookup (row, col) mapping)) cols
rows = toList $ Set.fromList (fst <$> Map.keys mapping)
cols = toList $ Set.fromList (snd <$> Map.keys mapping)
printJob :: Int -> Text -> (Table Text Platform BuildResult, Text) -> [Text]
printJob evalId name (Table mapping, maintainers) =
if length sets <= 1
then map printSingleRow sets
else ["- [ ] " <> makeJobSearchLink "" name <> " " <> maintainers] <> map printRow sets
where
printRow set = " - " <> printState set <> " " <> makeJobSearchLink set (if Text.null set then "toplevel" else set)
printSingleRow set = "- [ ] " <> printState set <> " " <> makeJobSearchLink set (makePkgName set) <> " " <> maintainers
makePkgName set = (if Text.null set then "" else set <> ".") <> name
printState set = Text.intercalate " " $ map (\pf -> maybe "" (label pf) $ Map.lookup (set, pf) mapping) platforms
makeJobSearchLink set linkLabel= makeSearchLink evalId linkLabel (makePkgName set)
sets = toList $ Set.fromList (fst <$> Map.keys mapping)
platforms = toList $ Set.fromList (snd <$> Map.keys mapping)
label pf (BuildResult s i) = "[[" <> platformIcon pf <> icon s <> "]](https://hydra.nixos.org/build/" <> showT i <> ")"
makeSearchLink :: Int -> Text -> Text -> Text
makeSearchLink evalId linkLabel query = "[" <> linkLabel <> "](" <> "https://hydra.nixos.org/eval/" <> showT evalId <> "?filter=" <> query <> ")"
statusToNumSummary :: StatusSummary -> NumSummary
statusToNumSummary = fmap getSum . foldMap (fmap Sum . jobTotals)
jobTotals :: (Table Text Platform BuildResult, a) -> Table Platform BuildState Int
jobTotals (Table mapping, _) = getSum <$> Table (Map.foldMapWithKey (\(_, platform) (BuildResult buildstate _) -> Map.singleton (platform, buildstate) (Sum 1)) mapping)
details :: Text -> [Text] -> [Text]
details summary content = ["<details><summary>" <> summary <> " </summary>", ""] <> content <> ["</details>", ""]
printBuildSummary :: Eval -> UTCTime -> StatusSummary -> Text
printBuildSummary
Eval{id, jobsetevalinputs = JobsetEvalInputs{nixpkgs = Nixpkgs{revision}}}
fetchTime
summary =
Text.unlines $
headline <> totals
<> optionalList "#### Maintained packages with build failure" (maintainedList fails)
<> optionalList "#### Maintained packages with failed dependency" (maintainedList failedDeps)
<> optionalList "#### Maintained packages with unknown error" (maintainedList unknownErr)
<> optionalHideableList "#### Unmaintained packages with build failure" (unmaintainedList fails)
<> optionalHideableList "#### Unmaintained packages with failed dependency" (unmaintainedList failedDeps)
<> optionalHideableList "#### Unmaintained packages with unknown error" (unmaintainedList unknownErr)
<> footer
where
footer = ["*Report generated with [maintainers/scripts/haskell/hydra-report.hs](https://github.com/NixOS/nixpkgs/blob/haskell-updates/maintainers/scripts/haskell/hydra-report.sh)*"]
totals =
[ "#### Build summary"
, ""
]
<> printTable "Platform" (\x -> makeSearchLink id (platform x <> " " <> platformIcon x) ("." <> platform x)) (\x -> showT x <> " " <> icon x) showT (statusToNumSummary summary)
headline =
[ "### [haskell-updates build report from hydra](https://hydra.nixos.org/jobset/nixpkgs/haskell-updates)"
, "*evaluation ["
<> showT id
<> "](https://hydra.nixos.org/eval/"
<> showT id
<> ") of nixpkgs commit ["
<> Text.take 7 revision
<> "](https://github.com/NixOS/nixpkgs/commits/"
<> revision
<> ") as of "
<> Text.pack (formatTime defaultTimeLocale "%Y-%m-%d %H:%M UTC" fetchTime)
<> "*"
]
jobsByState predicate = Map.filter (predicate . foldl' min Success . fmap state . fst) summary
fails = jobsByState (== Failed)
failedDeps = jobsByState (== DependencyFailed)
unknownErr = jobsByState (\x -> x > DependencyFailed && x < TimedOut)
withMaintainer = Map.mapMaybe (\(x, m) -> (x,) <$> nonEmpty (Set.toList m))
withoutMaintainer = Map.mapMaybe (\(x, m) -> if Set.null m then Just x else Nothing)
optionalList heading list = if null list then mempty else [heading] <> list
optionalHideableList heading list = if null list then mempty else [heading] <> details (showT (length list) <> " job(s)") list
maintainedList = showMaintainedBuild <=< Map.toList . withMaintainer
unmaintainedList = showBuild <=< Map.toList . withoutMaintainer
showBuild (name, table) = printJob id name (table, "")
showMaintainedBuild (name, (table, maintainers)) = printJob id name (table, Text.intercalate " " (fmap ("@" <>) (toList maintainers)))
printMaintainerPing :: IO ()
printMaintainerPing = do
maintainerMap <- getMaintainerMap
(eval, fetchTime, buildReport) <- readBuildReports
putStrLn (Text.unpack (printBuildSummary eval fetchTime (buildSummary maintainerMap buildReport)))
printMarkBrokenList :: IO ()
printMarkBrokenList = do
(_, _, buildReport) <- readBuildReports
forM_ buildReport \Build{buildstatus, job} ->
case (buildstatus, Text.splitOn "." job) of
(Just 1, ["haskellPackages", name, "x86_64-linux"]) -> putStrLn $ " - " <> Text.unpack name
_ -> pure ()

View file

@ -0,0 +1,45 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils git -I nixpkgs=.
# This script uses the data pulled with
# maintainers/scripts/haskell/hydra-report.hs get-report to produce a list of
# failing builds that get written to the hackage2nix config. Then
# hackage-packages.nix gets regenerated and transitive-broken packages get
# marked as dont-distribute in the config as well.
# This should disable builds for most failing jobs in the haskell-updates jobset.
set -euo pipefail
broken_config="pkgs/development/haskell-modules/configuration-hackage2nix/broken.yaml"
tmpfile=$(mktemp)
trap "rm ${tmpfile}" 0
echo "Remember that you need to manually run 'maintainers/scripts/haskell/hydra-report.hs get-report' sometime before running this script."
echo "Generating a list of broken builds and displaying for manual confirmation ..."
maintainers/scripts/haskell/hydra-report.hs mark-broken-list | sort -i > $tmpfile
$EDITOR $tmpfile
tail -n +3 "$broken_config" >> "$tmpfile"
cat > "$broken_config" << EOF
broken-packages:
# These packages don't compile.
EOF
sort -iu "$tmpfile" >> "$broken_config"
maintainers/scripts/haskell/regenerate-hackage-packages.sh
maintainers/scripts/haskell/regenerate-transitive-broken-packages.sh
maintainers/scripts/haskell/regenerate-hackage-packages.sh
if [[ "${1:-}" == "--do-commit" ]]; then
git add $broken_config
git add pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml
git add pkgs/development/haskell-modules/hackage-packages.nix
git commit -F - << EOF
hackage2nix: Mark failing builds broken
This commit has been generated by maintainers/scripts/haskell/mark-broken.sh
EOF
fi

View file

@ -0,0 +1,44 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils haskellPackages.cabal2nix-unstable git nix -I nixpkgs=.
# This script is used to regenerate nixpkgs' Haskell package set, using the
# tool hackage2nix from the nixos/cabal2nix repo. hackage2nix looks at the
# config files in pkgs/development/haskell-modules/configuration-hackage2nix
# and generates a Nix expression for package version specified there, using the
# Cabal files from the Hackage database (available under all-cabal-hashes) and
# its companion tool cabal2nix.
#
# Related scripts are update-hackage.sh, for updating the snapshot of the
# Hackage database used by hackage2nix, and update-cabal2nix-unstable.sh,
# for updating the version of hackage2nix used to perform this task.
set -euo pipefail
# To prevent hackage2nix fails because of encoding.
# See: https://github.com/NixOS/nixpkgs/pull/122023
export LC_ALL=C.UTF-8
extraction_derivation='with import ./. {}; runCommand "unpacked-cabal-hashes" { } "tar xf ${all-cabal-hashes} --strip-components=1 --one-top-level=$out"'
unpacked_hackage="$(nix-build -E "$extraction_derivation" --no-out-link)"
config_dir=pkgs/development/haskell-modules/configuration-hackage2nix
echo "Starting hackage2nix to regenerate pkgs/development/haskell-modules/hackage-packages.nix ..."
hackage2nix \
--hackage "$unpacked_hackage" \
--preferred-versions <(for n in "$unpacked_hackage"/*/preferred-versions; do cat "$n"; echo; done) \
--nixpkgs "$PWD" \
--config "$config_dir/main.yaml" \
--config "$config_dir/stackage.yaml" \
--config "$config_dir/broken.yaml" \
--config "$config_dir/transitive-broken.yaml"
if [[ "${1:-}" == "--do-commit" ]]; then
git add pkgs/development/haskell-modules/hackage-packages.nix
git commit -F - << EOF
hackage-packages.nix: Regenerate based on current config
This commit has been generated by maintainers/scripts/haskell/regenerate-hackage-packages.sh
EOF
fi
echo "Regeneration of hackage-packages.nix finished."

View file

@ -0,0 +1,15 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils nix gnused -I nixpkgs=.
config_file=pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml
cat > $config_file << EOF
# This file is automatically generated by
# maintainers/scripts/haskell/regenerate-transitive-broken-packages.sh
# It is supposed to list all haskellPackages that cannot evaluate because they
# depend on a dependency marked as broken.
dont-distribute-packages:
EOF
echo "Regenerating list of transitive broken packages ..."
echo -e $(nix-instantiate --eval --strict maintainers/scripts/haskell/transitive-broken-packages.nix) | sed 's/\"//' | sort -i >> $config_file

View file

@ -0,0 +1,16 @@
let
nixpkgs = import ../../..;
inherit (nixpkgs {}) pkgs lib;
getEvaluating = x:
builtins.attrNames (
lib.filterAttrs (
_: v: (builtins.tryEval (v.outPath or null)).success && lib.isDerivation v && !v.meta.broken
) x
);
brokenDeps = lib.subtractLists
(getEvaluating pkgs.haskellPackages)
(getEvaluating (nixpkgs { config.allowBroken = true; }).haskellPackages);
in
''
${lib.concatMapStringsSep "\n" (x: " - ${x}") brokenDeps}
''

View file

@ -0,0 +1,17 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils curl jq gnused haskellPackages.cabal2nix-unstable -I nixpkgs=.
# Updates cabal2nix-unstable to the latest master of the nixos/cabal2nix repository.
# See regenerate-hackage-packages.sh for details on the purpose of this script.
set -euo pipefail
# fetch current master HEAD from Github
head_info="$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/NixOS/cabal2nix/branches/master)"
# extract commit hash
commit="$(jq -r .commit.sha <<< "$head_info")"
# extract commit timestamp and convert to date
date="$(date "--date=$(jq -r .commit.commit.committer.date <<< "$head_info")" +%F)"
# generate nix expression from cabal file, replacing the version with the commit date
echo '# This file defines cabal2nix-unstable, used by maintainers/scripts/haskell/regenerate-hackage-packages.sh.' > pkgs/development/haskell-modules/cabal2nix-unstable.nix
cabal2nix "https://github.com/NixOS/cabal2nix/archive/$commit.tar.gz" | sed -e 's/version = ".*"/version = "'"unstable-$date"'"/' >> pkgs/development/haskell-modules/cabal2nix-unstable.nix

View file

@ -0,0 +1,35 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p nix curl jq nix-prefetch-github git gnused -I nixpkgs=.
# See regenerate-hackage-packages.sh for details on the purpose of this script.
set -euo pipefail
pin_file=pkgs/data/misc/hackage/pin.json
current_commit="$(jq -r .commit $pin_file)"
old_date="$(jq -r .msg $pin_file | sed 's/Update from Hackage at //')"
git_info="$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/commercialhaskell/all-cabal-hashes/branches/hackage)"
head_commit="$(echo "$git_info" | jq -r .commit.sha)"
commit_msg="$(echo "$git_info" | jq -r .commit.commit.message)"
new_date="$(echo "$commit_msg" | sed 's/Update from Hackage at //')"
if [ "$current_commit" != "$head_commit" ]; then
url="https://github.com/commercialhaskell/all-cabal-hashes/archive/$head_commit.tar.gz"
hash="$(nix-prefetch-url "$url")"
jq -n \
--arg commit "$head_commit" \
--arg hash "$hash" \
--arg url "$url" \
--arg commit_msg "$commit_msg" \
'{commit: $commit, url: $url, sha256: $hash, msg: $commit_msg}' \
> $pin_file
fi
if [[ "${1:-}" == "--do-commit" ]]; then
git add pkgs/data/misc/hackage/pin.json
git commit -F - << EOF
all-cabal-hashes: $old_date -> $new_date
This commit has been generated by maintainers/scripts/haskell/update-hackage.sh
EOF
fi

View file

@ -0,0 +1,68 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p nix curl jq nix-prefetch-github git gnused gnugrep -I nixpkgs=.
set -eu -o pipefail
tmpfile=$(mktemp "update-stackage.XXXXXXX")
# shellcheck disable=SC2064
stackage_config="pkgs/development/haskell-modules/configuration-hackage2nix/stackage.yaml"
trap "rm ${tmpfile} ${tmpfile}.new" 0
touch "$tmpfile" "$tmpfile.new" # Creating files here so that trap creates no errors.
curl -L -s "https://stackage.org/nightly/cabal.config" >"$tmpfile"
old_version=$(grep "# Stackage Nightly" $stackage_config | sed -E 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/\1/')
version=$(sed -rn "s/^--.*http:..(www.)?stackage.org.snapshot.nightly-//p" "$tmpfile")
if [[ "$old_version" == "$version" ]]; then
echo "No new stackage version"
exit 0 # Nothing to do
fi
# Create a simple yaml version of the file.
sed -r \
-e '/^--/d' \
-e 's|^constraints:||' \
-e 's|^ +| - |' \
-e 's|,$||' \
-e '/installed$/d' \
-e '/^$/d' \
< "${tmpfile}" | sort --ignore-case >"${tmpfile}.new"
cat > $stackage_config << EOF
# Stackage Nightly $version
# This file is auto-generated by
# maintainers/scripts/haskell/update-stackage.sh
default-package-overrides:
EOF
# Drop restrictions on some tools where we always want the latest version.
sed -r \
-e '/ cabal-install /d' \
-e '/ cabal2nix /d' \
-e '/ cabal2spec /d' \
-e '/ distribution-nixpkgs /d' \
-e '/ git-annex /d' \
-e '/ hindent /d' \
-e '/ hledger/d' \
-e '/ hlint /d' \
-e '/ hoogle /d' \
-e '/ hopenssl /d' \
-e '/ jailbreak-cabal /d' \
-e '/ json-autotype/d' \
-e '/ language-nix /d' \
-e '/ shake /d' \
-e '/ ShellCheck /d' \
-e '/ stack /d' \
-e '/ weeder /d' \
< "${tmpfile}.new" >> $stackage_config
if [[ "${1:-}" == "--do-commit" ]]; then
git add $stackage_config
git commit -F - << EOF
Stackage Nightly: $old_version -> $version
This commit has been generated by maintainers/scripts/haskell/update-stackage.sh
EOF
fi

View file

@ -13,6 +13,7 @@ import http
import json
import os
import subprocess
import logging
import sys
import time
import traceback
@ -34,6 +35,14 @@ ATOM_ENTRY = "{http://www.w3.org/2005/Atom}entry" # " vim gets confused here
ATOM_LINK = "{http://www.w3.org/2005/Atom}link" # "
ATOM_UPDATED = "{http://www.w3.org/2005/Atom}updated" # "
LOG_LEVELS = {
logging.getLevelName(level): level for level in [
logging.DEBUG, logging.INFO, logging.WARN, logging.ERROR ]
}
log = logging.getLogger()
log.addHandler(logging.StreamHandler())
def retry(ExceptionToCheck: Any, tries: int = 4, delay: float = 3, backoff: float = 2):
"""Retry calling the decorated function using an exponential backoff.
@ -235,6 +244,7 @@ def prefetch_plugin(
alias: Optional[str],
cache: "Optional[Cache]" = None,
) -> Tuple[Plugin, Dict[str, str]]:
log.info("Prefetching plugin %s", repo_name)
repo = Repo(user, repo_name, branch, alias)
commit, date = repo.latest_commit()
has_submodules = repo.has_submodules()
@ -464,6 +474,11 @@ def parse_args(editor: Editor):
"--no-commit", "-n", action="store_true", default=False,
help="Whether to autocommit changes"
)
parser.add_argument(
"--debug", "-d", choices=LOG_LEVELS.keys(),
default=logging.getLevelName(logging.WARN),
help="Adjust log level"
)
return parser.parse_args()
@ -503,6 +518,9 @@ def update_plugins(editor: Editor):
"""The main entry function of this module. All input arguments are grouped in the `Editor`."""
args = parse_args(editor)
log.setLevel(LOG_LEVELS[args.debug])
log.info("Start updating plugins")
nixpkgs_repo = git.Repo(editor.root, search_parent_directories=True)
update = get_update(args.input_file, args.outfile, args.proc, editor)

View file

@ -2,8 +2,11 @@
}:
with nixpkgs;
mkShell {
buildInputs = [
bash luarocks-nix nix-prefetch-scripts parallel
packages = [
bash
luarocks-nix
nix-prefetch-scripts
parallel
];
LUAROCKS_NIXPKGS_PATH = toString nixpkgs.path;
}

View file

@ -1,5 +1,6 @@
{ package ? null
, maintainer ? null
, predicate ? null
, path ? null
, max-workers ? null
, include-overlays ? false
@ -69,6 +70,11 @@ let
*/
packagesWith = packagesWithPath [];
/* Recursively find all packages in `pkgs` with updateScript matching given predicate.
*/
packagesWithUpdateScriptMatchingPredicate = cond:
packagesWith (path: pkg: builtins.hasAttr "updateScript" pkg && cond path pkg);
/* Recursively find all packages in `pkgs` with updateScript by given maintainer.
*/
packagesWithUpdateScriptAndMaintainer = maintainer':
@ -79,7 +85,7 @@ let
else
builtins.getAttr maintainer' lib.maintainers;
in
packagesWith (path: pkg: builtins.hasAttr "updateScript" pkg &&
packagesWithUpdateScriptMatchingPredicate (path: pkg:
(if builtins.hasAttr "maintainers" pkg.meta
then (if builtins.isList pkg.meta.maintainers
then builtins.elem maintainer pkg.meta.maintainers
@ -120,6 +126,8 @@ let
packages =
if package != null then
[ (packageByName package pkgs) ]
else if predicate != null then
packagesWithUpdateScriptMatchingPredicate predicate pkgs
else if maintainer != null then
packagesWithUpdateScriptAndMaintainer maintainer pkgs
else if path != null then
@ -135,11 +143,15 @@ let
to run all update scripts for all packages that lists \`garbas\` as a maintainer
and have \`updateScript\` defined, or:
% nix-shell maintainers/scripts/update.nix --argstr package gnome3.nautilus
% nix-shell maintainers/scripts/update.nix --argstr package gnome.nautilus
to run update script for specific package, or
% nix-shell maintainers/scripts/update.nix --argstr path gnome3
% nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: builtins.isList pkg.updateScript && builtins.length pkg.updateScript >= 1 && (let script = builtins.head pkg.updateScript; in builtins.isAttrs script && script.name == "gnome-update-script"))'
to run update script for all packages matching given predicate, or
% nix-shell maintainers/scripts/update.nix --argstr path gnome
to run update script for all package under an attribute path.

View file

@ -39,6 +39,9 @@ async def run_update_script(nixpkgs_root: str, merge_lock: asyncio.Lock, temp_di
if temp_dir is not None:
worktree, _branch = temp_dir
# Ensure the worktree is clean before update.
await check_subprocess('git', 'reset', '--hard', '--quiet', 'HEAD', cwd=worktree)
# Update scripts can use $(dirname $0) to get their location but we want to run
# their clones in the git worktree, not in the main nixpkgs repo.
update_script_command = map(lambda arg: re.sub(r'^{0}'.format(re.escape(nixpkgs_root)), worktree, arg), update_script_command)

View file

@ -48,6 +48,14 @@ with lib.maintainers; {
scope = "Maintain Cinnamon desktop environment and applications made by the LinuxMint team.";
};
chia = {
members = [
atemu
lourkeur
];
scope = "Maintain the Chia blockchain and its dependencies";
};
deshaw = {
# Verify additions to this team with at least one already existing member of the team.
members = [
@ -66,7 +74,7 @@ with lib.maintainers; {
};
freedesktop = {
members = [ jtojnar worldofpeace ];
members = [ jtojnar ];
scope = "Maintain Freedesktop.org packages for graphical desktop.";
};
@ -89,13 +97,21 @@ with lib.maintainers; {
members = [
hedning
jtojnar
worldofpeace
dasj19
maxeaubrey
];
scope = "Maintain GNOME desktop environment and platform.";
};
haskell = {
members = [
maralorn
cdepillabout
sternenseemann
];
scope = "Maintain Haskell packages and infrastructure.";
};
home-assistant = {
members = [
fab
@ -170,4 +186,13 @@ with lib.maintainers; {
];
scope = "Maintain SageMath and the dependencies that are likely to break it.";
};
serokell = {
# Verify additions by approval of an already existing member of the team.
members = [
balsoft
mkaito
];
scope = "Group registration for Serokell employees who collectively maintain packages.";
};
}

View file

@ -7,8 +7,12 @@
<para>
IPv6 is enabled by default. Stateless address autoconfiguration is used to
automatically assign IPv6 addresses to all interfaces. You can disable IPv6
support globally by setting:
automatically assign IPv6 addresses to all interfaces, and Privacy
Extensions (RFC 4946) are enabled by default. You can adjust the default
for this by setting <xref linkend="opt-networking.tempAddresses"/>.
This option may be overridden on a per-interface basis by
<xref linkend="opt-networking.interfaces._name_.tempAddress"/>.
You can disable IPv6 support globally by setting:
<programlisting>
<xref linkend="opt-networking.enableIPv6"/> = false;
</programlisting>

View file

@ -25,7 +25,7 @@
<programlisting>
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.xfce.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.gnome3.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.gnome.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.mate.enable"/> = true;
<xref linkend="opt-services.xserver.windowManager.xmonad.enable"/> = true;
<xref linkend="opt-services.xserver.windowManager.twm.enable"/> = true;

View file

@ -84,12 +84,12 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen>
</para>
<para>
You'll need <literal>nixos-generate-config</literal> and
<literal>nixos-install</literal> and we'll throw in some man pages and
<literal>nixos-enter</literal> just in case you want to chroot into your
NixOS partition. They are installed by default on NixOS, but you don't have
<literal>nixos-install</literal>, but this also makes some man pages
and <literal>nixos-enter</literal> available, just in case you want to chroot into your
NixOS partition. NixOS installs these by default, but you don't have
NixOS yet..
</para>
<screen><prompt>$ </prompt>nix-env -f '&lt;nixpkgs/nixos&gt;' --arg configuration {} -iA config.system.build.{nixos-generate-config,nixos-install,nixos-enter,manual.manpages}</screen>
<screen><prompt>$ </prompt>nix-env -f '&lt;nixpkgs>' -iA nixos-install-tools</screen>
</listitem>
<listitem>
<note>

View file

@ -83,10 +83,10 @@
like games.
<itemizedlist>
<para>This can be achieved with the following options which the desktop manager default enables, excluding <literal>games</literal>.</para>
<listitem><para><xref linkend="opt-services.gnome3.core-os-services.enable"/></para></listitem>
<listitem><para><xref linkend="opt-services.gnome3.core-shell.enable"/></para></listitem>
<listitem><para><xref linkend="opt-services.gnome3.core-utilities.enable"/></para></listitem>
<listitem><para><xref linkend="opt-services.gnome3.games.enable"/></para></listitem>
<listitem><para><option>services.gnome3.core-os-services.enable</option></para></listitem>
<listitem><para><option>services.gnome3.core-shell.enable</option></para></listitem>
<listitem><para><option>services.gnome3.core-utilities.enable</option></para></listitem>
<listitem><para><option>services.gnome3.games.enable</option></para></listitem>
</itemizedlist>
With these options we hope to give users finer grained control over their systems. Prior to this change you'd either have to manually
disable options or use <option>environment.gnome3.excludePackages</option> which only excluded the optional applications.

View file

@ -27,7 +27,7 @@
<para>The default Linux kernel was updated to the 5.10 LTS series, coming from the 5.4 LTS series.</para>
</listitem>
<listitem>
<para>GNOME desktop environment was upgraded to 3.38, see its <link xlink:href="https://help.gnome.org/misc/release-notes/3.38/">release notes</link>.</para>
<para>GNOME desktop environment was upgraded to 40, see the release notes for <link xlink:href="https://help.gnome.org/misc/release-notes/40.0/">40.0</link> and <link xlink:href="https://help.gnome.org/misc/release-notes/3.38/">3.38</link>. The <code>gnome3</code> attribute set has been renamed to <code>gnome</code> and so have been the NixOS options.</para>
</listitem>
<listitem>
<para>
@ -78,7 +78,7 @@
</listitem>
<listitem>
<para>
<link xlink:href="https://kodi.tv/">Kodi</link> has been updated to version 19.0 "Matrix". See
<link xlink:href="https://kodi.tv/">Kodi</link> has been updated to version 19.1 "Matrix". See
the <link xlink:href="https://kodi.tv/article/kodi-190-matrix-release">announcement</link> for
further details.
</para>
@ -100,6 +100,19 @@
Now nginx uses the zlib-ng library by default.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://libreswan.org/">Libreswan</link> has been updated
to version 4.4. The package now includes example configurations and manual
pages by default. The NixOS module has been changed to use the upstream
systemd units and write the configuration in the <literal>/etc/ipsec.d/
</literal> directory. In addition, two new options have been added to
specify connection policies
(<xref linkend="opt-services.libreswan.policies"/>)
and disable send/receive redirects
(<xref linkend="opt-services.libreswan.disableRedirects"/>).
</para>
</listitem>
</itemizedlist>
</section>
@ -145,6 +158,11 @@
section of the NixOS manual</link> for more information.
</para>
</listitem>
<listitem>
<para>
<xref linkend="opt-services.nebula.networks" /> <link xlink:href="https://github.com/slackhq/nebula">Nebula VPN</link>
</para>
</listitem>
</itemizedlist>
</section>
@ -697,6 +715,17 @@ environment.systemPackages = [
All CUDA toolkit versions prior to CUDA 10 have been removed.
</para>
</listitem>
<listitem>
<para>
The <package>kbdKeymaps</package> package was removed since dvp and neo
are now included in <package>kbd</package>.
If you want to use the Programmer Dvorak Keyboard Layout, you have to use
<literal>dvorak-programmer</literal> in <option>console.keyMap</option>
now instead of <literal>dvp</literal>.
In <option>services.xserver.xkbVariant</option> it's still <literal>dvp</literal>.
</para>
</listitem>
<listitem>
<para>
The <package>babeld</package> service is now being run as an unprivileged user. To achieve that the module configures
@ -715,6 +744,20 @@ environment.systemPackages = [
The <package>yadm</package> dotfile manager has been updated from 2.x to 3.x, which has new (XDG) default locations for some data/state files. Most yadm commands will fail and print a legacy path warning (which describes how to upgrade/migrate your repository). If you have scripts, daemons, scheduled jobs, shell profiles, etc. that invoke yadm, expect them to fail or misbehave until you perform this migration and prepare accordingly.
</para>
</listitem>
<listitem>
<para>
Instead of determining <option>services.radicale.package</option>
automatically based on <option>system.stateVersion</option>, the latest
version is always used because old versions are not officially supported.
</para>
<para>
Furthermore, Radicale's systemd unit was hardened which might break some
deployments. In particular, a non-default
<literal>filesystem_folder</literal> has to be added to
<option>systemd.services.radicale.serviceConfig.ReadWritePaths</option> if
the deprecated <option>services.radicale.config</option> is used.
</para>
</listitem>
</itemizedlist>
</section>
@ -909,9 +952,26 @@ environment.systemPackages = [
Note that users defined with an explicit UID below 500 are exempted from this check, as <xref linkend="opt-users.users._name_.isSystemUser" /> has no effect for those.
</para>
</listitem>
<listitem>
<para>
The <literal>security.apparmor</literal> module,
for the <link xlink:href="https://gitlab.com/apparmor/apparmor/-/wikis/Documentation">AppArmor</link>
Mandatory Access Control system,
has been substantialy improved along with related tools,
so that module maintainers can now more easily write AppArmor profiles for NixOS.
The most notable change on the user-side is the new option <xref linkend="opt-security.apparmor.policies"/>,
replacing the previous <literal>profiles</literal> option
to provide a way to disable a profile
and to select whether to confine in enforce mode (default)
or in complain mode (see <literal>journalctl -b --grep apparmor</literal>).
Security-minded users may also want to enable <xref linkend="opt-security.apparmor.killUnconfinedConfinables"/>,
at the cost of having some of their processes killed
when updating to a NixOS version introducing new AppArmor profiles.
</para>
</listitem>
<listitem>
<para>
The GNOME desktop manager once again installs <package>gnome3.epiphany</package> by default.
The GNOME desktop manager once again installs <package>gnome.epiphany</package> by default.
</para>
</listitem>
<listitem>
@ -1035,6 +1095,12 @@ environment.systemPackages = [
</programlisting>
</para>
</listitem>
<listitem>
<para>
The newly enabled <literal>systemd-pstore.service</literal> now automatically evacuates crashdumps and panic logs from the persistent storage to <literal>/var/lib/systemd/pstore</literal>.
This prevents NVRAM from filling up, which ensures the latest diagnostic data is always stored and alleviates problems with writing new boot configurations.
</para>
</listitem>
</itemizedlist>
</section>
</section>

View file

@ -4,5 +4,5 @@ in
pkgs.mkShell {
name = "nixos-manual";
buildInputs = with pkgs; [ xmlformat jing xmloscopy ruby ];
packages = with pkgs; [ xmlformat jing xmloscopy ruby ];
}

View file

@ -36,6 +36,13 @@ rec {
[ ../modules/virtualisation/qemu-vm.nix
../modules/testing/test-instrumentation.nix # !!! should only get added for automated test runs
{ key = "no-manual"; documentation.nixos.enable = false; }
{ key = "no-revision";
# Make the revision metadata constant, in order to avoid needless retesting.
# The human version (e.g. 21.05-pre) is left as is, because it is useful
# for external modules that test with e.g. nixosTest and rely on that
# version number.
config.system.nixos.revision = "constant-nixos-revision";
}
{ key = "nodes"; _module.args.nodes = nodes; }
] ++ optional minimal ../modules/testing/minimal-kernel.nix;
};

View file

@ -3,6 +3,7 @@ from contextlib import contextmanager, _GeneratorContextManager
from queue import Queue, Empty
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List, Iterable
from xml.sax.saxutils import XMLGenerator
from colorama import Style
import queue
import io
import _thread
@ -151,6 +152,8 @@ class Logger:
self.xml.startDocument()
self.xml.startElement("logfile", attrs={})
self._print_serial_logs = True
def close(self) -> None:
self.xml.endElement("logfile")
self.xml.endDocument()
@ -174,15 +177,21 @@ class Logger:
self.drain_log_queue()
self.log_line(message, attributes)
def enqueue(self, message: Dict[str, str]) -> None:
self.queue.put(message)
def log_serial(self, message: str, machine: str) -> None:
self.enqueue({"msg": message, "machine": machine, "type": "serial"})
if self._print_serial_logs:
eprint(Style.DIM + "{} # {}".format(machine, message) + Style.RESET_ALL)
def enqueue(self, item: Dict[str, str]) -> None:
self.queue.put(item)
def drain_log_queue(self) -> None:
try:
while True:
item = self.queue.get_nowait()
attributes = {"machine": item["machine"], "type": "serial"}
self.log_line(self.sanitise(item["msg"]), attributes)
msg = self.sanitise(item["msg"])
del item["msg"]
self.log_line(msg, item)
except Empty:
pass
@ -327,6 +336,9 @@ class Machine:
def log(self, msg: str) -> None:
self.logger.log(msg, {"machine": self.name})
def log_serial(self, msg: str) -> None:
self.logger.log_serial(msg, self.name)
def nested(self, msg: str, attrs: Dict[str, str] = {}) -> _GeneratorContextManager:
my_attrs = {"machine": self.name}
my_attrs.update(attrs)
@ -784,8 +796,7 @@ class Machine:
# Ignore undecodable bytes that may occur in boot menus
line = _line.decode(errors="ignore").replace("\r", "").rstrip()
self.last_lines.put(line)
eprint("{} # {}".format(self.name, line))
self.logger.enqueue({"msg": line, "machine": self.name})
self.log_serial(line)
_thread.start_new_thread(process_serial_output, ())
@ -927,6 +938,16 @@ def run_tests() -> None:
machine.execute("sync")
def serial_stdout_on() -> None:
global log
log._print_serial_logs = True
def serial_stdout_off() -> None:
global log
log._print_serial_logs = False
@contextmanager
def subtest(name: str) -> Iterator[None]:
with log.nested(name):

View file

@ -25,13 +25,21 @@ rec {
name = "nixos-test-driver";
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ (python3.withPackages (p: [ p.ptpython ])) ];
buildInputs = [ (python3.withPackages (p: [ p.ptpython p.colorama ])) ];
checkInputs = with python3Packages; [ pylint black mypy ];
dontUnpack = true;
preferLocalBuild = true;
buildPhase = ''
python <<EOF
from pydoc import importfile
with open('driver-exports', 'w') as fp:
fp.write(','.join(dir(importfile('${testDriverScript}'))))
EOF
'';
doCheck = true;
checkPhase = ''
mypy --disallow-untyped-defs \
@ -50,6 +58,8 @@ rec {
wrapProgram $out/bin/nixos-test-driver \
--prefix PATH : "${lib.makeBinPath [ qemu_pkg vde2 netpbm coreutils ]}" \
install -m 0644 -vD driver-exports $out/nix-support/driver-exports
'';
};
@ -73,7 +83,9 @@ rec {
LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
'';
passthru = driver.passthru;
passthru = driver.passthru // {
inherit driver;
};
inherit pos;
};
@ -146,7 +158,7 @@ rec {
in
lib.warnIf skipLint "Linting is disabled" (runCommand testDriverName
{
buildInputs = [ makeWrapper ];
nativeBuildInputs = [ makeWrapper ];
testScript = testScript';
preferLocalBuild = true;
testName = name;
@ -159,7 +171,10 @@ rec {
echo -n "$testScript" > $out/test-script
${lib.optionalString (!skipLint) ''
${python3Packages.black}/bin/black --check --diff $out/test-script
PYFLAKES_BUILTINS="$(
echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
< ${lib.escapeShellArg "${testDriver}/nix-support/driver-exports"}
)" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
''}
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
@ -193,6 +208,8 @@ rec {
(node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
nodeNames;
nodeHostNames = map (c: c.config.system.name) (lib.attrValues driver.nodes);
in
if lib.length invalidNodeNames > 0 then
throw ''

View file

@ -82,8 +82,7 @@ in
packages = mkOption {
type = types.listOf types.package;
default = with pkgs.kbdKeymaps; [ dvp neo ];
defaultText = "with pkgs.kbdKeymaps; [ dvp neo ]";
default = [ ];
description = ''
List of additional packages that provide console fonts, keymaps and
other resources for virtual consoles use.

View file

@ -448,6 +448,40 @@ in
(mkIf cfg.enable {
environment.systemPackages = [ pkgs.fontconfig ];
environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/";
security.apparmor.includes."abstractions/fonts" = ''
# fonts.conf
r ${pkg.out}/etc/fonts/fonts.conf,
# fontconfig default config files
r ${pkg.out}/etc/fonts/conf.d/*.conf,
# 00-nixos-cache.conf
r ${cacheConf},
# 10-nixos-rendering.conf
r ${renderConf},
# 50-user.conf
${optionalString cfg.includeUserConf ''
r ${pkg.out}/etc/fonts/conf.d.bak/50-user.conf,
''}
# local.conf (indirect priority 51)
${optionalString (cfg.localConf != "") ''
r ${localConf},
''}
# 52-nixos-default-fonts.conf
r ${defaultFontsConf},
# 53-no-bitmaps.conf
r ${rejectBitmaps},
${optionalString (!cfg.allowType1) ''
# 53-nixos-reject-type1.conf
r ${rejectType1},
''}
'';
})
(mkIf cfg.enable {
fonts.fontconfig.confPackages = [ confPkg ];

View file

@ -87,5 +87,12 @@ in
environment.etc."ld-nix.so.preload".text = ''
${providerLibPath}
'';
security.apparmor.includes = {
"abstractions/base" = ''
r /etc/ld-nix.so.preload,
r ${config.environment.etc."ld-nix.so.preload".source},
mr ${providerLibPath},
'';
};
};
}

View file

@ -9,7 +9,7 @@ with lib;
isoImage.edition = "gnome";
services.xserver.desktopManager.gnome3 = {
services.xserver.desktopManager.gnome = {
# Add firefox to favorite-apps
favoriteAppsOverride = ''
[org.gnome.shell]

View file

@ -162,12 +162,14 @@ let
isolinuxCfg = concatStringsSep "\n"
([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null;
# Setup instructions for rEFInd.
refind =
if targetArch == "x64" then
if refindBinary != null then
''
# Adds rEFInd to the ISO.
cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/
cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/boot/
''
else
"# No refind for ${targetArch}"
@ -186,7 +188,10 @@ let
# Fonts can be loaded?
# (This font is assumed to always be provided as a fallback by NixOS)
if loadfont (hd0)/EFI/boot/unicode.pf2; then
if loadfont /EFI/boot/unicode.pf2; then
set with_fonts=true
fi
if [ "\$textmode" != "true" -a "\$with_fonts" == "true" ]; then
# Use graphical term, it can be either with background image or a theme.
# input is "console", while output is "gfxterm".
# This enables "serial" input and output only when possible.
@ -207,11 +212,11 @@ let
${ # When there is a theme configured, use it, otherwise use the background image.
if config.isoImage.grubTheme != null then ''
# Sets theme.
set theme=(hd0)/EFI/boot/grub-theme/theme.txt
set theme=/EFI/boot/grub-theme/theme.txt
# Load theme fonts
$(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (hd0)/EFI/boot/grub-theme/%P\n")
$(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont /EFI/boot/grub-theme/%P\n")
'' else ''
if background_image (hd0)/EFI/boot/efi-background.png; then
if background_image /EFI/boot/efi-background.png; then
# Black background means transparent background when there
# is a background image set... This seems undocumented :(
set color_normal=black/black
@ -228,7 +233,10 @@ let
# Notes about grub:
# * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you
# will get white-on-black console-like text on sub-menus. *sigh*
efiDir = pkgs.runCommand "efi-directory" {} ''
efiDir = pkgs.runCommand "efi-directory" {
nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ];
strictDeps = true;
} ''
mkdir -p $out/EFI/boot/
# ALWAYS required modules.
@ -258,12 +266,14 @@ let
# Make our own efi program, we can't rely on "grub-install" since it seems to
# probe for devices, even with --skip-fs-probe.
${grubPkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
grub-mkimage --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
$MODULES
cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
cat <<EOF > $out/EFI/boot/grub.cfg
set with_fonts=false
set textmode=false
# If you want to use serial for "terminal_*" commands, you need to set one up:
# Example manual configuration:
# → serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
@ -273,8 +283,28 @@ let
export with_serial
clear
set timeout=10
# This message will only be viewable when "gfxterm" is not used.
echo ""
echo "Loading graphical boot menu..."
echo ""
echo "Press 't' to use the text boot menu on this console..."
echo ""
${grubMenuCfg}
hiddenentry 'Text mode' --hotkey 't' {
loadfont /EFI/boot/unicode.pf2
set textmode=true
terminal_output gfxterm console
}
hiddenentry 'GUI mode' --hotkey 'g' {
$(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont /EFI/boot/grub-theme/%P\n")
set textmode=false
terminal_output gfxterm
}
# If the parameter iso_path is set, append the findiso parameter to the kernel
# line. We need this to allow the nixos iso to be booted from grub directly.
if [ \''${iso_path} ] ; then
@ -337,11 +367,15 @@ let
}
}
menuentry 'rEFInd' --class refind {
# UUID is hard-coded in the derivation.
search --set=root --no-floppy --fs-uuid 1234-5678
chainloader (\$root)/EFI/boot/refind_x64.efi
}
${lib.optionalString (refindBinary != null) ''
# GRUB apparently cannot do "chainloader" operations on "CD".
if [ "\$root" != "cd0" ]; then
menuentry 'rEFInd' --class refind {
# \$root defaults to the drive the EFI is found on.
chainloader (\$root)/EFI/boot/${refindBinary}
}
fi
''}
menuentry 'Firmware Setup' --class settings {
fwsetup
clear
@ -357,7 +391,10 @@ let
${refind}
'';
efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; }
efiImg = pkgs.runCommand "efi-image_eltorito" {
nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
strictDeps = true;
}
# Be careful about determinism: du --apparent-size,
# dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
''
@ -377,10 +414,10 @@ let
echo "Usage size: $usage_size"
echo "Image size: $image_size"
truncate --size=$image_size "$out"
${pkgs.libfaketime}/bin/faketime "2000-01-01 00:00:00" ${pkgs.dosfstools}/sbin/mkfs.vfat -i 12345678 -n EFIBOOT "$out"
faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out"
mcopy -psvm -i "$out" ./EFI ./boot ::
# Verify the FAT partition.
${pkgs.dosfstools}/sbin/fsck.vfat -vn "$out"
fsck.vfat -vn "$out"
''; # */
# Name used by UEFI for architectures.
@ -389,6 +426,8 @@ let
"ia32"
else if pkgs.stdenv.isx86_64 then
"x64"
else if pkgs.stdenv.isAarch32 then
"arm"
else if pkgs.stdenv.isAarch64 then
"aa64"
else

View file

@ -1,14 +0,0 @@
{ config, ... }:
{
imports = [
../sd-card/sd-image-raspberrypi4-installer.nix
];
config = {
warnings = [
''
.../cd-dvd/sd-image-raspberrypi4.nix is deprecated and will eventually be removed.
Please switch to .../sd-card/sd-image-raspberrypi4-installer.nix, instead.
''
];
};
}

View file

@ -18,13 +18,6 @@
# - ttyAMA0: for QEMU's -machine virt
boot.kernelParams = ["console=ttyS0,115200n8" "console=ttyAMA0,115200n8" "console=tty0"];
boot.initrd.availableKernelModules = [
# Allows early (earlier) modesetting for the Raspberry Pi
"vc4" "bcm2835_dma" "i2c_bcm2835"
# Allows early (earlier) modesetting for Allwinner SoCs
"sun4i_drm" "sun8i_drm_hdmi" "sun8i_mixer"
];
sdImage = {
populateFirmwareCommands = let
configTxt = pkgs.writeText "config.txt" ''

View file

@ -1,10 +0,0 @@
{
imports = [
../../profiles/installation-device.nix
./sd-image-raspberrypi4.nix
];
# the installation media is also the installation target,
# so we don't want to provide the installation configuration.nix.
installer.cloneConfig = false;
}

View file

@ -1,8 +0,0 @@
# To build, use:
# nix-build nixos -I nixos-config=nixos/modules/installer/sd-card/sd-image-raspberrypi4.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
{
imports = [ ./sd-image-aarch64.nix ];
boot.kernelPackages = pkgs.linuxPackages_rpi4;
}

View file

@ -29,6 +29,7 @@ in
imports = [
(mkRemovedOptionModule [ "sdImage" "bootPartitionID" ] "The FAT partition for SD image now only holds the Raspberry Pi firmware files. Use firmwarePartitionID to configure that partition's ID.")
(mkRemovedOptionModule [ "sdImage" "bootSize" ] "The boot files for SD image have been moved to the main ext4 partition. The FAT partition now only holds the Raspberry Pi firmware files. Changing its size may not be required.")
../../profiles/all-hardware.nix
];
options.sdImage = {

View file

@ -1,6 +1,6 @@
{
x86_64-linux = "/nix/store/iwfs2bfcy7lqwhri94p2i6jc87ih55zk-nix-2.3.10";
i686-linux = "/nix/store/a3ccfvy9i5n418d5v0bir330kbcz3vj8-nix-2.3.10";
aarch64-linux = "/nix/store/bh5g6cv7bv35iz853d3xv2sphn51ybmb-nix-2.3.10";
x86_64-darwin = "/nix/store/8c98r6zlwn2d40qm7jnnrr2rdlqviszr-nix-2.3.10";
x86_64-linux = "/nix/store/d1ppfhjhdwcsb4npfzyifv5z8i00fzsk-nix-2.3.11";
i686-linux = "/nix/store/c6ikndcrzwpfn2sb5b9xb1f17p9b8iga-nix-2.3.11";
aarch64-linux = "/nix/store/fb0lfrn0m8s197d264jzd64vhz9c8zbx-nix-2.3.11";
x86_64-darwin = "/nix/store/qvb86ffv08q3r66qbd6nqifz425lyyhf-nix-2.3.11";
}

View file

@ -44,7 +44,7 @@ with lib;
# Enable GDM/GNOME by uncommenting above two lines and two lines below.
# services.xserver.displayManager.gdm.enable = true;
# services.xserver.desktopManager.gnome3.enable = true;
# services.xserver.desktopManager.gnome.enable = true;
# Set your time zone.
# time.timeZone = "Europe/Amsterdam";

View file

@ -315,7 +315,7 @@ in
restya-board = 284;
mighttpd2 = 285;
hass = 286;
monero = 287;
#monero = 287; # dynamically allocated as of 2021-05-08
ceph = 288;
duplicati = 289;
monetdb = 290;
@ -617,7 +617,7 @@ in
restya-board = 284;
mighttpd2 = 285;
hass = 286;
monero = 287;
# monero = 287; # dynamically allocated as of 2021-05-08
ceph = 288;
duplicati = 289;
monetdb = 290;

View file

@ -163,6 +163,7 @@
./programs/neovim.nix
./programs/nm-applet.nix
./programs/npm.nix
./programs/noisetorch.nix
./programs/oblogout.nix
./programs/partition-manager.nix
./programs/plotinus.nix
@ -211,7 +212,6 @@
./rename.nix
./security/acme.nix
./security/apparmor.nix
./security/apparmor-suid.nix
./security/audit.nix
./security/auditd.nix
./security/ca.nix
@ -339,21 +339,21 @@
./services/desktops/malcontent.nix
./services/desktops/pipewire/pipewire.nix
./services/desktops/pipewire/pipewire-media-session.nix
./services/desktops/gnome3/at-spi2-core.nix
./services/desktops/gnome3/chrome-gnome-shell.nix
./services/desktops/gnome3/evolution-data-server.nix
./services/desktops/gnome3/glib-networking.nix
./services/desktops/gnome3/gnome-initial-setup.nix
./services/desktops/gnome3/gnome-keyring.nix
./services/desktops/gnome3/gnome-online-accounts.nix
./services/desktops/gnome3/gnome-online-miners.nix
./services/desktops/gnome3/gnome-remote-desktop.nix
./services/desktops/gnome3/gnome-settings-daemon.nix
./services/desktops/gnome3/gnome-user-share.nix
./services/desktops/gnome3/rygel.nix
./services/desktops/gnome3/sushi.nix
./services/desktops/gnome3/tracker.nix
./services/desktops/gnome3/tracker-miners.nix
./services/desktops/gnome/at-spi2-core.nix
./services/desktops/gnome/chrome-gnome-shell.nix
./services/desktops/gnome/evolution-data-server.nix
./services/desktops/gnome/glib-networking.nix
./services/desktops/gnome/gnome-initial-setup.nix
./services/desktops/gnome/gnome-keyring.nix
./services/desktops/gnome/gnome-online-accounts.nix
./services/desktops/gnome/gnome-online-miners.nix
./services/desktops/gnome/gnome-remote-desktop.nix
./services/desktops/gnome/gnome-settings-daemon.nix
./services/desktops/gnome/gnome-user-share.nix
./services/desktops/gnome/rygel.nix
./services/desktops/gnome/sushi.nix
./services/desktops/gnome/tracker.nix
./services/desktops/gnome/tracker-miners.nix
./services/desktops/neard.nix
./services/desktops/profile-sync-daemon.nix
./services/desktops/system-config-printer.nix
@ -472,6 +472,7 @@
./services/misc/cgminer.nix
./services/misc/confd.nix
./services/misc/couchpotato.nix
./services/misc/dendrite.nix
./services/misc/devmon.nix
./services/misc/dictd.nix
./services/misc/duckling.nix
@ -514,7 +515,6 @@
./services/misc/mame.nix
./services/misc/matrix-appservice-discord.nix
./services/misc/matrix-appservice-irc.nix
./services/misc/matrix-dendrite.nix
./services/misc/matrix-synapse.nix
./services/misc/mautrix-telegram.nix
./services/misc/mbpfan.nix
@ -690,6 +690,7 @@
./services/networking/gale.nix
./services/networking/gateone.nix
./services/networking/gdomap.nix
./services/networking/ghostunnel.nix
./services/networking/git-daemon.nix
./services/networking/gnunet.nix
./services/networking/go-neb.nix
@ -896,6 +897,7 @@
./services/system/kerberos/default.nix
./services/system/nscd.nix
./services/system/saslauthd.nix
./services/system/self-deploy.nix
./services/system/uptimed.nix
./services/torrent/deluge.nix
./services/torrent/flexget.nix

View file

@ -37,6 +37,9 @@ in
# drives.
"uas"
# SD cards.
"sdhci_pci"
# Firewire support. Not tested.
"ohci1394" "sbp2"
@ -46,11 +49,66 @@ in
# VMware support.
"mptspi" "vmxnet3" "vsock"
] ++ lib.optional platform.isx86 "vmw_balloon"
++ lib.optionals (!platform.isAarch64) [ # not sure where else they're missing
++ lib.optionals (!platform.isAarch64 && !platform.isAarch32) [ # not sure where else they're missing
"vmw_vmci" "vmwgfx" "vmw_vsock_vmci_transport"
# Hyper-V support.
"hv_storvsc"
] ++ lib.optionals (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [
# Most of the following falls into two categories:
# - early KMS / early display
# - early storage (e.g. USB) support
# Allows using framebuffer configured by the initial boot firmware
"simplefb"
# Allwinner support
# Required for early KMS
"sun4i-drm"
"sun8i-mixer" # Audio, but required for kms
# PWM for the backlight
"pwm-sun4i"
# Broadcom
"vc4"
] ++ lib.optionals pkgs.stdenv.isAarch64 [
# Most of the following falls into two categories:
# - early KMS / early display
# - early storage (e.g. USB) support
# Broadcom
"pcie-brcmstb"
# Rockchip
"dw-hdmi"
"dw-mipi-dsi"
"rockchipdrm"
"rockchip-rga"
"phy-rockchip-pcie"
"pcie-rockchip-host"
# Misc. uncategorized hardware
# Used for some platform's integrated displays
"panel-simple"
"pwm-bl"
# Power supply drivers, some platforms need them for USB
"axp20x-ac-power"
"axp20x-battery"
"pinctrl-axp209"
"mp8859"
# USB drivers
"xhci-pci-renesas"
# Misc "weak" dependencies
"analogix-dp"
"analogix-anx6345" # For DP or eDP (e.g. integrated display)
];
# Include lots of firmware.

View file

@ -36,6 +36,7 @@ with lib;
security.virtualisation.flushL1DataCache = mkDefault "always";
security.apparmor.enable = mkDefault true;
security.apparmor.killUnconfinedConfinables = mkDefault true;
boot.kernelParams = [
# Slab/slub sanity checks, redzoning, and poisoning

View file

@ -99,5 +99,13 @@ with lib;
# because we have the firewall enabled. This makes installs from the
# console less cumbersome if the machine has a public IP.
networking.firewall.logRefusedConnections = mkDefault false;
# Prevent installation media from evacuating persistent storage, as their
# var directory is not persistent and it would thus result in deletion of
# those entries.
environment.etc."systemd/pstore.conf".text = ''
[PStore]
Unlink=no
'';
};
}

View file

@ -1,6 +1,6 @@
# Global configuration for atop.
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
with lib;
@ -12,11 +12,83 @@ in
options = {
programs.atop = {
programs.atop = rec {
enable = mkEnableOption "Atop";
package = mkOption {
type = types.package;
default = pkgs.atop;
description = ''
Which package to use for Atop.
'';
};
netatop = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to install and enable the netatop kernel module.
Note: this sets the kernel taint flag "O" for loading out-of-tree modules.
'';
};
package = mkOption {
type = types.package;
default = config.boot.kernelPackages.netatop;
description = ''
Which package to use for netatop.
'';
};
};
atopgpu.enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to install and enable the atopgpud daemon to get information about
NVIDIA gpus.
'';
};
setuidWrapper.enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to install a setuid wrapper for Atop. This is required to use some of
the features as non-root user (e.g.: ipc information, netatop, atopgpu).
Atop tries to drop the root privileges shortly after starting.
'';
};
atopService.enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable the atop service responsible for storing statistics for
long-term analysis.
'';
};
atopRotateTimer.enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable the atop-rotate timer, which restarts the atop service
daily to make sure the data files are rotate.
'';
};
atopacctService.enable = mkOption {
type = types.bool;
default = true;
description = ''
Whether to enable the atopacct service which manages process accounting.
This allows Atop to gather data about processes that disappeared in between
two refresh intervals.
'';
};
settings = mkOption {
type = types.attrs;
default = {};
default = { };
example = {
flags = "a1f";
interval = 5;
@ -25,12 +97,50 @@ in
Parameters to be written to <filename>/etc/atoprc</filename>.
'';
};
};
};
config = mkIf (cfg.settings != {}) {
environment.etc.atoprc.text =
concatStrings (mapAttrsToList (n: v: "${n} ${toString v}\n") cfg.settings);
};
config = mkIf cfg.enable (
let
atop =
if cfg.atopgpu.enable then
(cfg.package.override { withAtopgpu = true; })
else
cfg.package;
in
{
environment.etc = mkIf (cfg.settings != { }) {
atoprc.text = concatStrings
(mapAttrsToList
(n: v: ''
${n} ${toString v}
'')
cfg.settings);
};
environment.systemPackages = [ atop (lib.mkIf cfg.netatop.enable cfg.netatop.package) ];
boot.extraModulePackages = [ (lib.mkIf cfg.netatop.enable cfg.netatop.package) ];
systemd =
let
mkSystemd = type: cond: name: restartTriggers: {
${name} = lib.mkIf cond {
inherit restartTriggers;
wantedBy = [ (if type == "services" then "multi-user.target" else if type == "timers" then "timers.target" else null) ];
};
};
mkService = mkSystemd "services";
mkTimer = mkSystemd "timers";
in
{
packages = [ atop (lib.mkIf cfg.netatop.enable cfg.netatop.package) ];
services =
mkService cfg.atopService.enable "atop" [ atop ]
// mkService cfg.atopacctService.enable "atopacct" [ atop ]
// mkService cfg.netatop.enable "netatop" [ cfg.netatop.package ]
// mkService cfg.atopgpu.enable "atopgpu" [ atop ];
timers = mkTimer cfg.atopRotateTimer.enable "atop-rotate" [ atop ];
};
security.wrappers =
lib.mkIf cfg.setuidWrapper.enable { atop = { source = "${atop}/bin/atop"; }; };
}
);
}

View file

@ -54,6 +54,8 @@ in
services.dbus.packages = [ pkgs.dconf ];
systemd.packages = [ pkgs.dconf ];
# For dconf executable
environment.systemPackages = [ pkgs.dconf ];

View file

@ -30,9 +30,9 @@ with lib;
config = mkIf config.programs.file-roller.enable {
environment.systemPackages = [ pkgs.gnome3.file-roller ];
environment.systemPackages = [ pkgs.gnome.file-roller ];
services.dbus.packages = [ pkgs.gnome3.file-roller ];
services.dbus.packages = [ pkgs.gnome.file-roller ];
};

View file

@ -15,10 +15,10 @@ in {
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.gnome3.geary ];
environment.systemPackages = [ pkgs.gnome.geary ];
programs.dconf.enable = true;
services.gnome3.gnome-keyring.enable = true;
services.gnome3.gnome-online-accounts.enable = true;
services.gnome.gnome-keyring.enable = true;
services.gnome.gnome-online-accounts.enable = true;
};
}

View file

@ -41,9 +41,9 @@ with lib;
config = mkIf config.programs.gnome-disks.enable {
environment.systemPackages = [ pkgs.gnome3.gnome-disk-utility ];
environment.systemPackages = [ pkgs.gnome.gnome-disk-utility ];
services.dbus.packages = [ pkgs.gnome3.gnome-disk-utility ];
services.dbus.packages = [ pkgs.gnome.gnome-disk-utility ];
};

View file

@ -13,7 +13,7 @@ with lib;
# Added 2019-08-09
imports = [
(mkRenamedOptionModule
[ "services" "gnome3" "gnome-documents" "enable" ]
[ "services" "gnome" "gnome-documents" "enable" ]
[ "programs" "gnome-documents" "enable" ])
];
@ -41,13 +41,13 @@ with lib;
config = mkIf config.programs.gnome-documents.enable {
environment.systemPackages = [ pkgs.gnome3.gnome-documents ];
environment.systemPackages = [ pkgs.gnome.gnome-documents ];
services.dbus.packages = [ pkgs.gnome3.gnome-documents ];
services.dbus.packages = [ pkgs.gnome.gnome-documents ];
services.gnome3.gnome-online-accounts.enable = true;
services.gnome.gnome-online-accounts.enable = true;
services.gnome3.gnome-online-miners.enable = true;
services.gnome.gnome-online-miners.enable = true;
};

View file

@ -28,9 +28,9 @@ in
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.gnome3.gnome-terminal ];
services.dbus.packages = [ pkgs.gnome3.gnome-terminal ];
systemd.packages = [ pkgs.gnome3.gnome-terminal ];
environment.systemPackages = [ pkgs.gnome.gnome-terminal ];
services.dbus.packages = [ pkgs.gnome.gnome-terminal ];
systemd.packages = [ pkgs.gnome.gnome-terminal ];
programs.bash.vteIntegration = true;
programs.zsh.vteIntegration = true;

View file

@ -27,10 +27,10 @@ with lib;
###### implementation
config = mkIf config.programs.gpaste.enable {
environment.systemPackages = [ pkgs.gnome3.gpaste ];
services.dbus.packages = [ pkgs.gnome3.gpaste ];
systemd.packages = [ pkgs.gnome3.gpaste ];
environment.systemPackages = [ pkgs.gnome.gpaste ];
services.dbus.packages = [ pkgs.gnome.gpaste ];
systemd.packages = [ pkgs.gnome.gpaste ];
# gnome-control-center crashes in Keyboard Shortcuts pane without the GSettings schemas.
services.xserver.desktopManager.gnome3.sessionPath = [ pkgs.gnome3.gpaste ];
services.xserver.desktopManager.gnome.sessionPath = [ pkgs.gnome.gpaste ];
};
}

View file

@ -0,0 +1,25 @@
{ config, pkgs, lib, ... }:
with lib;
let cfg = config.programs.noisetorch;
in {
options.programs.noisetorch = {
enable = mkEnableOption "noisetorch + setcap wrapper";
package = mkOption {
type = types.package;
default = pkgs.noisetorch;
description = ''
The noisetorch package to use.
'';
};
};
config = mkIf cfg.enable {
security.wrappers.noisetorch = {
source = "${cfg.package}/bin/noisetorch";
capabilities = "cap_sys_resource=+ep";
};
};
}

View file

@ -145,18 +145,10 @@ in {
programs.feedbackd.enable = true;
# https://source.puri.sm/Librem5/phosh/-/issues/303
security.pam.services.phosh = {
text = ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so user != root quiet_success
auth required pam_securetty.so
auth requisite pam_nologin.so
'';
};
security.pam.services.phosh = {};
services.gnome3.core-shell.enable = true;
services.gnome3.core-os-services.enable = true;
services.gnome.core-shell.enable = true;
services.gnome.core-os-services.enable = true;
services.xserver.displayManager.sessionPackages = [ pkgs.phosh ];
environment.etc."phosh/phoc.ini".source =

View file

@ -31,14 +31,14 @@ with lib;
config = mkIf config.programs.seahorse.enable {
programs.ssh.askPassword = mkDefault "${pkgs.gnome3.seahorse}/libexec/seahorse/ssh-askpass";
programs.ssh.askPassword = mkDefault "${pkgs.gnome.seahorse}/libexec/seahorse/ssh-askpass";
environment.systemPackages = [
pkgs.gnome3.seahorse
pkgs.gnome.seahorse
];
services.dbus.packages = [
pkgs.gnome3.seahorse
pkgs.gnome.seahorse
];
};

View file

@ -31,6 +31,7 @@ let
extraOptions = cfg.extraOptions;
withBaseWrapper = cfg.wrapperFeatures.base;
withGtkWrapper = cfg.wrapperFeatures.gtk;
isNixOS = true;
};
in {
options.programs.sway = {
@ -38,9 +39,8 @@ in {
Sway, the i3-compatible tiling Wayland compositor. You can manually launch
Sway by executing "exec sway" on a TTY. Copy /etc/sway/config to
~/.config/sway/config to modify the default configuration. See
https://github.com/swaywm/sway/wiki and "man 5 sway" for more information.
Please have a look at the "extraSessionCommands" example for running
programs natively under Wayland'';
<link xlink:href="https://github.com/swaywm/sway/wiki" /> and
"man 5 sway" for more information'';
wrapperFeatures = mkOption {
type = wrapperOptions;
@ -55,16 +55,20 @@ in {
type = types.lines;
default = "";
example = ''
# SDL:
export SDL_VIDEODRIVER=wayland
# needs qt5.qtwayland in systemPackages
export QT_QPA_PLATFORM=wayland
# QT (needs qt5.qtwayland in systemPackages):
export QT_QPA_PLATFORM=wayland-egl
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
# Fix for some Java AWT applications (e.g. Android Studio),
# use this if they aren't displayed properly:
export _JAVA_AWT_WM_NONREPARENTING=1
'';
description = ''
Shell commands executed just before Sway is started.
Shell commands executed just before Sway is started. See
<link xlink:href="https://github.com/swaywm/sway/wiki/Running-programs-natively-under-wayland" />
and <link xlink:href="https://github.com/swaywm/wlroots/blob/master/docs/env_vars.md" />
for some useful environment variables.
'';
};
@ -94,13 +98,15 @@ in {
'';
example = literalExample ''
with pkgs; [
xwayland
i3status i3status-rust
termite rofi light
]
'';
description = ''
Extra packages to be installed system wide.
Extra packages to be installed system wide. See
<link xlink:href="https://github.com/swaywm/sway/wiki/Useful-add-ons-for-sway" /> and
<link xlink:href="https://github.com/swaywm/sway/wiki/i3-Migration-Guide#common-x11-apps-used-on-i3-with-wayland-alternatives" />
for a list of useful software.
'';
};
@ -120,8 +126,11 @@ in {
systemPackages = [ swayPackage ] ++ cfg.extraPackages;
etc = {
"sway/config".source = mkOptionDefault "${swayPackage}/etc/sway/config";
#"sway/security.d".source = mkOptionDefault "${swayPackage}/etc/sway/security.d/";
#"sway/config.d".source = mkOptionDefault "${swayPackage}/etc/sway/config.d/";
"sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
# Import the most important environment variables into the D-Bus and systemd
# user environments (e.g. required for screen sharing and Pinentry prompts):
exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
'';
};
};
security.pam.services.swaylock = {};
@ -131,7 +140,9 @@ in {
# To make a Sway session available if a display manager like SDDM is enabled:
services.xserver.displayManager.sessionPackages = [ swayPackage ];
programs.xwayland.enable = mkDefault true;
# For screen sharing (this option only has an effect with xdg.portal.enable):
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-wlr ];
};
meta.maintainers = with lib.maintainers; [ gnidorah primeos colemickens ];
meta.maintainers = with lib.maintainers; [ primeos colemickens ];
}

View file

@ -1,49 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.security.apparmor;
in
with lib;
{
imports = [
(mkRenamedOptionModule [ "security" "virtualization" "flushL1DataCache" ] [ "security" "virtualisation" "flushL1DataCache" ])
];
options.security.apparmor.confineSUIDApplications = mkOption {
type = types.bool;
default = true;
description = ''
Install AppArmor profiles for commonly-used SUID application
to mitigate potential privilege escalation attacks due to bugs
in such applications.
Currently available profiles: ping
'';
};
config = mkIf (cfg.confineSUIDApplications) {
security.apparmor.profiles = [ (pkgs.writeText "ping" ''
#include <tunables/global>
/run/wrappers/bin/ping {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/nameservice>
capability net_raw,
capability setuid,
network inet raw,
${pkgs.stdenv.cc.libc.out}/lib/*.so mr,
${pkgs.libcap.lib}/lib/libcap.so* mr,
${pkgs.attr.out}/lib/libattr.so* mr,
${pkgs.iputils}/bin/ping mixr,
#/etc/modules.conf r,
## Site-specific additions and overrides. See local/README for details.
##include <local/bin.ping>
}
'') ];
};
}

View file

@ -1,59 +1,216 @@
{ config, lib, pkgs, ... }:
with lib;
let
inherit (lib) mkIf mkOption types concatMapStrings;
inherit (builtins) attrNames head map match readFile;
inherit (lib) types;
inherit (config.environment) etc;
cfg = config.security.apparmor;
mkDisableOption = name: mkEnableOption name // {
default = true;
example = false;
};
enabledPolicies = filterAttrs (n: p: p.enable) cfg.policies;
in
{
options = {
security.apparmor = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the AppArmor Mandatory Access Control system.";
};
profiles = mkOption {
type = types.listOf types.path;
default = [];
description = "List of files containing AppArmor profiles.";
};
packages = mkOption {
type = types.listOf types.package;
default = [];
description = "List of packages to be added to apparmor's include path";
};
};
};
imports = [
(mkRemovedOptionModule [ "security" "apparmor" "confineSUIDApplications" ] "Please use the new options: `security.apparmor.policies.<policy>.enable'.")
(mkRemovedOptionModule [ "security" "apparmor" "profiles" ] "Please use the new option: `security.apparmor.policies'.")
apparmor/includes.nix
apparmor/profiles.nix
];
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.apparmor-utils ];
options = {
security.apparmor = {
enable = mkEnableOption ''
the AppArmor Mandatory Access Control system.
boot.kernelParams = [ "apparmor=1" "security=apparmor" ];
If you're enabling this module on a running system,
note that a reboot will be required to activate AppArmor in the kernel.
systemd.services.apparmor = let
paths = concatMapStrings (s: " -I ${s}/etc/apparmor.d")
([ pkgs.apparmor-profiles ] ++ cfg.packages);
in {
after = [ "local-fs.target" ];
before = [ "sysinit.target" ];
wantedBy = [ "multi-user.target" ];
unitConfig = {
DefaultDependencies = "no";
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
ExecStart = map (p:
''${pkgs.apparmor-parser}/bin/apparmor_parser -rKv ${paths} "${p}"''
) cfg.profiles;
ExecStop = map (p:
''${pkgs.apparmor-parser}/bin/apparmor_parser -Rv "${p}"''
) cfg.profiles;
ExecReload = map (p:
''${pkgs.apparmor-parser}/bin/apparmor_parser --reload ${paths} "${p}"''
) cfg.profiles;
};
};
};
Also, beware that enabling this module privileges stability over security
by not trying to kill unconfined but newly confinable running processes by default,
though it would be needed because AppArmor can only confine new
or already confined processes of an executable.
This killing would for instance be necessary when upgrading to a NixOS revision
introducing for the first time an AppArmor profile for the executable
of a running process.
Enable <xref linkend="opt-security.apparmor.killUnconfinedConfinables"/>
if you want this service to do such killing
by sending a <literal>SIGTERM</literal> to those running processes'';
policies = mkOption {
description = ''
AppArmor policies.
'';
type = types.attrsOf (types.submodule ({ name, config, ... }: {
options = {
enable = mkDisableOption "loading of the profile into the kernel";
enforce = mkDisableOption "enforcing of the policy or only complain in the logs";
profile = mkOption {
description = "The policy of the profile.";
type = types.lines;
apply = pkgs.writeText name;
};
};
}));
default = {};
};
includes = mkOption {
type = types.attrsOf types.lines;
default = {};
description = ''
List of paths to be added to AppArmor's searched paths
when resolving <literal>include</literal> directives.
'';
apply = mapAttrs pkgs.writeText;
};
packages = mkOption {
type = types.listOf types.package;
default = [];
description = "List of packages to be added to AppArmor's include path";
};
enableCache = mkEnableOption ''
caching of AppArmor policies
in <literal>/var/cache/apparmor/</literal>.
Beware that AppArmor policies almost always contain Nix store paths,
and thus produce at each change of these paths
a new cached version accumulating in the cache'';
killUnconfinedConfinables = mkEnableOption ''
killing of processes which have an AppArmor profile enabled
(in <xref linkend="opt-security.apparmor.policies"/>)
but are not confined (because AppArmor can only confine new processes).
This is only sending a gracious <literal>SIGTERM</literal> signal to the processes,
not a <literal>SIGKILL</literal>.
Beware that due to a current limitation of AppArmor,
only profiles with exact paths (and no name) can enable such kills'';
};
};
config = mkIf cfg.enable {
assertions = map (policy:
{ assertion = match ".*/.*" policy == null;
message = "`security.apparmor.policies.\"${policy}\"' must not contain a slash.";
# Because, for instance, aa-remove-unknown uses profiles_names_list() in rc.apparmor.functions
# which does not recurse into sub-directories.
}
) (attrNames cfg.policies);
environment.systemPackages = [
pkgs.apparmor-utils
pkgs.apparmor-bin-utils
];
environment.etc."apparmor.d".source = pkgs.linkFarm "apparmor.d" (
# It's important to put only enabledPolicies here and not all cfg.policies
# because aa-remove-unknown reads profiles from all /etc/apparmor.d/*
mapAttrsToList (name: p: { inherit name; path = p.profile; }) enabledPolicies ++
mapAttrsToList (name: path: { inherit name path; }) cfg.includes
);
environment.etc."apparmor/parser.conf".text = ''
${if cfg.enableCache then "write-cache" else "skip-cache"}
cache-loc /var/cache/apparmor
Include /etc/apparmor.d
'' +
concatMapStrings (p: "Include ${p}/etc/apparmor.d\n") cfg.packages;
# For aa-logprof
environment.etc."apparmor/apparmor.conf".text = ''
'';
# For aa-logprof
environment.etc."apparmor/severity.db".source = pkgs.apparmor-utils + "/etc/apparmor/severity.db";
environment.etc."apparmor/logprof.conf".source = pkgs.runCommand "logprof.conf" {
header = ''
[settings]
# /etc/apparmor.d/ is read-only on NixOS
profiledir = /var/cache/apparmor/logprof
inactive_profiledir = /etc/apparmor.d/disable
# Use: journalctl -b --since today --grep audit: | aa-logprof
logfiles = /dev/stdin
parser = ${pkgs.apparmor-parser}/bin/apparmor_parser
ldd = ${pkgs.glibc.bin}/bin/ldd
logger = ${pkgs.util-linux}/bin/logger
# customize how file ownership permissions are presented
# 0 - off
# 1 - default of what ever mode the log reported
# 2 - force the new permissions to be user
# 3 - force all perms on the rule to be user
default_owner_prompt = 1
custom_includes = /etc/apparmor.d ${concatMapStringsSep " " (p: "${p}/etc/apparmor.d") cfg.packages}
[qualifiers]
${pkgs.runtimeShell} = icnu
${pkgs.bashInteractive}/bin/sh = icnu
${pkgs.bashInteractive}/bin/bash = icnu
${config.users.defaultUserShell} = icnu
'';
footer = "${pkgs.apparmor-utils}/etc/apparmor/logprof.conf";
passAsFile = [ "header" ];
} ''
cp $headerPath $out
sed '1,/\[qualifiers\]/d' $footer >> $out
'';
boot.kernelParams = [ "apparmor=1" "security=apparmor" ];
systemd.services.apparmor = {
after = [
"local-fs.target"
"systemd-journald-audit.socket"
];
before = [ "sysinit.target" ];
wantedBy = [ "multi-user.target" ];
unitConfig = {
Description="Load AppArmor policies";
DefaultDependencies = "no";
ConditionSecurity = "apparmor";
};
# Reloading instead of restarting enables to load new AppArmor profiles
# without necessarily restarting all services which have Requires=apparmor.service
reloadIfChanged = true;
restartTriggers = [
etc."apparmor/parser.conf".source
etc."apparmor.d".source
];
serviceConfig = let
killUnconfinedConfinables = pkgs.writeShellScript "apparmor-kill" ''
set -eu
${pkgs.apparmor-bin-utils}/bin/aa-status --json |
${pkgs.jq}/bin/jq --raw-output '.processes | .[] | .[] | select (.status == "unconfined") | .pid' |
xargs --verbose --no-run-if-empty --delimiter='\n' \
kill
'';
commonOpts = p: "--verbose --show-cache ${optionalString (!p.enforce) "--complain "}${p.profile}";
in {
Type = "oneshot";
RemainAfterExit = "yes";
ExecStartPre = "${pkgs.apparmor-utils}/bin/aa-teardown";
ExecStart = mapAttrsToList (n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --add ${commonOpts p}") enabledPolicies;
ExecStartPost = optional cfg.killUnconfinedConfinables killUnconfinedConfinables;
ExecReload =
# Add or replace into the kernel profiles in enabledPolicies
# (because AppArmor can do that without stopping the processes already confined).
mapAttrsToList (n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --replace ${commonOpts p}") enabledPolicies ++
# Remove from the kernel any profile whose name is not
# one of the names within the content of the profiles in enabledPolicies
# (indirectly read from /etc/apparmor.d/*, without recursing into sub-directory).
# Note that this does not remove profiles dynamically generated by libvirt.
[ "${pkgs.apparmor-utils}/bin/aa-remove-unknown" ] ++
# Optionaly kill the processes which are unconfined but now have a profile loaded
# (because AppArmor can only start to confine new processes).
optional cfg.killUnconfinedConfinables killUnconfinedConfinables;
ExecStop = "${pkgs.apparmor-utils}/bin/aa-teardown";
CacheDirectory = [ "apparmor" "apparmor/logprof" ];
CacheDirectoryMode = "0700";
};
};
};
meta.maintainers = with maintainers; [ julm ];
}

View file

@ -0,0 +1,317 @@
{ config, lib, pkgs, ... }:
let
inherit (builtins) attrNames hasAttr isAttrs;
inherit (lib) getLib;
inherit (config.environment) etc;
# Utility to generate an AppArmor rule
# only when the given path exists in config.environment.etc
etcRule = arg:
let go = { path ? null, mode ? "r", trail ? "" }:
lib.optionalString (hasAttr path etc)
"${mode} ${config.environment.etc.${path}.source}${trail},";
in if isAttrs arg
then go arg
else go { path = arg; };
in
{
# FIXME: most of the etcRule calls below have been
# written systematically by converting from apparmor-profiles's profiles
# without testing nor deep understanding of their uses,
# and thus may need more rules or can have less rules;
# this remains to be determined case by case,
# some may even be completely useless.
config.security.apparmor.includes = {
# This one is included by <tunables/global>
# which is usualy included before any profile.
"abstractions/tunables/alias" = ''
alias /bin -> /run/current-system/sw/bin,
alias /lib/modules -> /run/current-system/kernel/lib/modules,
alias /sbin -> /run/current-system/sw/sbin,
alias /usr -> /run/current-system/sw,
'';
"abstractions/audio" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/audio"
'' + lib.concatMapStringsSep "\n" etcRule [
"asound.conf"
"esound/esd.conf"
"libao.conf"
{ path = "pulse"; trail = "/"; }
{ path = "pulse"; trail = "/**"; }
{ path = "sound"; trail = "/"; }
{ path = "sound"; trail = "/**"; }
{ path = "alsa/conf.d"; trail = "/"; }
{ path = "alsa/conf.d"; trail = "/*"; }
"openal/alsoft.conf"
"wildmidi/wildmidi.conf"
];
"abstractions/authentication" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/authentication"
# Defined in security.pam
include <abstractions/pam>
'' + lib.concatMapStringsSep "\n" etcRule [
"nologin"
"securetty"
{ path = "security"; trail = "/*"; }
"shadow"
"gshadow"
"pwdb.conf"
"default/passwd"
"login.defs"
];
"abstractions/base" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/base"
r ${pkgs.stdenv.cc.libc}/share/locale/**,
r ${pkgs.stdenv.cc.libc}/share/locale.alias,
${lib.optionalString (pkgs.glibcLocales != null) "r ${pkgs.glibcLocales}/lib/locale/locale-archive,"}
${etcRule "localtime"}
r ${pkgs.tzdata}/share/zoneinfo/**,
r ${pkgs.stdenv.cc.libc}/share/i18n/**,
'';
"abstractions/bash" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/bash"
# bash inspects filesystems at startup
# and /etc/mtab is linked to /proc/mounts
@{PROC}/mounts
# system-wide bash configuration
'' + lib.concatMapStringsSep "\n" etcRule [
"profile.dos"
"profile"
"profile.d"
{ path = "profile.d"; trail = "/*"; }
"bashrc"
"bash.bashrc"
"bash.bashrc.local"
"bash_completion"
"bash_completion.d"
{ path = "bash_completion.d"; trail = "/*"; }
# bash relies on system-wide readline configuration
"inputrc"
# run out of /etc/bash.bashrc
"DIR_COLORS"
];
"abstractions/consoles" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/consoles"
'';
"abstractions/cups-client" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/cpus-client"
${etcRule "cups/cups-client.conf"}
'';
"abstractions/dbus-session-strict" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dbus-session-strict"
${etcRule "machine-id"}
'';
"abstractions/dconf" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dconf"
${etcRule { path = "dconf"; trail = "/**"; }}
'';
"abstractions/dri-common" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/dri-common"
${etcRule "drirc"}
'';
# The config.fonts.fontconfig NixOS module adds many files to /etc/fonts/
# by symlinking them but without exporting them outside of its NixOS module,
# those are therefore added there to this "abstractions/fonts".
"abstractions/fonts" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/fonts"
${etcRule { path = "fonts"; trail = "/**"; }}
'';
"abstractions/gnome" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/gnome"
include <abstractions/fonts>
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "gnome"; trail = "/gtkrc*"; }
{ path = "gtk"; trail = "/*"; }
{ path = "gtk-2.0"; trail = "/*"; }
{ path = "gtk-3.0"; trail = "/*"; }
"orbitrc"
{ path = "pango"; trail = "/*"; }
{ path = "/etc/gnome-vfs-2.0"; trail = "/modules/"; }
{ path = "/etc/gnome-vfs-2.0"; trail = "/modules/*"; }
"papersize"
{ path = "cups"; trail = "/lpoptions"; }
{ path = "gnome"; trail = "/defaults.list"; }
{ path = "xdg"; trail = "/{,*-}mimeapps.list"; }
"xdg/mimeapps.list"
];
"abstractions/kde" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/kde"
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "qt3"; trail = "/kstylerc"; }
{ path = "qt3"; trail = "/qt_plugins_3.3rc"; }
{ path = "qt3"; trail = "/qtrc"; }
"kderc"
{ path = "kde3"; trail = "/*"; }
"kde4rc"
{ path = "xdg"; trail = "/kdeglobals"; }
{ path = "xdg"; trail = "/Trolltech.conf"; }
];
"abstractions/kerberosclient" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/kerberosclient"
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "krb5.keytab"; mode="rk"; }
"krb5.conf"
"krb5.conf.d"
{ path = "krb5.conf.d"; trail = "/*"; }
# config files found via strings on libs
"krb.conf"
"krb.realms"
"srvtab"
];
"abstractions/ldapclient" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ldapclient"
'' + lib.concatMapStringsSep "\n" etcRule [
"ldap.conf"
"ldap.secret"
{ path = "openldap"; trail = "/*"; }
{ path = "openldap"; trail = "/cacerts/*"; }
{ path = "sasl2"; trail = "/*"; }
];
"abstractions/likewise" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/likewise"
'';
"abstractions/mdns" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/mdns"
${etcRule "nss_mdns.conf"}
'';
"abstractions/nameservice" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nameservice"
# Many programs wish to perform nameservice-like operations, such as
# looking up users by name or id, groups by name or id, hosts by name
# or IP, etc. These operations may be performed through files, dns,
# NIS, NIS+, LDAP, hesiod, wins, etc. Allow them all here.
mr ${getLib pkgs.nss}/lib/libnss_*.so*,
mr ${getLib pkgs.nss}/lib64/libnss_*.so*,
'' + lib.concatMapStringsSep "\n" etcRule [
"group"
"host.conf"
"hosts"
"nsswitch.conf"
"gai.conf"
"passwd"
"protocols"
# libtirpc (used for NIS/YP login) needs this
"netconfig"
"resolv.conf"
{ path = "samba"; trail = "/lmhosts"; }
"services"
"default/nss"
# libnl-3-200 via libnss-gw-name
{ path = "libnl"; trail = "/classid"; }
{ path = "libnl-3"; trail = "/classid"; }
];
"abstractions/nis" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nis"
'';
"abstractions/nvidia" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/nvidia"
${etcRule "vdpau_wrapper.cfg"}
'';
"abstractions/opencl-common" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/opencl-common"
${etcRule { path = "OpenCL"; trail = "/**"; }}
'';
"abstractions/opencl-mesa" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/opencl-mesa"
${etcRule "default/drirc"}
'';
"abstractions/openssl" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/openssl"
${etcRule { path = "ssl"; trail = "/openssl.cnf"; }}
'';
"abstractions/p11-kit" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/p11-kit"
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "pkcs11"; trail = "/"; }
{ path = "pkcs11"; trail = "/pkcs11.conf"; }
{ path = "pkcs11"; trail = "/modules/"; }
{ path = "pkcs11"; trail = "/modules/*"; }
];
"abstractions/perl" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/perl"
${etcRule { path = "perl"; trail = "/**"; }}
'';
"abstractions/php" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/php"
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "php"; trail = "/**/"; }
{ path = "php5"; trail = "/**/"; }
{ path = "php7"; trail = "/**/"; }
{ path = "php"; trail = "/**.ini"; }
{ path = "php5"; trail = "/**.ini"; }
{ path = "php7"; trail = "/**.ini"; }
];
"abstractions/postfix-common" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/postfix-common"
'' + lib.concatMapStringsSep "\n" etcRule [
"mailname"
{ path = "postfix"; trail = "/*.cf"; }
"postfix/main.cf"
"postfix/master.cf"
];
"abstractions/python" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/python"
'';
"abstractions/qt5" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/qt5"
'' + lib.concatMapStringsSep "\n" etcRule [
{ path = "xdg"; trail = "/QtProject/qtlogging.ini"; }
{ path = "xdg/QtProject"; trail = "/qtlogging.ini"; }
"xdg/QtProject/qtlogging.ini"
];
"abstractions/samba" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/samba"
${etcRule { path = "samba"; trail = "/*"; }}
'';
"abstractions/ssl_certs" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/ssl_certs"
# For the NixOS module: security.acme
r /var/lib/acme/*/cert.pem,
r /var/lib/acme/*/chain.pem,
r /var/lib/acme/*/fullchain.pem,
'' + lib.concatMapStringsSep "\n" etcRule [
"ssl/certs/ca-certificates.crt"
"ssl/certs/ca-bundle.crt"
"pki/tls/certs/ca-bundle.crt"
{ path = "ssl/trust"; trail = "/"; }
{ path = "ssl/trust"; trail = "/*"; }
{ path = "ssl/trust/anchors"; trail = "/"; }
{ path = "ssl/trust/anchors"; trail = "/**"; }
{ path = "pki/trust"; trail = "/"; }
{ path = "pki/trust"; trail = "/*"; }
{ path = "pki/trust/anchors"; trail = "/"; }
{ path = "pki/trust/anchors"; trail = "/**"; }
];
"abstractions/ssl_keys" = ''
# security.acme NixOS module
r /var/lib/acme/*/full.pem,
r /var/lib/acme/*/key.pem,
'';
"abstractions/vulkan" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/vulkan"
${etcRule { path = "vulkan/icd.d"; trail = "/"; }}
${etcRule { path = "vulkan/icd.d"; trail = "/*.json"; }}
'';
"abstractions/winbind" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/winbind"
${etcRule { path = "samba"; trail = "/smb.conf"; }}
${etcRule { path = "samba"; trail = "/dhcp.conf"; }}
'';
"abstractions/X" = ''
include "${pkgs.apparmor-profiles}/etc/apparmor.d/abstractions/X"
${etcRule { path = "X11/cursors"; trail = "/"; }}
${etcRule { path = "X11/cursors"; trail = "/**"; }}
'';
};
}

View file

@ -0,0 +1,11 @@
{ config, lib, pkgs, ... }:
let apparmor = config.security.apparmor; in
{
config.security.apparmor.packages = [ pkgs.apparmor-profiles ];
config.security.apparmor.policies."bin.ping".profile = lib.mkIf apparmor.policies."bin.ping".enable ''
include "${pkgs.iputils.apparmor}/bin.ping"
include "${pkgs.inetutils.apparmor}/bin.ping"
# Note that including those two profiles in the same profile
# would not work if the second one were to re-include <tunables/global>.
'';
}

View file

@ -10,15 +10,10 @@ let
blacklist = cfg.caCertificateBlacklist;
};
caCertificates = pkgs.runCommand "ca-certificates.crt"
{ files =
cfg.certificateFiles ++
[ (builtins.toFile "extra.crt" (concatStringsSep "\n" cfg.certificates)) ];
preferLocalBuild = true;
}
''
cat $files > $out
'';
caCertificates = pkgs.runCommand "ca-certificates.crt" {
files = cfg.certificateFiles ++ [ (builtins.toFile "extra.crt" (concatStringsSep "\n" cfg.certificates)) ];
preferLocalBuild = true;
} "awk 1 $files > $out"; # awk ensures a newline between each pair of consecutive files
in

View file

@ -7,6 +7,10 @@ with lib;
maintainers = [ maintainers.joachifm ];
};
imports = [
(lib.mkRenamedOptionModule [ "security" "virtualization" "flushL1DataCache" ] [ "security" "virtualisation" "flushL1DataCache" ])
];
options = {
security.allowUserNamespaces = mkOption {
type = types.bool;

View file

@ -433,7 +433,7 @@ let
("auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
" kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
${optionalString cfg.enableGnomeKeyring
"auth optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so"}
"auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so"}
${optionalString cfg.gnupg.enable
"auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"
+ optionalString cfg.gnupg.storeOnly " store-only"
@ -471,7 +471,7 @@ let
${optionalString config.krb5.enable
"password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"}
${optionalString cfg.enableGnomeKeyring
"password optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok"}
"password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok"}
# Session management.
${optionalString cfg.setEnvironment ''
@ -512,7 +512,7 @@ let
("session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so" +
" kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5")}
${optionalString (cfg.enableGnomeKeyring)
"session optional ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start"}
"session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start"}
${optionalString cfg.gnupg.enable
"session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"
+ optionalString cfg.gnupg.noAutostart " no-autostart"
@ -895,6 +895,81 @@ in
runuser-l = { rootOK = true; unixAuth = false; };
};
security.apparmor.includes."abstractions/pam" = let
isEnabled = test: fold or false (map test (attrValues config.security.pam.services));
in
lib.concatMapStringsSep "\n"
(name: "r ${config.environment.etc."pam.d/${name}".source},")
(attrNames config.security.pam.services) +
''
mr ${getLib pkgs.pam}/lib/security/pam_filter/*,
mr ${getLib pkgs.pam}/lib/security/pam_*.so,
r ${getLib pkgs.pam}/lib/security/,
'' +
optionalString use_ldap ''
mr ${pam_ldap}/lib/security/pam_ldap.so,
'' +
optionalString config.services.sssd.enable ''
mr ${pkgs.sssd}/lib/security/pam_sss.so,
'' +
optionalString config.krb5.enable ''
mr ${pam_krb5}/lib/security/pam_krb5.so,
mr ${pam_ccreds}/lib/security/pam_ccreds.so,
'' +
optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) ''
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_admin.so,
'' +
optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication)) ''
mr ${pkgs.google-compute-engine-oslogin}/lib/pam_oslogin_login.so,
'' +
optionalString (config.security.pam.enableSSHAgentAuth
&& isEnabled (cfg: cfg.sshAgentAuth)) ''
mr ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so,
'' +
optionalString (isEnabled (cfg: cfg.fprintAuth)) ''
mr ${pkgs.fprintd}/lib/security/pam_fprintd.so,
'' +
optionalString (isEnabled (cfg: cfg.u2fAuth)) ''
mr ${pkgs.pam_u2f}/lib/security/pam_u2f.so,
'' +
optionalString (isEnabled (cfg: cfg.usbAuth)) ''
mr ${pkgs.pam_usb}/lib/security/pam_usb.so,
'' +
optionalString (isEnabled (cfg: cfg.oathAuth)) ''
"mr ${pkgs.oathToolkit}/lib/security/pam_oath.so,
'' +
optionalString (isEnabled (cfg: cfg.yubicoAuth)) ''
mr ${pkgs.yubico-pam}/lib/security/pam_yubico.so,
'' +
optionalString (isEnabled (cfg: cfg.duoSecurity.enable)) ''
mr ${pkgs.duo-unix}/lib/security/pam_duo.so,
'' +
optionalString (isEnabled (cfg: cfg.otpwAuth)) ''
mr ${pkgs.otpw}/lib/security/pam_otpw.so,
'' +
optionalString config.security.pam.enableEcryptfs ''
mr ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so,
'' +
optionalString (isEnabled (cfg: cfg.pamMount)) ''
mr ${pkgs.pam_mount}/lib/security/pam_mount.so,
'' +
optionalString (isEnabled (cfg: cfg.enableGnomeKeyring)) ''
mr ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so,
'' +
optionalString (isEnabled (cfg: cfg.startSession)) ''
mr ${pkgs.systemd}/lib/security/pam_systemd.so,
'' +
optionalString (isEnabled (cfg: cfg.enableAppArmor)
&& config.security.apparmor.enable) ''
mr ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so,
'' +
optionalString (isEnabled (cfg: cfg.enableKwallet)) ''
mr ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so,
'' +
optionalString config.virtualisation.lxc.lxcfs.enable ''
mr ${pkgs.lxc}/lib/security/pam_cgfs.so
'';
};
}

View file

@ -61,6 +61,17 @@ in
'';
};
security.sudo.execWheelOnly = mkOption {
type = types.bool;
default = false;
description = ''
Only allow members of the <code>wheel</code> group to execute sudo by
setting the executable's permissions accordingly.
This prevents users that are not members of <code>wheel</code> from
exploiting vulnerabilities in sudo such as CVE-2021-3156.
'';
};
security.sudo.configFile = mkOption {
type = types.lines;
# Note: if syntax errors are detected in this file, the NixOS
@ -216,9 +227,20 @@ in
${cfg.extraConfig}
'';
security.wrappers = {
sudo.source = "${cfg.package.out}/bin/sudo";
sudoedit.source = "${cfg.package.out}/bin/sudoedit";
security.wrappers = let
owner = "root";
group = if cfg.execWheelOnly then "wheel" else "root";
setuid = true;
permissions = if cfg.execWheelOnly then "u+rx,g+x" else "u+rx,g+x,o+x";
in {
sudo = {
source = "${cfg.package.out}/bin/sudo";
inherit owner group setuid permissions;
};
sudoedit = {
source = "${cfg.package.out}/bin/sudoedit";
inherit owner group setuid permissions;
};
};
environment.systemPackages = [ sudo ];

View file

@ -171,6 +171,14 @@ in
export PATH="${wrapperDir}:$PATH"
'';
security.apparmor.includes."nixos/security.wrappers" = ''
include "${pkgs.apparmorRulesFromClosure { name="security.wrappers"; } [
securityWrapper
pkgs.stdenv.cc.cc
pkgs.stdenv.cc.libc
]}"
'';
###### setcap activation script
system.activationScripts.wrappers =
lib.stringAfter [ "specialfs" "users" ]

View file

@ -290,5 +290,5 @@ in {
];
meta.maintainers = [ maintainers.gnidorah ];
meta.maintainers = [ ];
}

View file

@ -233,14 +233,15 @@ in {
{
User = "${cfg.user}";
ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon /run/mpd/mpd.conf";
ExecStartPre = pkgs.writeShellScript "mpd-start-pre" ''
ExecStartPre = pkgs.writeShellScript "mpd-start-pre" (''
set -euo pipefail
install -m 600 ${mpdConf} /run/mpd/mpd.conf
${optionalString (cfg.credentials != [])
"${pkgs.replace}/bin/replace-literal -fe ${
concatStringsSep " -a " (imap0 (i: c: "\"{{password-${toString i}}}\" \"$(cat ${c.passwordFile})\"") cfg.credentials)
} /run/mpd/mpd.conf"}
'';
'' + optionalString (cfg.credentials != [])
(concatStringsSep "\n"
(imap0
(i: c: ''${pkgs.replace-secret}/bin/replace-secret '{{password-${toString i}}}' '${c.passwordFile}' /run/mpd/mpd.conf'')
cfg.credentials))
);
RuntimeDirectory = "mpd";
Type = "notify";
LimitRTPRIO = 50;

View file

@ -59,7 +59,7 @@ let
replaceSecret = secretFile: placeholder: targetFile:
optionalString (secretFile != null) ''
${pkgs.replace}/bin/replace-literal -ef ${placeholder} "$(cat ${secretFile})" ${targetFile}'';
${pkgs.replace-secret}/bin/replace-secret '${placeholder}' '${secretFile}' '${targetFile}' '';
preStart = pkgs.writeShellScript "mpdscribble-pre-start" ''
cp -f "${cfgTemplate}" "${cfgFile}"

View file

@ -1,16 +1,17 @@
{ config, lib, pkgs, ...}:
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.duplicity;
stateDirectory = "/var/lib/duplicity";
localTarget = if hasPrefix "file://" cfg.targetUrl
localTarget =
if hasPrefix "file://" cfg.targetUrl
then removePrefix "file://" cfg.targetUrl else null;
in {
in
{
options.services.duplicity = {
enable = mkEnableOption "backups with duplicity";
@ -24,7 +25,7 @@ in {
include = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
example = [ "/home" ];
description = ''
List of paths to include into the backups. See the FILE SELECTION
@ -35,7 +36,7 @@ in {
exclude = mkOption {
type = types.listOf types.str;
default = [];
default = [ ];
description = ''
List of paths to exclude from backups. See the FILE SELECTION section in
<citerefentry><refentrytitle>duplicity</refentrytitle>
@ -82,14 +83,60 @@ in {
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--full-if-older-than" "1M" ];
default = [ ];
example = [ "--backend-retry-delay" "100" ];
description = ''
Extra command-line flags passed to duplicity. See
<citerefentry><refentrytitle>duplicity</refentrytitle>
<manvolnum>1</manvolnum></citerefentry>.
'';
};
fullIfOlderThan = mkOption {
type = types.str;
default = "never";
example = "1M";
description = ''
If <literal>"never"</literal> (the default) always do incremental
backups (the first backup will be a full backup, of course). If
<literal>"always"</literal> always do full backups. Otherwise, this
must be a string representing a duration. Full backups will be made
when the latest full backup is older than this duration. If this is not
the case, an incremental backup is performed.
'';
};
cleanup = {
maxAge = mkOption {
type = types.nullOr types.str;
default = null;
example = "6M";
description = ''
If non-null, delete all backup sets older than the given time. Old backup sets
will not be deleted if backup sets newer than time depend on them.
'';
};
maxFull = mkOption {
type = types.nullOr types.int;
default = null;
example = 2;
description = ''
If non-null, delete all backups sets that are older than the count:th last full
backup (in other words, keep the last count full backups and
associated incremental sets).
'';
};
maxIncr = mkOption {
type = types.nullOr types.int;
default = null;
example = 1;
description = ''
If non-null, delete incremental sets of all backups sets that are
older than the count:th last full backup (in other words, keep only
old full backups and not their increments).
'';
};
};
};
config = mkIf cfg.enable {
@ -99,18 +146,26 @@ in {
environment.HOME = stateDirectory;
serviceConfig = {
ExecStart = ''
${pkgs.duplicity}/bin/duplicity ${escapeShellArgs (
[
cfg.root
cfg.targetUrl
"--archive-dir" stateDirectory
]
script =
let
target = escapeShellArg cfg.targetUrl;
extra = escapeShellArgs ([ "--archive-dir" stateDirectory ] ++ cfg.extraFlags);
dup = "${pkgs.duplicity}/bin/duplicity";
in
''
set -x
${dup} cleanup ${target} --force ${extra}
${lib.optionalString (cfg.cleanup.maxAge != null) "${dup} remove-older-than ${lib.escapeShellArg cfg.cleanup.maxAge} ${target} --force ${extra}"}
${lib.optionalString (cfg.cleanup.maxFull != null) "${dup} remove-all-but-n-full ${toString cfg.cleanup.maxFull} ${target} --force ${extra}"}
${lib.optionalString (cfg.cleanup.maxIncr != null) "${dup} remove-all-incr-but-n-full ${toString cfg.cleanup.maxIncr} ${target} --force ${extra}"}
exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArgs (
[ cfg.root cfg.targetUrl ]
++ concatMap (p: [ "--include" p ]) cfg.include
++ concatMap (p: [ "--exclude" p ]) cfg.exclude
++ cfg.extraFlags)}
++ (lib.optionals (cfg.fullIfOlderThan != "never" && cfg.fullIfOlderThan != "always") [ "--full-if-older-than" cfg.fullIfOlderThan ])
)} ${extra}
'';
serviceConfig = {
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = "read-only";
@ -130,7 +185,7 @@ in {
assertions = singleton {
# Duplicity will fail if the last file selection option is an include. It
# is not always possible to detect but this simple case can be caught.
assertion = cfg.include != [] -> cfg.exclude != [] || cfg.extraFlags != [];
assertion = cfg.include != [ ] -> cfg.exclude != [ ] || cfg.extraFlags != [ ];
message = ''
Duplicity will fail if you only specify included paths ("Because the
default is to include all files, the expression is redundant. Exiting

View file

@ -48,7 +48,7 @@ in {
startAt = mkOption {
default = "*-*-* 01:15:00";
type = types.str;
type = with types; either (listOf str) str;
description = ''
This option defines (see <literal>systemd.time</literal> for format) when the
databases should be dumped.

View file

@ -62,7 +62,7 @@ in
'';
};
enable = mkEnableOption "Whether to enable Kubernetes addon manager.";
enable = mkEnableOption "Kubernetes addon manager.";
};
###### implementation

View file

@ -7,12 +7,12 @@ let
defaultContainerdConfigFile = pkgs.writeText "containerd.toml" ''
version = 2
root = "/var/lib/containerd/daemon"
state = "/var/run/containerd/daemon"
root = "/var/lib/containerd"
state = "/run/containerd"
oom_score = 0
[grpc]
address = "/var/run/containerd/containerd.sock"
address = "/run/containerd/containerd.sock"
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "pause:latest"

View file

@ -134,7 +134,7 @@ in
containerRuntimeEndpoint = mkOption {
description = "Endpoint at which to find the container runtime api interface/socket";
type = str;
default = "unix:///var/run/containerd/containerd.sock";
default = "unix:///run/containerd/containerd.sock";
};
enable = mkEnableOption "Kubernetes kubelet.";

View file

@ -49,6 +49,15 @@ in
'';
};
daemonNiceLevel = mkOption {
type = types.ints.between (-20) 19;
default = 0;
description = ''
Daemon process priority for FAHClient.
0 is the default Unix process priority, 19 is the lowest.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
@ -70,6 +79,7 @@ in
serviceConfig = {
DynamicUser = true;
StateDirectory = "foldingathome";
Nice = cfg.daemonNiceLevel;
WorkingDirectory = "%S/foldingathome";
};
};

View file

@ -283,5 +283,5 @@ in {
'')
];
meta.maintainers = with lib.maintainers; [ nand0p mic92 lopsided98 ];
meta.maintainers = with lib.maintainers; [ mic92 lopsided98 ];
}

View file

@ -191,6 +191,6 @@ in {
};
};
meta.maintainers = with lib.maintainers; [ nand0p ];
meta.maintainers = with lib.maintainers; [ ];
}

View file

@ -37,15 +37,22 @@ let
description = ''
Number of tasks to perform simultaneously.
A task is a single derivation build or an evaluation.
A task is a single derivation build, an evaluation or an effect run.
At minimum, you need 2 concurrent tasks for <literal>x86_64-linux</literal>
in your cluster, to allow for import from derivation.
<literal>concurrentTasks</literal> can be around the CPU core count or lower if memory is
the bottleneck.
The optimal value depends on the resource consumption characteristics of your workload,
including memory usage and in-task parallelism. This is typically determined empirically.
When scaling, it is generally better to have a double-size machine than two machines,
because each split of resources causes inefficiencies; particularly with regards
to build latency because of extra downloads.
'';
type = types.int;
default = 4;
type = types.either types.ints.positive (types.enum [ "auto" ]);
default = "auto";
};
workDirectory = mkOption {
description = ''
@ -186,7 +193,18 @@ in
# even shortly after the previous lookup. This *also* applies to the daemon.
narinfo-cache-negative-ttl = 0
'';
services.hercules-ci-agent.tomlFile =
format.generate "hercules-ci-agent.toml" cfg.settings;
services.hercules-ci-agent = {
tomlFile =
format.generate "hercules-ci-agent.toml" cfg.settings;
settings.labels = {
agent.source =
if options.services.hercules-ci-agent.package.highestPrio == (lib.modules.mkOptionDefault { }).priority
then "nixpkgs"
else lib.mkOptionDefault "override";
pkgs.version = pkgs.lib.version;
lib.version = lib.version;
};
};
};
}

View file

@ -68,7 +68,23 @@ in
# Trusted user allows simplified configuration and better performance
# when operating in a cluster.
nix.trustedUsers = [ config.systemd.services.hercules-ci-agent.serviceConfig.User ];
services.hercules-ci-agent.settings.nixUserIsTrusted = true;
services.hercules-ci-agent = {
settings = {
nixUserIsTrusted = true;
labels =
let
mkIfNotNull = x: mkIf (x != null) x;
in
{
nixos.configurationRevision = mkIfNotNull config.system.configurationRevision;
nixos.release = config.system.nixos.release;
nixos.label = mkIfNotNull config.system.nixos.label;
nixos.codeName = config.system.nixos.codeName;
nixos.tags = config.system.nixos.tags;
nixos.systemName = mkIfNotNull config.system.name;
};
};
};
users.users.hercules-ci-agent = {
home = cfg.settings.baseDirectory;

View file

@ -42,6 +42,7 @@ with lib;
User = "clickhouse";
Group = "clickhouse";
ConfigurationDirectory = "clickhouse-server";
AmbientCapabilities = "CAP_SYS_NICE";
StateDirectory = "clickhouse";
LogsDirectory = "clickhouse";
ExecStart = "${pkgs.clickhouse}/bin/clickhouse-server --config-file=${pkgs.clickhouse}/etc/clickhouse-server/config.xml";

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