Project import generated by Copybara.

GitOrigin-RevId: bc4b9eef3ce3d5a90d8693e8367c9cbfc9fc1e13
This commit is contained in:
Default email 2022-04-03 20:54:34 +02:00
parent fa8f317d6f
commit d56f44df06
986 changed files with 36538 additions and 27903 deletions

View file

@ -1,14 +1,15 @@
name: Basic evaluation checks
on:
pull_request:
branches:
- master
- release-**
push:
branches:
- master
- release-**
workflow_dispatch
# pull_request:
# branches:
# - master
# - release-**
# push:
# branches:
# - master
# - release-**
jobs:
tests:
runs-on: ubuntu-latest

View file

@ -78,21 +78,46 @@ If both the dependency and depending packages aren't compilers or other machine-
Finally, if the depending package is a compiler or other machine-code-producing tool, it might need dependencies that run at "emit time". This is for compilers that (regrettably) insist on being built together with their source languages' standard libraries. Assuming build != host != target, a run-time dependency of the standard library cannot be run at the compiler's build time or run time, but only at the run time of code emitted by the compiler.
Putting this all together, that means we have dependencies in the form "host → target", in at most the following six combinations:
Putting this all together, that means that we have dependency types of the form "X→ E", which means that the dependency executes on X and emits code for E; each of X and E can be `build`, `host`, or `target`, and E can be `*` to indicate that the dependency is not a compiler-like package.
Dependency types describe the relationships that a package has with each of its transitive dependencies. You could think of attaching one or more dependency types to each of the formal parameters at the top of a package's `.nix` file, as well as to all of *their* formal parameters, and so on. Triples like `(foo, bar, baz)`, on the other hand, are a property of an instantiated derivation -- you could would attach a triple `(mips-linux, mips-linux, sparc-solaris)` to a `.drv` file in `/nix/store`.
Only nine dependency types matter in practice:
#### Possible dependency types {#possible-dependency-types}
| Dependencys host platform | Dependencys target platform |
|----------------------------|------------------------------|
| build | build |
| build | host |
| build | target |
| host | host |
| host | target |
| target | target |
| Dependency type | Dependencys host platform | Dependencys target platform |
|-----------------|----------------------------|------------------------------|
| build → * | build | (none) |
| build → build | build | build |
| build → host | build | host |
| build → target | build | target |
| host → * | host | (none) |
| host → host | host | host |
| host → target | host | target |
| target → * | target | (none) |
| target → target | target | target |
Let's use `g++` as an example to make this table clearer. `g++` is a C++ compiler written in C. Suppose we are building `g++` with a `(build, host, target)` platform triple of `(foo, bar, baz)`. This means we are using a `foo`-machine to build a copy of `g++` which will run on a `bar`-machine and emit binaries for the `baz`-machine.
Some examples will make this table clearer. Suppose there's some package that is being built with a `(build, host, target)` platform triple of `(foo, bar, baz)`. If it has a build-time library dependency, that would be a "host → build" dependency with a triple of `(foo, foo, *)` (the target platform is irrelevant). If it needs a compiler to be built, that would be a "build → host" dependency with a triple of `(foo, foo, *)` (the target platform is irrelevant). That compiler, would be built with another compiler, also "build → host" dependency, with a triple of `(foo, foo, foo)`.
* `g++` links against the host platform's `glibc` C library, which is a "host→ *" dependency with a triple of `(bar, bar, *)`. Since it is a library, not a compiler, it has no "target".
* Since `g++` is written in C, the `gcc` compiler used to compile it is a "build→ host" dependency of `g++` with a triple of `(foo, foo, bar)`. This compiler runs on the build platform and emits code for the host platform.
* `gcc` links against the build platform's `glibc` C library, which is a "build→ *" dependency with a triple of `(foo, foo, *)`. Since it is a library, not a compiler, it has no "target".
* This `gcc` is itself compiled by an *earlier* copy of `gcc`. This earlier copy of `gcc` is a "build→ build" dependency of `g++` with a triple of `(foo, foo, foo)`. This "early `gcc`" runs on the build platform and emits code for the build platform.
* `g++` is bundled with `libgcc`, which includes a collection of target-machine routines for exception handling and
software floating point emulation. `libgcc` would be a "target→ *" dependency with triple `(foo, baz, *)`, because it consists of machine code which gets linked against the output of the compiler that we are building. It is a library, not a compiler, so it has no target of its own.
* `libgcc` is written in C and compiled with `gcc`. The `gcc` that compiles it will be a "build→ target" dependency with triple `(foo, foo, baz)`. It gets compiled *and run* at `g++`-build-time (on platform `foo`), but must emit code for the `baz`-platform.
* `g++` allows inline assembler code, so it depends on access to a copy of the `gas` assembler. This would be a "host→ target" dependency with triple `(foo, bar, baz)`.
* `g++` (and `gcc`) include a library `libgccjit.so`, which wrap the compiler in a library to create a just-in-time compiler. In nixpkgs, this library is in the `libgccjit` package; if C++ required that programs have access to a JIT, `g++` would need to add a "target→ target" dependency for `libgccjit` with triple `(foo, baz, baz)`. This would ensure that the compiler ships with a copy of `libgccjit` which both executes on and generates code for the `baz`-platform.
* If `g++` itself linked against `libgccjit.so` (for example, to allow compile-time-evaluated C++ expressions), then the `libgccjit` package used to provide this functionality would be a "host→ host" dependency of `g++`: it is code which runs on the `host` and emits code for execution on the `host`.
### Cross packaging cookbook {#ssec-cross-cookbook}

View file

@ -125,7 +125,7 @@ The extension of `PATH` with dependencies, alluded to above, proceeds according
A dependency is said to be **propagated** when some of its other-transitive (non-immediate) downstream dependencies also need it as an immediate dependency.
[^footnote-stdenv-propagated-dependencies]
It is important to note that dependencies are not necessarily propagated as the same sort of dependency that they were before, but rather as the corresponding sort so that the platform rules still line up. To determine the exact rules for dependency propagation, we start by assigning to each dependency a couple of ternary numbers (`-1` for `build`, `0` for `host`, and `1` for `target`), representing how respectively its host and target platforms are "offset" from the depending derivations platforms. The following table summarize the different combinations that can be obtained:
It is important to note that dependencies are not necessarily propagated as the same sort of dependency that they were before, but rather as the corresponding sort so that the platform rules still line up. To determine the exact rules for dependency propagation, we start by assigning to each dependency a couple of ternary numbers (`-1` for `build`, `0` for `host`, and `1` for `target`) representing its [dependency type](#possible-dependency-types), which captures how its host and target platforms are each "offset" from the depending derivations host and target platforms. The following table summarize the different combinations that can be obtained:
| `host → target` | attribute name | offset |
| ------------------- | ------------------- | -------- |

View file

@ -117,8 +117,55 @@ rec {
callPackageWith = autoArgs: fn: args:
let
f = if lib.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
in makeOverridable f (auto // args);
fargs = lib.functionArgs f;
# All arguments that will be passed to the function
# This includes automatic ones and ones passed explicitly
allArgs = builtins.intersectAttrs fargs autoArgs // args;
# A list of argument names that the function requires, but
# wouldn't be passed to it
missingArgs = lib.attrNames
# Filter out arguments that have a default value
(lib.filterAttrs (name: value: ! value)
# Filter out arguments that would be passed
(removeAttrs fargs (lib.attrNames allArgs)));
# Get a list of suggested argument names for a given missing one
getSuggestions = arg: lib.pipe (autoArgs // args) [
lib.attrNames
# Only use ones that are at most 2 edits away. While mork would work,
# levenshteinAtMost is only fast for 2 or less.
(lib.filter (lib.strings.levenshteinAtMost 2 arg))
# Put strings with shorter distance first
(lib.sort (x: y: lib.strings.levenshtein x arg < lib.strings.levenshtein y arg))
# Only take the first couple results
(lib.take 3)
# Quote all entries
(map (x: "\"" + x + "\""))
];
prettySuggestions = suggestions:
if suggestions == [] then ""
else if lib.length suggestions == 1 then ", did you mean ${lib.elemAt suggestions 0}?"
else ", did you mean ${lib.concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?";
errorForArg = arg:
let
loc = builtins.unsafeGetAttrPos arg fargs;
# loc' can be removed once lib/minver.nix is >2.3.4, since that includes
# https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
loc' = if loc != null then loc.file + ":" + toString loc.line
else if ! lib.isFunction fn then
toString fn + lib.optionalString (lib.sources.pathIsDirectory fn) "/default.nix"
else "<unknown location>";
in "Function called without required argument \"${arg}\" at "
+ "${loc'}${prettySuggestions (getSuggestions arg)}";
# Only show the error for the first missing argument
error = errorForArg (lib.head missingArgs);
in if missingArgs == [] then makeOverridable f allArgs else throw error;
/* Like callPackage, but for a function that returns an attribute

View file

@ -120,7 +120,7 @@ rec {
Example:
mkPackageOption pkgs "GHC" {
default = [ "ghc" ];
example = "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])";
example = "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])";
}
=> { _type = "option"; default = «derivation /nix/store/jxx55cxsjrf8kyh3fp2ya17q99w7541r-ghc-8.10.7.drv»; defaultText = { ... }; description = "The GHC package to use."; example = { ... }; type = { ... }; }
*/

View file

@ -774,4 +774,131 @@ rec {
(x: if stringLength x == 0 then "unknown" else x)
];
/* Computes the Levenshtein distance between two strings.
Complexity O(n*m) where n and m are the lengths of the strings.
Algorithm adjusted from https://stackoverflow.com/a/9750974/6605742
Type: levenshtein :: string -> string -> int
Example:
levenshtein "foo" "foo"
=> 0
levenshtein "book" "hook"
=> 1
levenshtein "hello" "Heyo"
=> 3
*/
levenshtein = a: b: let
# Two dimensional array with dimensions (stringLength a + 1, stringLength b + 1)
arr = lib.genList (i:
lib.genList (j:
dist i j
) (stringLength b + 1)
) (stringLength a + 1);
d = x: y: lib.elemAt (lib.elemAt arr x) y;
dist = i: j:
let c = if substring (i - 1) 1 a == substring (j - 1) 1 b
then 0 else 1;
in
if j == 0 then i
else if i == 0 then j
else lib.min
( lib.min (d (i - 1) j + 1) (d i (j - 1) + 1))
( d (i - 1) (j - 1) + c );
in d (stringLength a) (stringLength b);
/* Returns the length of the prefix common to both strings.
*/
commonPrefixLength = a: b:
let
m = lib.min (stringLength a) (stringLength b);
go = i: if i >= m then m else if substring i 1 a == substring i 1 b then go (i + 1) else i;
in go 0;
/* Returns the length of the suffix common to both strings.
*/
commonSuffixLength = a: b:
let
m = lib.min (stringLength a) (stringLength b);
go = i: if i >= m then m else if substring (stringLength a - i - 1) 1 a == substring (stringLength b - i - 1) 1 b then go (i + 1) else i;
in go 0;
/* Returns whether the levenshtein distance between two strings is at most some value
Complexity is O(min(n,m)) for k <= 2 and O(n*m) otherwise
Type: levenshteinAtMost :: int -> string -> string -> bool
Example:
levenshteinAtMost 0 "foo" "foo"
=> true
levenshteinAtMost 1 "foo" "boa"
=> false
levenshteinAtMost 2 "foo" "boa"
=> true
levenshteinAtMost 2 "This is a sentence" "this is a sentense."
=> false
levenshteinAtMost 3 "This is a sentence" "this is a sentense."
=> true
*/
levenshteinAtMost = let
infixDifferAtMost1 = x: y: stringLength x <= 1 && stringLength y <= 1;
# This function takes two strings stripped by their common pre and suffix,
# and returns whether they differ by at most two by Levenshtein distance.
# Because of this stripping, if they do indeed differ by at most two edits,
# we know that those edits were (if at all) done at the start or the end,
# while the middle has to have stayed the same. This fact is used in the
# implementation.
infixDifferAtMost2 = x: y:
let
xlen = stringLength x;
ylen = stringLength y;
# This function is only called with |x| >= |y| and |x| - |y| <= 2, so
# diff is one of 0, 1 or 2
diff = xlen - ylen;
# Infix of x and y, stripped by the left and right most character
xinfix = substring 1 (xlen - 2) x;
yinfix = substring 1 (ylen - 2) y;
# x and y but a character deleted at the left or right
xdelr = substring 0 (xlen - 1) x;
xdell = substring 1 (xlen - 1) x;
ydelr = substring 0 (ylen - 1) y;
ydell = substring 1 (ylen - 1) y;
in
# A length difference of 2 can only be gotten with 2 delete edits,
# which have to have happened at the start and end of x
# Example: "abcdef" -> "bcde"
if diff == 2 then xinfix == y
# A length difference of 1 can only be gotten with a deletion on the
# right and a replacement on the left or vice versa.
# Example: "abcdef" -> "bcdez" or "zbcde"
else if diff == 1 then xinfix == ydelr || xinfix == ydell
# No length difference can either happen through replacements on both
# sides, or a deletion on the left and an insertion on the right or
# vice versa
# Example: "abcdef" -> "zbcdez" or "bcdefz" or "zabcde"
else xinfix == yinfix || xdelr == ydell || xdell == ydelr;
in k: if k <= 0 then a: b: a == b else
let f = a: b:
let
alen = stringLength a;
blen = stringLength b;
prelen = commonPrefixLength a b;
suflen = commonSuffixLength a b;
presuflen = prelen + suflen;
ainfix = substring prelen (alen - presuflen) a;
binfix = substring prelen (blen - presuflen) b;
in
# Make a be the bigger string
if alen < blen then f b a
# If a has over k more characters than b, even with k deletes on a, b can't be reached
else if alen - blen > k then false
else if k == 1 then infixDifferAtMost1 ainfix binfix
else if k == 2 then infixDifferAtMost2 ainfix binfix
else levenshtein ainfix binfix <= k;
in f;
}

View file

@ -913,4 +913,156 @@ runTests {
};
};
## Levenshtein distance functions and co.
testCommonPrefixLengthEmpty = {
expr = strings.commonPrefixLength "" "hello";
expected = 0;
};
testCommonPrefixLengthSame = {
expr = strings.commonPrefixLength "hello" "hello";
expected = 5;
};
testCommonPrefixLengthDiffering = {
expr = strings.commonPrefixLength "hello" "hey";
expected = 2;
};
testCommonSuffixLengthEmpty = {
expr = strings.commonSuffixLength "" "hello";
expected = 0;
};
testCommonSuffixLengthSame = {
expr = strings.commonSuffixLength "hello" "hello";
expected = 5;
};
testCommonSuffixLengthDiffering = {
expr = strings.commonSuffixLength "test" "rest";
expected = 3;
};
testLevenshteinEmpty = {
expr = strings.levenshtein "" "";
expected = 0;
};
testLevenshteinOnlyAdd = {
expr = strings.levenshtein "" "hello there";
expected = 11;
};
testLevenshteinOnlyRemove = {
expr = strings.levenshtein "hello there" "";
expected = 11;
};
testLevenshteinOnlyTransform = {
expr = strings.levenshtein "abcdef" "ghijkl";
expected = 6;
};
testLevenshteinMixed = {
expr = strings.levenshtein "kitchen" "sitting";
expected = 5;
};
testLevenshteinAtMostZeroFalse = {
expr = strings.levenshteinAtMost 0 "foo" "boo";
expected = false;
};
testLevenshteinAtMostZeroTrue = {
expr = strings.levenshteinAtMost 0 "foo" "foo";
expected = true;
};
testLevenshteinAtMostOneFalse = {
expr = strings.levenshteinAtMost 1 "car" "ct";
expected = false;
};
testLevenshteinAtMostOneTrue = {
expr = strings.levenshteinAtMost 1 "car" "cr";
expected = true;
};
# We test levenshteinAtMost 2 particularly well because it uses a complicated
# implementation
testLevenshteinAtMostTwoIsEmpty = {
expr = strings.levenshteinAtMost 2 "" "";
expected = true;
};
testLevenshteinAtMostTwoIsZero = {
expr = strings.levenshteinAtMost 2 "abcdef" "abcdef";
expected = true;
};
testLevenshteinAtMostTwoIsOne = {
expr = strings.levenshteinAtMost 2 "abcdef" "abddef";
expected = true;
};
testLevenshteinAtMostTwoDiff0False = {
expr = strings.levenshteinAtMost 2 "abcdef" "aczyef";
expected = false;
};
testLevenshteinAtMostTwoDiff0Outer = {
expr = strings.levenshteinAtMost 2 "abcdef" "zbcdez";
expected = true;
};
testLevenshteinAtMostTwoDiff0DelLeft = {
expr = strings.levenshteinAtMost 2 "abcdef" "bcdefz";
expected = true;
};
testLevenshteinAtMostTwoDiff0DelRight = {
expr = strings.levenshteinAtMost 2 "abcdef" "zabcde";
expected = true;
};
testLevenshteinAtMostTwoDiff1False = {
expr = strings.levenshteinAtMost 2 "abcdef" "bddez";
expected = false;
};
testLevenshteinAtMostTwoDiff1DelLeft = {
expr = strings.levenshteinAtMost 2 "abcdef" "bcdez";
expected = true;
};
testLevenshteinAtMostTwoDiff1DelRight = {
expr = strings.levenshteinAtMost 2 "abcdef" "zbcde";
expected = true;
};
testLevenshteinAtMostTwoDiff2False = {
expr = strings.levenshteinAtMost 2 "hello" "hxo";
expected = false;
};
testLevenshteinAtMostTwoDiff2True = {
expr = strings.levenshteinAtMost 2 "hello" "heo";
expected = true;
};
testLevenshteinAtMostTwoDiff3 = {
expr = strings.levenshteinAtMost 2 "hello" "ho";
expected = false;
};
testLevenshteinAtMostThreeFalse = {
expr = strings.levenshteinAtMost 3 "hello" "Holla!";
expected = false;
};
testLevenshteinAtMostThreeTrue = {
expr = strings.levenshteinAtMost 3 "hello" "Holla";
expected = true;
};
}

View file

@ -8549,7 +8549,7 @@
};
msfjarvis = {
github = "msfjarvis";
githubId = 3348378;
githubId = 13348378;
name = "Harsh Shandilya";
email = "nixos@msfjarvis.dev";
keys = [{
@ -14251,4 +14251,16 @@
github = "nigelgbanks";
githubId = 487373;
};
zanculmarktum = {
name = "Azure Zanculmarktum";
email = "zanculmarktum@gmail.com";
github = "zanculmarktum";
githubId = 16958511;
};
kuwii = {
name = "kuwii";
email = "kuwii.someone@gmail.com";
github = "kuwii";
githubId = 10705175;
};
}

View file

@ -0,0 +1,98 @@
#!/usr/bin/env nix-shell
#!nix-shell -i perl -p perl -p perlPackages.JSON perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.TermReadKey
# This script generates a list of teams to ping for the Feature Freeze announcement on Discourse.
# It's intended to be used by Release Managers before creating such posts.
#
# The script interactively reads a GitHub username and a corresponding GitHub Personal Access token.
# This is required to access the GitHub Teams API so the token needs at least the read:org privilege.
## no critic (InputOutput::RequireCheckedSyscalls, InputOutput::ProhibitBacktickOperators)
use strict;
use warnings;
use Carp;
use Cwd 'abs_path';
use File::Basename;
use JSON qw(decode_json);
use LWP::UserAgent;
use Term::ReadKey qw(ReadLine ReadMode);
sub github_team_members {
my ($team_name, $username, $token) = @_;
my @ret;
my $req = HTTP::Request->new('GET', "https://api.github.com/orgs/NixOS/teams/$team_name/members", [ 'Accept' => 'application/vnd.github.v3+json' ]);
$req->authorization_basic($username, $token);
my $response = LWP::UserAgent->new->request($req);
if ($response->is_success) {
my $content = decode_json($response->decoded_content);
foreach (@{$content}) {
push @ret, $_->{'login'};
}
} else {
print {*STDERR} "!! Requesting members of GitHub Team '$team_name' failed: $response->status_line";
}
return \@ret;
}
# Read GitHub credentials
print {*STDERR} 'GitHub username: ';
my $github_user = ReadLine(0);
ReadMode('noecho');
print {*STDERR} 'GitHub personal access token (no echo): ';
my $github_token = ReadLine(0);
ReadMode('restore');
print {*STDERR} "\n";
chomp $github_user;
chomp $github_token;
# Read nix output
my $nix_version = `nix --version`;
my $out;
my $lib_path = abs_path(dirname(__FILE__)) . '../../../lib';
if ($nix_version =~ m/2[.]3[.]/msx) {
$out = `nix eval --json '(import $lib_path).teams'` || croak 'nix eval failed';
} else {
$out = `nix --extra-experimental-features nix-command eval --json --impure --expr '(import $lib_path).teams'` || croak('nix eval failed');
}
my $data = decode_json($out);
# Process teams
print {*STDERR} "\n";
while (my ($team_nix_key, $team_config) = each %{$data}) {
# Ignore teams that don't want to be or can't be pinged
if (not defined $team_config->{enableFeatureFreezePing} or not $team_config->{enableFeatureFreezePing}) {
next;
}
if (not defined $team_config->{shortName}) {
print {*STDERR} "!! The team with the nix key '$team_nix_key' has no shortName set - ignoring";
next;
}
# Team name
print {*STDERR} "$team_config->{shortName}:";
# GitHub Teams
my @github_members;
if (defined $team_config->{githubTeams}) {
foreach (@{$team_config->{githubTeams}}) {
print {*STDERR} " \@NixOS/${_}";
push @github_members, @{github_team_members($_, $github_user, $github_token)};
}
}
my %github_members = map { $_ => 1 } @github_members;
# Members
if (defined $team_config->{members}) {
foreach (@{$team_config->{members}}) {
my %user = %{$_};
my $github_handle = $user{'github'};
# Ensure we don't ping team members twice (as team member and directly)
if (defined $github_members{$github_handle}) {
next;
}
print {*STDERR} " \@$github_handle";
}
}
print {*STDERR} "\n";
}

View file

@ -0,0 +1,22 @@
let
nixpkgs = import ../../..;
inherit (nixpkgs {}) haskellPackages lib;
maintainedPkgs = lib.filterAttrs (
_: v: builtins.length (v.meta.maintainers or []) > 0
) haskellPackages;
brokenPkgs = lib.filterAttrs (_: v: v.meta.broken) maintainedPkgs;
transitiveBrokenPkgs = lib.filterAttrs
(_: v: !(builtins.tryEval (v.outPath or null)).success && !v.meta.broken)
maintainedPkgs;
infoList = pkgs: lib.concatStringsSep "\n" (lib.mapAttrsToList (name: drv: "${name} ${(builtins.elemAt drv.meta.maintainers 0).github}") pkgs);
in {
report = ''
BROKEN:
${infoList brokenPkgs}
TRANSITIVE BROKEN:
${infoList transitiveBrokenPkgs}
'';
transitiveErrors =
builtins.attrValues transitiveBrokenPkgs;
}

View file

@ -1,26 +1,38 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p nix curl jq nix-prefetch-github git gnused gnugrep -I nixpkgs=.
# shellcheck shell=bash
set -eu -o pipefail
tmpfile=$(mktemp "update-stackage.XXXXXXX")
# shellcheck disable=SC2064
# Stackage solver to use, LTS or Nightly
# (should be capitalized like the display name)
SOLVER=LTS
TMP_TEMPLATE=update-stackage.XXXXXXX
readonly SOLVER
readonly TMP_TEMPLATE
toLower() {
printf "%s" "$1" | tr '[:upper:]' '[:lower:]'
}
tmpfile=$(mktemp "$TMP_TEMPLATE")
tmpfile_new=$(mktemp "$TMP_TEMPLATE")
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.
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/lts/cabal.config" >"$tmpfile"
old_version=$(grep "# Stackage" $stackage_config | sed -E 's/.*([0-9]{2}\.[0-9]+)/\1/')
version=$(sed -rn "s/^--.*http:..(www.)?stackage.org.snapshot.lts-//p" "$tmpfile")
curl -L -s "https://stackage.org/$(toLower "$SOLVER")/cabal.config" >"$tmpfile"
old_version=$(grep '^# Stackage' $stackage_config | sed -e 's/.\+ \([A-Za-z]\+ [0-9.-]\+\)$/\1/g')
version="$SOLVER $(sed -rn "s/^--.*http:..(www.)?stackage.org.snapshot.$(toLower "$SOLVER")-//p" "$tmpfile")"
if [[ "$old_version" == "$version" ]]; then
echo "No new stackage version"
exit 0 # Nothing to do
fi
echo "Updating Stackage LTS from $old_version to $version."
echo "Updating Stackage from $old_version to $version."
# Create a simple yaml version of the file.
sed -r \
@ -30,10 +42,10 @@ sed -r \
-e 's|,$||' \
-e '/installed$/d' \
-e '/^$/d' \
< "${tmpfile}" | sort --ignore-case >"${tmpfile}.new"
< "${tmpfile}" | sort --ignore-case >"${tmpfile_new}"
cat > $stackage_config << EOF
# Stackage LTS $version
# Stackage $version
# This file is auto-generated by
# maintainers/scripts/haskell/update-stackage.sh
default-package-overrides:
@ -45,12 +57,13 @@ sed -r \
-e '/ distribution-nixpkgs /d' \
-e '/ jailbreak-cabal /d' \
-e '/ language-nix /d' \
< "${tmpfile}.new" >> $stackage_config
-e '/ cabal-install /d' \
< "${tmpfile_new}" >> $stackage_config
if [[ "${1:-}" == "--do-commit" ]]; then
git add $stackage_config
git commit -F - << EOF
haskellPackages: stackage-lts $old_version -> $version
haskellPackages: stackage $old_version -> $version
This commit has been generated by maintainers/scripts/haskell/update-stackage.sh
EOF

View file

@ -3,12 +3,19 @@
# Required
members = [ maintainer1 maintainer2 ];
scope = "Maintain foo packages.";
shortName = "foo";
# Optional
enableFeatureFreezePing = true;
githubTeams = [ "my-subsystem" ];
};
where
- `members` is the list of maintainers belonging to the group,
- `scope` describes the scope of the group.
- `shortName` short human-readable name
- `enableFeatureFreezePing` will ping this team during the Feature Freeze announcements on releases
- `githubTeams` will ping specified GitHub teams as well
More fields may be added in the future.
@ -27,6 +34,7 @@ with lib.maintainers; {
m1cr0man
];
scope = "Maintain ACME-related packages and modules.";
shortName = "ACME";
};
bazel = {
@ -41,6 +49,8 @@ with lib.maintainers; {
ylecornec
];
scope = "Bazel build tool & related tools https://bazel.build/";
shortName = "Bazel";
enableFeatureFreezePing = true;
};
beam = {
@ -53,7 +63,32 @@ with lib.maintainers; {
minijackson
yurrriq
];
githubTeams = [
"beam"
];
scope = "Maintain BEAM-related packages and modules.";
shortName = "BEAM";
enableFeatureFreezePing = true;
};
blockchains = {
members = [
mmahut
RaghavSood
];
scope = "Maintain Blockchain packages and modules.";
shortName = "Blockchains";
enableFeatureFreezePing = true;
};
c = {
members = [
matthewbauer
mic92
];
scope = "Maintain C libraries and tooling.";
shortName = "C";
enableFeatureFreezePing = true;
};
cinnamon = {
@ -61,6 +96,8 @@ with lib.maintainers; {
mkg20001
];
scope = "Maintain Cinnamon desktop environment and applications made by the LinuxMint team.";
shortName = "Cinnamon";
enableFeatureFreezePing = true;
};
chia = {
@ -68,6 +105,40 @@ with lib.maintainers; {
lourkeur
];
scope = "Maintain the Chia blockchain and its dependencies";
shortName = "Chia Blockchain";
};
coq = {
members = [
cohencyril
Zimmi48
# gares has no entry in the maintainers list
siraben
vbgl
];
scope = "Maintain the Coq theorem prover and related packages.";
shortName = "Coq";
enableFeatureFreezePing = true;
};
darwin = {
members = [
toonn
];
githubTeams = [
"darwin-maintainers"
];
scope = "Maintain Darwin compatibility of packages and Darwin-only packages.";
shortName = "Darwin";
enableFeatureFreezePing = true;
};
cosmopolitan = {
members = [
lourkeur
tomberek
];
scope = "Maintain the Cosmopolitan LibC and related programs.";
};
deshaw = {
@ -76,6 +147,7 @@ with lib.maintainers; {
limeytexan
];
scope = "Group registration for D. E. Shaw employees who collectively maintain packages.";
shortName = "Shaw employees";
};
determinatesystems = {
@ -85,11 +157,63 @@ with lib.maintainers; {
grahamc
];
scope = "Group registration for packages maintained by Determinate Systems.";
shortName = "Determinate Systems employees";
};
dhall = {
members = [
Gabriel439
ehmry
];
scope = "Maintain Dhall and related packages.";
shortName = "Dhall";
enableFeatureFreezePing = true;
};
docker = {
members = [
roberth
utdemir
];
scope = "Maintain Docker and related tools.";
shortName = "DockerTools";
enableFeatureFreezePing = true;
};
docs = {
members = [
ryantm
];
scope = "Maintain nixpkgs/NixOS documentation and tools for building it.";
shortName = "Docs";
enableFeatureFreezePing = true;
};
emacs = {
members = [
adisbladis
];
scope = "Maintain the Emacs editor and packages.";
shortName = "Emacs";
enableFeatureFreezePing = true;
};
# Dummy group for the "everyone else" section
feature-freeze-everyone-else = {
members = [ ];
githubTeams = [
"nixpkgs-committers"
"release-engineers"
];
scope = "Dummy team for the #everyone else' section during feture freezes, not to be used as package maintainers!";
shortName = "Everyone else";
enableFeatureFreezePing = true;
};
freedesktop = {
members = [ jtojnar ];
scope = "Maintain Freedesktop.org packages for graphical desktop.";
shortName = "freedesktop.org packaging";
};
gcc = {
@ -99,6 +223,7 @@ with lib.maintainers; {
ericson2314
];
scope = "Maintain GCC (GNU Compiler Collection) compilers";
shortName = "GCC";
};
golang = {
@ -113,6 +238,8 @@ with lib.maintainers; {
zowoq
];
scope = "Maintain Golang compilers.";
shortName = "Go";
enableFeatureFreezePing = true;
};
gnome = {
@ -123,7 +250,12 @@ with lib.maintainers; {
dasj19
maxeaubrey
];
githubTeams = [
"gnome"
];
scope = "Maintain GNOME desktop environment and platform.";
shortName = "GNOME";
enableFeatureFreezePing = true;
};
haskell = {
@ -133,7 +265,12 @@ with lib.maintainers; {
maralorn
sternenseemann
];
githubTeams = [
"haskell"
];
scope = "Maintain Haskell packages and infrastructure.";
shortName = "Haskell";
enableFeatureFreezePing = true;
};
home-assistant = {
@ -144,6 +281,7 @@ with lib.maintainers; {
mic92
];
scope = "Maintain the Home Assistant ecosystem";
shortName = "Home Assistant";
};
iog = {
@ -155,6 +293,7 @@ with lib.maintainers; {
nrdxp
];
scope = "Input-Output Global employees, which maintain critical software";
shortName = "Input-Output Global employees";
};
jitsi = {
@ -165,6 +304,7 @@ with lib.maintainers; {
yuka
];
scope = "Maintain Jitsi.";
shortName = "Jitsi";
};
kubernetes = {
@ -176,6 +316,7 @@ with lib.maintainers; {
zowoq
];
scope = "Maintain the Kubernetes package and module";
shortName = "Kubernetes";
};
kodi = {
@ -188,6 +329,7 @@ with lib.maintainers; {
sephalon
];
scope = "Maintain Kodi and related packages.";
shortName = "Kodi";
};
linux-kernel = {
@ -198,6 +340,17 @@ with lib.maintainers; {
qyliss
];
scope = "Maintain the Linux kernel.";
shortName = "Linux Kernel";
};
marketing = {
members = [
garbas
tomberek
];
scope = "Marketing of Nix/NixOS/nixpkgs.";
shortName = "Marketing";
enableFeatureFreezePing = true;
};
mate = {
@ -206,6 +359,7 @@ with lib.maintainers; {
romildo
];
scope = "Maintain Mate desktop environment and related packages.";
shortName = "MATE";
};
matrix = {
@ -219,6 +373,40 @@ with lib.maintainers; {
sumnerevans
];
scope = "Maintain the ecosystem around Matrix, a decentralized messenger.";
shortName = "Matrix";
};
mobile = {
members = [
samueldr
];
scope = "Maintain Mobile NixOS.";
shortName = "Mobile";
enableFeatureFreezePing = true;
};
nix = {
members = [
Profpatsch
eelco
grahamc
pierron
];
scope = "Maintain the Nix package manager.";
shortName = "Nix/nix-cli ecosystem";
enableFeatureFreezePing = true;
};
nixos-modules = {
members = [
ericson2314
infinisil
qyliss
roberth
];
scope = "Maintain nixpkgs module system internals.";
shortName = "NixOS Modules / internals";
enableFeatureFreezePing = true;
};
openstack = {
@ -227,6 +415,7 @@ with lib.maintainers; {
SuperSandro2000
];
scope = "Maintain the ecosystem around OpenStack";
shortName = "OpenStack";
};
pantheon = {
@ -234,7 +423,21 @@ with lib.maintainers; {
davidak
bobby285271
];
githubTeams = [
"pantheon"
];
scope = "Maintain Pantheon desktop environment and platform.";
shortName = "Pantheon";
enableFeatureFreezePing = true;
};
perl = {
members = [
sgo
];
scope = "Maintain the Perl interpreter and Perl packages.";
shortName = "Perl";
enableFeatureFreezePing = true;
};
php = {
@ -246,7 +449,12 @@ with lib.maintainers; {
ma27
talyz
];
githubTeams = [
"php"
];
scope = "Maintain PHP related packages and extensions.";
shortName = "PHP";
enableFeatureFreezePing = true;
};
podman = {
@ -256,7 +464,54 @@ with lib.maintainers; {
vdemeester
zowoq
];
githubTeams = [
"podman"
];
scope = "Maintain Podman and CRI-O related packages and modules.";
shortName = "Podman";
enableFeatureFreezePing = true;
};
postgres = {
members = [
thoughtpolice
];
scope = "Maintain the PostgreSQL package and plugins along with the NixOS module.";
shortName = "PostgreSQL";
enableFeatureFreezePing = true;
};
python = {
members = [
fridh
hexa
jonringer
];
scope = "Maintain the Python interpreter and related packages.";
shortName = "Python";
enableFeatureFreezePing = true;
};
qt-kde = {
members = [
ttuegel
];
githubTeams = [
"qt-kde"
];
scope = "Maintain the KDE desktop environment and Qt.";
shortName = "Qt / KDE";
enableFeatureFreezePing = true;
};
r = {
members = [
bcdarwin
jbedo
];
scope = "Maintain the R programming language and related packages.";
shortName = "R";
enableFeatureFreezePing = true;
};
redcodelabs = {
@ -266,6 +521,38 @@ with lib.maintainers; {
wintrmvte
];
scope = "Maintain Red Code Labs related packages and modules.";
shortName = "Red Code Labs";
};
release = {
members = [ ];
githubTeams = [
"nixos-release-managers"
];
scope = "Manage the current nixpkgs/NixOS release.";
shortName = "Release";
enableFeatureFreezePing = true;
};
ruby = {
members = [
marsam
];
scope = "Maintain the Ruby interpreter and related packages.";
shortName = "Ruby";
enableFeatureFreezePing = true;
};
rust = {
members = [
andir
lnl7
mic92
zowoq
];
scope = "Maintain the Rust compiler toolchain and nixpkgs integration.";
shortName = "Rust";
enableFeatureFreezePing = true;
};
sage = {
@ -276,6 +563,7 @@ with lib.maintainers; {
collares
];
scope = "Maintain SageMath and the dependencies that are likely to break it.";
shortName = "SageMath";
};
sphinx = {
@ -283,6 +571,7 @@ with lib.maintainers; {
SuperSandro2000
];
scope = "Maintain Sphinx related packages.";
shortName = "Sphinx";
};
serokell = {
@ -292,6 +581,26 @@ with lib.maintainers; {
mkaito
];
scope = "Group registration for Serokell employees who collectively maintain packages.";
shortName = "Serokell employees";
};
systemd = {
members = [ ];
githubTeams = [
"systemd"
];
scope = "Maintain systemd for NixOS.";
shortName = "systemd";
enableFeatureFreezePing = true;
};
tests = {
members = [
tfc
];
scope = "Maintain the NixOS VM test runner.";
shortName = "NixOS tests";
enableFeatureFreezePing = true;
};
tts = {
@ -300,6 +609,18 @@ with lib.maintainers; {
mic92
];
scope = "coqui-ai TTS (formerly Mozilla TTS) and leaf packages";
shortName = "coqui-ai TTS";
};
vim = {
members = [
jonringer
softinio
teto
];
scope = "Maintain the vim and neovim text editors and related packages.";
shortName = "Vim/Neovim";
enableFeatureFreezePing = true;
};
xfce = {
@ -307,5 +628,6 @@ with lib.maintainers; {
romildo
];
scope = "Maintain Xfce desktop environment and related packages.";
shortName = "Xfce";
};
}

View file

@ -120,14 +120,14 @@ lib.mkOption {
```nix
lib.mkPackageOption pkgs "GHC" {
default = [ "ghc" ];
example = "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])";
example = "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])";
}
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.ghc;
defaultText = lib.literalExpression "pkgs.ghc";
example = lib.literalExpression "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])";
example = lib.literalExpression "pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])";
description = "The GHC package to use.";
}
```

View file

@ -32,6 +32,20 @@ type of this option should represent the format. The most common formats
have a predefined type and string generator already declared under
`pkgs.formats`:
`pkgs.formats.javaProperties` { *`comment`* ? `"Generated with Nix"` }
: A function taking an attribute set with values
`comment`
: A string to put at the start of the
file in a comment. It can have multiple
lines.
It returns the `type`: `attrsOf str` and a function
`generate` to build a Java `.properties` file, taking
care of the correct escaping, etc.
`pkgs.formats.json` { }
: A function taking an empty attribute set (for future extensibility)

View file

@ -5,15 +5,9 @@ A NixOS test is a Nix expression that has the following structure:
```nix
import ./make-test-python.nix {
# Either the configuration of a single machine:
machine =
{ config, pkgs, ... }:
{ configuration…
};
# Or a set of machines:
# One or more machines:
nodes =
{ machine1 =
{ machine =
{ config, pkgs, ... }: { … };
machine2 =
{ config, pkgs, ... }: { … };
@ -29,17 +23,16 @@ import ./make-test-python.nix {
The attribute `testScript` is a bit of Python code that executes the
test (described below). During the test, it will start one or more
virtual machines, the configuration of which is described by the
attribute `machine` (if you need only one machine in your test) or by
the attribute `nodes` (if you need multiple machines). For instance,
[`login.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix)
only needs a single machine to test whether users can log in
virtual machines, the configuration of which is described by
the attribute `nodes`.
An example of a single-node test is
[`login.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix).
It only needs a single machine to test whether users can log in
on the virtual console, whether device ownership is correctly maintained
when switching between consoles, and so on. On the other hand,
[`nfs/simple.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix),
which tests NFS client and server functionality in the
Linux kernel (including whether locks are maintained across server
crashes), requires three machines: a server and two clients.
when switching between consoles, and so on. An interesting multi-node test is
[`nfs/simple.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix).
It uses two client nodes to test correct locking across server crashes.
There are a few special NixOS configuration options for test VMs:
@ -67,8 +60,7 @@ The test script is a sequence of Python statements that perform various
actions, such as starting VMs, executing commands in the VMs, and so on.
Each virtual machine is represented as an object stored in the variable
`name` if this is also the identifier of the machine in the declarative
config. If you didn\'t specify multiple machines using the `nodes`
attribute, it is just `machine`. The following example starts the
config. If you specified a node `nodes.machine`, the following example starts the
machine, waits until it has finished booting, then executes a command
and checks that the output is more-or-less correct:
@ -79,7 +71,7 @@ if not "Linux" in machine.succeed("uname"):
raise Exception("Wrong OS")
```
The first line is actually unnecessary; machines are implicitly started
The first line is technically unnecessary; machines are implicitly started
when you first execute an action on them (such as `wait_for_unit` or
`succeed`). If you have multiple machines, you can speed up the test by
starting them in parallel:
@ -303,7 +295,7 @@ For faster dev cycles it\'s also possible to disable the code-linters
```nix
import ./make-test-python.nix {
skipLint = true;
machine =
nodes.machine =
{ config, pkgs, ... }:
{ configuration…
};

View file

@ -183,14 +183,14 @@ lib.mkOption {
<programlisting language="bash">
lib.mkPackageOption pkgs &quot;GHC&quot; {
default = [ &quot;ghc&quot; ];
example = &quot;pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
example = &quot;pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
}
# is like
lib.mkOption {
type = lib.types.package;
default = pkgs.ghc;
defaultText = lib.literalExpression &quot;pkgs.ghc&quot;;
example = lib.literalExpression &quot;pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
example = lib.literalExpression &quot;pkgs.haskell.package.ghc922.ghc.withPackages (hkgs: [ hkgs.primes ])&quot;;
description = &quot;The GHC package to use.&quot;;
}
</programlisting>

View file

@ -53,6 +53,38 @@
<literal>pkgs.formats</literal>:
</para>
<variablelist>
<varlistentry>
<term>
<literal>pkgs.formats.javaProperties</literal> {
<emphasis><literal>comment</literal></emphasis> ?
<literal>&quot;Generated with Nix&quot;</literal> }
</term>
<listitem>
<para>
A function taking an attribute set with values
</para>
<variablelist>
<varlistentry>
<term>
<literal>comment</literal>
</term>
<listitem>
<para>
A string to put at the start of the file in a comment.
It can have multiple lines.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
It returns the <literal>type</literal>:
<literal>attrsOf str</literal> and a function
<literal>generate</literal> to build a Java
<literal>.properties</literal> file, taking care of the
correct escaping, etc.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>pkgs.formats.json</literal> { }

View file

@ -6,15 +6,9 @@
<programlisting language="bash">
import ./make-test-python.nix {
# Either the configuration of a single machine:
machine =
{ config, pkgs, ... }:
{ configuration…
};
# Or a set of machines:
# One or more machines:
nodes =
{ machine1 =
{ machine =
{ config, pkgs, ... }: { … };
machine2 =
{ config, pkgs, ... }: { … };
@ -31,18 +25,18 @@ import ./make-test-python.nix {
The attribute <literal>testScript</literal> is a bit of Python code
that executes the test (described below). During the test, it will
start one or more virtual machines, the configuration of which is
described by the attribute <literal>machine</literal> (if you need
only one machine in your test) or by the attribute
<literal>nodes</literal> (if you need multiple machines). For
instance,
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix"><literal>login.nix</literal></link>
only needs a single machine to test whether users can log in on the
virtual console, whether device ownership is correctly maintained
when switching between consoles, and so on. On the other hand,
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix"><literal>nfs/simple.nix</literal></link>,
which tests NFS client and server functionality in the Linux kernel
(including whether locks are maintained across server crashes),
requires three machines: a server and two clients.
described by the attribute <literal>nodes</literal>.
</para>
<para>
An example of a single-node test is
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix"><literal>login.nix</literal></link>.
It only needs a single machine to test whether users can log in on
the virtual console, whether device ownership is correctly
maintained when switching between consoles, and so on. An
interesting multi-node test is
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix"><literal>nfs/simple.nix</literal></link>.
It uses two client nodes to test correct locking across server
crashes.
</para>
<para>
There are a few special NixOS configuration options for test VMs:
@ -94,9 +88,8 @@ import ./make-test-python.nix {
various actions, such as starting VMs, executing commands in the
VMs, and so on. Each virtual machine is represented as an object
stored in the variable <literal>name</literal> if this is also the
identifier of the machine in the declarative config. If you didn't
specify multiple machines using the <literal>nodes</literal>
attribute, it is just <literal>machine</literal>. The following
identifier of the machine in the declarative config. If you
specified a node <literal>nodes.machine</literal>, the following
example starts the machine, waits until it has finished booting,
then executes a command and checks that the output is more-or-less
correct:
@ -108,7 +101,7 @@ if not &quot;Linux&quot; in machine.succeed(&quot;uname&quot;):
raise Exception(&quot;Wrong OS&quot;)
</programlisting>
<para>
The first line is actually unnecessary; machines are implicitly
The first line is technically unnecessary; machines are implicitly
started when you first execute an action on them (such as
<literal>wait_for_unit</literal> or <literal>succeed</literal>). If
you have multiple machines, you can speed up the test by starting
@ -554,7 +547,7 @@ machine.wait_for_unit(&quot;xautolock.service&quot;, &quot;x-session-user&quot;)
<programlisting language="bash">
import ./make-test-python.nix {
skipLint = true;
machine =
nodes.machine =
{ config, pkgs, ... }:
{ configuration…
};

View file

@ -17,7 +17,7 @@ $ diskutil list
[..]
$ diskutil unmountDisk diskN
Unmount of all volumes on diskN was successful
$ sudo dd if=nix.iso of=/dev/rdiskN
$ sudo dd if=nix.iso of=/dev/rdiskN bs=1M
</programlisting>
<para>
Using the 'raw' <literal>rdiskN</literal> device instead of

View file

@ -411,6 +411,13 @@ OK
specify on which disk the GRUB boot loader is to be
installed. Without it, NixOS cannot boot.
</para>
<para>
If there are other operating systems running on the
machine before installing NixOS, the
<xref linkend="opt-boot.loader.grub.useOSProber" />
option can be set to <literal>true</literal> to
automatically add them to the grub menu.
</para>
</listitem>
</varlistentry>
<varlistentry>
@ -436,13 +443,6 @@ OK
</listitem>
</varlistentry>
</variablelist>
<para>
If there are other operating systems running on the machine
before installing NixOS, the
<xref linkend="opt-boot.loader.grub.useOSProber" /> option can
be set to <literal>true</literal> to automatically add them to
the grub menu.
</para>
<para>
If you need to configure networking for your machine the
configuration options are described in

View file

@ -88,6 +88,14 @@
and their users.
</para>
</listitem>
<listitem>
<para>
The default GHC version has been updated from 8.10.7 to 9.0.2.
<literal>pkgs.haskellPackages</literal> and
<literal>pkgs.ghc</literal> will now use this version by
default.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-22.05-new-services">
@ -221,6 +229,13 @@
<link xlink:href="options.html#opt-services.prometheus.exporters.pve">services.prometheus.exporters.pve</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/netbox-community/netbox">netbox</link>,
infrastructure resource modeling (IRM) tool. Available as
<link xlink:href="options.html#opt-services.netbox.enable">services.netbox</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://tetrd.app">tetrd</link>, share your
@ -1010,8 +1025,8 @@
<listitem>
<para>
<literal>pkgs.pgadmin</literal> now refers to
<literal>pkgs.pgadmin4</literal>. If you still need pgadmin3,
use <literal>pkgs.pgadmin3</literal>.
<literal>pkgs.pgadmin4</literal>. <literal>pgadmin3</literal>
has been removed.
</para>
</listitem>
<listitem>
@ -1253,6 +1268,13 @@
example.
</para>
</listitem>
<listitem>
<para>
<literal>pkgs.cosmopolitan</literal> no longer provides the
<literal>cosmoc</literal> command. It has been moved to
<literal>pkgs.cosmoc</literal>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-22.05-notable-changes">
@ -1379,6 +1401,35 @@
versions.
</para>
</listitem>
<listitem>
<para>
A new option group
<literal>systemd.network.wait-online</literal> was added, with
options to configure
<literal>systemd-networkd-wait-online.service</literal>:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>anyInterface</literal> allows specifying that the
network should be considered online when <emphasis>at
least one</emphasis> interface is online (useful on
laptops)
</para>
</listitem>
<listitem>
<para>
<literal>timeout</literal> defines how long to wait for
the network to come online
</para>
</listitem>
<listitem>
<para>
<literal>extraArgs</literal> for everything else
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
The <literal>influxdb2</literal> package was split into
@ -1633,9 +1684,20 @@
</listitem>
<listitem>
<para>
<literal>services.logrotate.enable</literal> now defaults to
true if any rotate path has been defined, and some paths have
been added by default.
<link linkend="opt-services.logrotate.enable">services.logrotate.enable</link>
now defaults to true if any rotate path has been defined, and
some paths have been added by default.
</para>
</listitem>
<listitem>
<para>
The logrotate module also has been updated to freeform syntax:
<link linkend="opt-services.logrotate.paths">services.logrotate.paths</link>
and
<link linkend="opt-services.logrotate.extraConfig">services.logrotate.extraConfig</link>
will work, but issue deprecation warnings and
<link linkend="opt-services.logrotate.settings">services.logrotate.settings</link>
should now be used instead.
</para>
</listitem>
<listitem>
@ -1718,6 +1780,13 @@
desktop environments as needed.
</para>
</listitem>
<listitem>
<para>
<literal>services.xserver.desktopManager.xfce</literal> now
includes Xfces screen locker,
<literal>xfce4-screensaver</literal>.
</para>
</listitem>
<listitem>
<para>
The <literal>hadoop</literal> package has added support for

View file

@ -18,7 +18,7 @@ $ diskutil list
[..]
$ diskutil unmountDisk diskN
Unmount of all volumes on diskN was successful
$ sudo dd if=nix.iso of=/dev/rdiskN
$ sudo dd if=nix.iso of=/dev/rdiskN bs=1M
```
Using the \'raw\' `rdiskN` device instead of `diskN` completes in

View file

@ -296,6 +296,11 @@ Use the following commands:
specify on which disk the GRUB boot loader is to be installed.
Without it, NixOS cannot boot.
: If there are other operating systems running on the machine before
installing NixOS, the [](#opt-boot.loader.grub.useOSProber)
option can be set to `true` to automatically add them to the grub
menu.
UEFI systems
: You *must* set the option [](#opt-boot.loader.systemd-boot.enable)
@ -307,11 +312,6 @@ Use the following commands:
[`boot.loader.systemd-boot`](#opt-boot.loader.systemd-boot.enable)
as well.
If there are other operating systems running on the machine before
installing NixOS, the [](#opt-boot.loader.grub.useOSProber)
option can be set to `true` to automatically add them to the grub
menu.
If you need to configure networking for your machine the
configuration options are described in [](#sec-networking). In
particular, while wifi is supported on the installation image, it is

View file

@ -3,10 +3,15 @@
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>NixOS Reference Pages</title>
<info>
<author><personname><firstname>Eelco</firstname><surname>Dolstra</surname></personname>
<author>
<personname><firstname>Eelco</firstname><surname>Dolstra</surname></personname>
<contrib>Author</contrib>
</author>
<copyright><year>2007-2020</year><holder>Eelco Dolstra</holder>
<author>
<personname><othername>The Nixpkgs/NixOS contributors</othername></personname>
<contrib>Author</contrib>
</author>
<copyright><year>2007-2022</year><holder>Eelco Dolstra and the Nixpkgs/NixOS contributors</holder>
</copyright>
</info>
<xi:include href="man-configuration.xml" />

View file

@ -29,6 +29,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- Module authors can use `mkRenamedOptionModuleWith` to automate the deprecation cycle without annoying out-of-tree module authors and their users.
- The default GHC version has been updated from 8.10.7 to 9.0.2. `pkgs.haskellPackages` and `pkgs.ghc` will now use this version by default.
## New Services {#sec-release-22.05-new-services}
- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable).
@ -65,6 +67,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](options.html#opt-services.prometheus.exporters.pve).
- [netbox](https://github.com/netbox-community/netbox), infrastructure resource modeling (IRM) tool. Available as [services.netbox](options.html#opt-services.netbox.enable).
- [tetrd](https://tetrd.app), share your internet connection from your device to your PC and vice versa through a USB cable. Available at [services.tetrd](#opt-services.tetrd.enable).
- [agate](https://github.com/mbrubeck/agate), a very simple server for the Gemini hypertext protocol. Available as [services.agate](options.html#opt-services.agate.enable).
@ -373,8 +377,7 @@ In addition to numerous new and upgraded packages, this release has the followin
you should change the package you refer to. If you don't need them update your
commands from `otelcontribcol` to `otelcorecol` and enjoy a 7x smaller binary.
- `pkgs.pgadmin` now refers to `pkgs.pgadmin4`.
If you still need pgadmin3, use `pkgs.pgadmin3`.
- `pkgs.pgadmin` now refers to `pkgs.pgadmin4`. `pgadmin3` has been removed.
- `pkgs.noto-fonts-cjk` is now deprecated in favor of `pkgs.noto-fonts-cjk-sans`
and `pkgs.noto-fonts-cjk-serif` because they each have different release
@ -444,6 +447,8 @@ In addition to numerous new and upgraded packages, this release has the followin
See the `vscode` package for a more detailed example.
- `pkgs.cosmopolitan` no longer provides the `cosmoc` command. It has been moved to `pkgs.cosmoc`.
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
## Other Notable Changes {#sec-release-22.05-notable-changes}
@ -493,6 +498,11 @@ In addition to numerous new and upgraded packages, this release has the followin
still under heavy development and behavior is not always flawless.
Furthermore, not all Electron apps use the latest Electron versions.
- A new option group `systemd.network.wait-online` was added, with options to configure `systemd-networkd-wait-online.service`:
- `anyInterface` allows specifying that the network should be considered online when *at least one* interface is online (useful on laptops)
- `timeout` defines how long to wait for the network to come online
- `extraArgs` for everything else
- The `influxdb2` package was split into `influxdb2-server` and
`influxdb2-cli`, matching the split that took place upstream. A
combined `influxdb2` package is still provided in this release for
@ -573,8 +583,11 @@ In addition to numerous new and upgraded packages, this release has the followin
- `services.mattermost.plugins` has been added to allow the declarative installation of Mattermost plugins.
Plugins are automatically repackaged using autoPatchelf.
- `services.logrotate.enable` now defaults to true if any rotate path has
- [services.logrotate.enable](#opt-services.logrotate.enable) now defaults to true if any rotate path has
been defined, and some paths have been added by default.
- The logrotate module also has been updated to freeform syntax: [services.logrotate.paths](#opt-services.logrotate.paths)
and [services.logrotate.extraConfig](#opt-services.logrotate.extraConfig) will work, but issue deprecation
warnings and [services.logrotate.settings](#opt-services.logrotate.settings) should now be used instead.
- The `zrepl` package has been updated from 0.4.0 to 0.5:
@ -602,6 +615,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- The polkit service, available at `security.polkit.enable`, is now disabled by default. It will automatically be enabled through services and desktop environments as needed.
- `services.xserver.desktopManager.xfce` now includes Xfce's screen locker, `xfce4-screensaver`.
- The `hadoop` package has added support for `aarch64-linux` and `aarch64-darwin` as of 3.3.1 ([#158613](https://github.com/NixOS/nixpkgs/pull/158613)).
- The `R` package now builds again on `aarch64-darwin` ([#158992](https://github.com/NixOS/nixpkgs/pull/158992)).

View file

@ -122,10 +122,15 @@ in rec {
(if isList value then value else [value]))
as));
generateUnits = generateUnits' true;
generateUnits' = allowCollisions: type: units: upstreamUnits: upstreamWants:
pkgs.runCommand "${type}-units"
generateUnits = { allowCollisions ? true, type, units, upstreamUnits, upstreamWants, packages ? cfg.packages, package ? cfg.package }:
let
typeDir = ({
system = "system";
initrd = "system";
user = "user";
nspawn = "nspawn";
}).${type};
in pkgs.runCommand "${type}-units"
{ preferLocalBuild = true;
allowSubstitutes = false;
} ''
@ -133,7 +138,7 @@ in rec {
# Copy the upstream systemd units we're interested in.
for i in ${toString upstreamUnits}; do
fn=${cfg.package}/example/systemd/${type}/$i
fn=${package}/example/systemd/${typeDir}/$i
if ! [ -e $fn ]; then echo "missing $fn"; false; fi
if [ -L $fn ]; then
target="$(readlink "$fn")"
@ -150,7 +155,7 @@ in rec {
# Copy .wants links, but only those that point to units that
# we're interested in.
for i in ${toString upstreamWants}; do
fn=${cfg.package}/example/systemd/${type}/$i
fn=${package}/example/systemd/${typeDir}/$i
if ! [ -e $fn ]; then echo "missing $fn"; false; fi
x=$out/$(basename $fn)
mkdir $x
@ -162,14 +167,14 @@ in rec {
done
# Symlink all units provided listed in systemd.packages.
packages="${toString cfg.packages}"
packages="${toString packages}"
# Filter duplicate directories
declare -A unique_packages
for k in $packages ; do unique_packages[$k]=1 ; done
for i in ''${!unique_packages[@]}; do
for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do
for fn in $i/etc/systemd/${typeDir}/* $i/lib/systemd/${typeDir}/*; do
if ! [[ "$fn" =~ .wants$ ]]; then
if [[ -d "$fn" ]]; then
targetDir="$out/$(basename "$fn")"
@ -270,9 +275,9 @@ in rec {
{ Conflicts = toString config.conflicts; }
// optionalAttrs (config.requisite != [])
{ Requisite = toString config.requisite; }
// optionalAttrs (config.restartTriggers != [])
// optionalAttrs (config ? restartTriggers && config.restartTriggers != [])
{ X-Restart-Triggers = toString config.restartTriggers; }
// optionalAttrs (config.reloadTriggers != [])
// optionalAttrs (config ? reloadTriggers && config.reloadTriggers != [])
{ X-Reload-Triggers = toString config.reloadTriggers; }
// optionalAttrs (config.description != "") {
Description = config.description; }
@ -288,45 +293,24 @@ in rec {
};
};
serviceConfig = { name, config, ... }: {
config = mkMerge
[ { # Default path for systemd services. Should be quite minimal.
path = mkAfter
[ pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gnused
systemd
];
environment.PATH = "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
}
(mkIf (config.preStart != "")
{ serviceConfig.ExecStartPre =
[ (makeJobScript "${name}-pre-start" config.preStart) ];
})
(mkIf (config.script != "")
{ serviceConfig.ExecStart =
makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
})
(mkIf (config.postStart != "")
{ serviceConfig.ExecStartPost =
[ (makeJobScript "${name}-post-start" config.postStart) ];
})
(mkIf (config.reload != "")
{ serviceConfig.ExecReload =
makeJobScript "${name}-reload" config.reload;
})
(mkIf (config.preStop != "")
{ serviceConfig.ExecStop =
makeJobScript "${name}-pre-stop" config.preStop;
})
(mkIf (config.postStop != "")
{ serviceConfig.ExecStopPost =
makeJobScript "${name}-post-stop" config.postStop;
})
];
serviceConfig = { config, ... }: {
config.environment.PATH = mkIf (config.path != []) "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
};
stage2ServiceConfig = {
imports = [ serviceConfig ];
# Default path for systemd services. Should be quite minimal.
config.path = mkAfter [
pkgs.coreutils
pkgs.findutils
pkgs.gnugrep
pkgs.gnused
systemd
];
};
stage1ServiceConfig = serviceConfig;
mountConfig = { config, ... }: {
config = {
mountConfig =
@ -374,12 +358,12 @@ in rec {
# systemd max line length is now 1MiB
# https://github.com/systemd/systemd/commit/e6dde451a51dc5aaa7f4d98d39b8fe735f73d2af
in if stringLength s >= 1048576 then throw "The value of the environment variable ${n} in systemd service ${name}.service is too long." else s) (attrNames env)}
${if def.reloadIfChanged then ''
${if def ? reloadIfChanged && def.reloadIfChanged then ''
X-ReloadIfChanged=true
'' else if !def.restartIfChanged then ''
'' else if (def ? restartIfChanged && !def.restartIfChanged) then ''
X-RestartIfChanged=false
'' else ""}
${optionalString (!def.stopIfChanged) "X-StopIfChanged=false"}
${optionalString (def ? stopIfChanged && !def.stopIfChanged) "X-StopIfChanged=false"}
${attrsToSection def.serviceConfig}
'';
};

View file

@ -0,0 +1,37 @@
{ lib, systemdUtils }:
with systemdUtils.lib;
with systemdUtils.unitOptions;
with lib;
rec {
units = with types;
attrsOf (submodule ({ name, config, ... }: {
options = concreteUnitOptions;
config = { unit = mkDefault (systemdUtils.lib.makeUnit name config); };
}));
services = with types; attrsOf (submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ]);
initrdServices = with types; attrsOf (submodule [ stage1ServiceOptions unitConfig stage1ServiceConfig ]);
targets = with types; attrsOf (submodule [ stage2CommonUnitOptions unitConfig ]);
initrdTargets = with types; attrsOf (submodule [ stage1CommonUnitOptions unitConfig ]);
sockets = with types; attrsOf (submodule [ stage2SocketOptions unitConfig ]);
initrdSockets = with types; attrsOf (submodule [ stage1SocketOptions unitConfig ]);
timers = with types; attrsOf (submodule [ stage2TimerOptions unitConfig ]);
initrdTimers = with types; attrsOf (submodule [ stage1TimerOptions unitConfig ]);
paths = with types; attrsOf (submodule [ stage2PathOptions unitConfig ]);
initrdPaths = with types; attrsOf (submodule [ stage1PathOptions unitConfig ]);
slices = with types; attrsOf (submodule [ stage2SliceOptions unitConfig ]);
initrdSlices = with types; attrsOf (submodule [ stage1SliceOptions unitConfig ]);
mounts = with types; listOf (submodule [ stage2MountOptions unitConfig mountConfig ]);
initrdMounts = with types; listOf (submodule [ stage1MountOptions unitConfig mountConfig ]);
automounts = with types; listOf (submodule [ stage2AutomountOptions unitConfig automountConfig ]);
initrdAutomounts = with types; attrsOf (submodule [ stage1AutomountOptions unitConfig automountConfig ]);
}

View file

@ -94,7 +94,7 @@ in rec {
};
commonUnitOptions = sharedOptions // {
commonUnitOptions = { options = (sharedOptions // {
description = mkOption {
default = "";
@ -191,27 +191,6 @@ in rec {
'';
};
restartTriggers = mkOption {
default = [];
type = types.listOf types.unspecified;
description = ''
An arbitrary list of items such as derivations. If any item
in the list changes between reconfigurations, the service will
be restarted.
'';
};
reloadTriggers = mkOption {
default = [];
type = types.listOf unitOption;
description = ''
An arbitrary list of items such as derivations. If any item
in the list changes between reconfigurations, the service will
be reloaded. If anything but a reload trigger changes in the
unit file, the unit will be restarted instead.
'';
};
onFailure = mkOption {
default = [];
type = types.listOf unitNameType;
@ -239,10 +218,39 @@ in rec {
'';
};
}); };
stage2CommonUnitOptions = {
imports = [
commonUnitOptions
];
options = {
restartTriggers = mkOption {
default = [];
type = types.listOf types.unspecified;
description = ''
An arbitrary list of items such as derivations. If any item
in the list changes between reconfigurations, the service will
be restarted.
'';
};
reloadTriggers = mkOption {
default = [];
type = types.listOf unitOption;
description = ''
An arbitrary list of items such as derivations. If any item
in the list changes between reconfigurations, the service will
be reloaded. If anything but a reload trigger changes in the
unit file, the unit will be restarted instead.
'';
};
};
};
stage1CommonUnitOptions = commonUnitOptions;
serviceOptions = commonUnitOptions // {
serviceOptions = { options = {
environment = mkOption {
default = {};
@ -276,121 +284,164 @@ in rec {
'';
};
script = mkOption {
type = types.lines;
default = "";
description = "Shell commands executed as the service's main process.";
}; };
stage2ServiceOptions = { name, config, ... }: {
imports = [
stage2CommonUnitOptions
serviceOptions
];
options = {
script = mkOption {
type = types.lines;
default = "";
description = "Shell commands executed as the service's main process.";
};
scriptArgs = mkOption {
type = types.str;
default = "";
description = "Arguments passed to the main process script.";
};
preStart = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed before the service's main process
is started.
'';
};
postStart = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed after the service's main process
is started.
'';
};
reload = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed when the service's main process
is reloaded.
'';
};
preStop = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed to stop the service.
'';
};
postStop = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed after the service's main process
has exited.
'';
};
restartIfChanged = mkOption {
type = types.bool;
default = true;
description = ''
Whether the service should be restarted during a NixOS
configuration switch if its definition has changed.
'';
};
reloadIfChanged = mkOption {
type = types.bool;
default = false;
description = ''
Whether the service should be reloaded during a NixOS
configuration switch if its definition has changed. If
enabled, the value of <option>restartIfChanged</option> is
ignored.
This option should not be used anymore in favor of
<option>reloadTriggers</option> which allows more granular
control of when a service is reloaded and when a service
is restarted.
'';
};
stopIfChanged = mkOption {
type = types.bool;
default = true;
description = ''
If set, a changed unit is restarted by calling
<command>systemctl stop</command> in the old configuration,
then <command>systemctl start</command> in the new one.
Otherwise, it is restarted in a single step using
<command>systemctl restart</command> in the new configuration.
The latter is less correct because it runs the
<literal>ExecStop</literal> commands from the new
configuration.
'';
};
startAt = mkOption {
type = with types; either str (listOf str);
default = [];
example = "Sun 14:00:00";
description = ''
Automatically start this unit at the given date/time, which
must be in the format described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>. This is equivalent
to adding a corresponding timer unit with
<option>OnCalendar</option> set to the value given here.
'';
apply = v: if isList v then v else [ v ];
};
};
scriptArgs = mkOption {
type = types.str;
default = "";
description = "Arguments passed to the main process script.";
};
preStart = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed before the service's main process
is started.
'';
};
postStart = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed after the service's main process
is started.
'';
};
reload = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed when the service's main process
is reloaded.
'';
};
preStop = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed to stop the service.
'';
};
postStop = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed after the service's main process
has exited.
'';
};
restartIfChanged = mkOption {
type = types.bool;
default = true;
description = ''
Whether the service should be restarted during a NixOS
configuration switch if its definition has changed.
'';
};
reloadIfChanged = mkOption {
type = types.bool;
default = false;
description = ''
Whether the service should be reloaded during a NixOS
configuration switch if its definition has changed. If
enabled, the value of <option>restartIfChanged</option> is
ignored.
This option should not be used anymore in favor of
<option>reloadTriggers</option> which allows more granular
control of when a service is reloaded and when a service
is restarted.
'';
};
stopIfChanged = mkOption {
type = types.bool;
default = true;
description = ''
If set, a changed unit is restarted by calling
<command>systemctl stop</command> in the old configuration,
then <command>systemctl start</command> in the new one.
Otherwise, it is restarted in a single step using
<command>systemctl restart</command> in the new configuration.
The latter is less correct because it runs the
<literal>ExecStop</literal> commands from the new
configuration.
'';
};
startAt = mkOption {
type = with types; either str (listOf str);
default = [];
example = "Sun 14:00:00";
description = ''
Automatically start this unit at the given date/time, which
must be in the format described in
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>. This is equivalent
to adding a corresponding timer unit with
<option>OnCalendar</option> set to the value given here.
'';
apply = v: if isList v then v else [ v ];
};
config = mkMerge
[ (mkIf (config.preStart != "")
{ serviceConfig.ExecStartPre =
[ (makeJobScript "${name}-pre-start" config.preStart) ];
})
(mkIf (config.script != "")
{ serviceConfig.ExecStart =
makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
})
(mkIf (config.postStart != "")
{ serviceConfig.ExecStartPost =
[ (makeJobScript "${name}-post-start" config.postStart) ];
})
(mkIf (config.reload != "")
{ serviceConfig.ExecReload =
makeJobScript "${name}-reload" config.reload;
})
(mkIf (config.preStop != "")
{ serviceConfig.ExecStop =
makeJobScript "${name}-pre-stop" config.preStop;
})
(mkIf (config.postStop != "")
{ serviceConfig.ExecStopPost =
makeJobScript "${name}-post-stop" config.postStop;
})
];
};
stage1ServiceOptions = {
imports = [
stage1CommonUnitOptions
serviceOptions
];
};
socketOptions = commonUnitOptions // {
socketOptions = { options = {
listenStreams = mkOption {
default = [];
@ -424,10 +475,24 @@ in rec {
'';
};
}; };
stage2SocketOptions = {
imports = [
stage2CommonUnitOptions
socketOptions
];
};
stage1SocketOptions = {
imports = [
stage1CommonUnitOptions
socketOptions
];
};
timerOptions = commonUnitOptions // {
timerOptions = { options = {
timerConfig = mkOption {
default = {};
@ -443,10 +508,24 @@ in rec {
'';
};
}; };
stage2TimerOptions = {
imports = [
stage2CommonUnitOptions
timerOptions
];
};
stage1TimerOptions = {
imports = [
stage1CommonUnitOptions
timerOptions
];
};
pathOptions = commonUnitOptions // {
pathOptions = { options = {
pathConfig = mkOption {
default = {};
@ -460,10 +539,24 @@ in rec {
'';
};
}; };
stage2PathOptions = {
imports = [
stage2CommonUnitOptions
pathOptions
];
};
stage1PathOptions = {
imports = [
stage1CommonUnitOptions
pathOptions
];
};
mountOptions = commonUnitOptions // {
mountOptions = { options = {
what = mkOption {
example = "/dev/sda1";
@ -505,9 +598,23 @@ in rec {
<manvolnum>5</manvolnum></citerefentry> for details.
'';
};
}; };
stage2MountOptions = {
imports = [
stage2CommonUnitOptions
mountOptions
];
};
automountOptions = commonUnitOptions // {
stage1MountOptions = {
imports = [
stage1CommonUnitOptions
mountOptions
];
};
automountOptions = { options = {
where = mkOption {
example = "/mnt";
@ -529,11 +636,23 @@ in rec {
<manvolnum>5</manvolnum></citerefentry> for details.
'';
};
}; };
stage2AutomountOptions = {
imports = [
stage2CommonUnitOptions
automountOptions
];
};
targetOptions = commonUnitOptions;
stage1AutomountOptions = {
imports = [
stage1CommonUnitOptions
automountOptions
];
};
sliceOptions = commonUnitOptions // {
sliceOptions = { options = {
sliceConfig = mkOption {
default = {};
@ -547,6 +666,20 @@ in rec {
'';
};
}; };
stage2SliceOptions = {
imports = [
stage2CommonUnitOptions
sliceOptions
];
};
stage1SliceOptions = {
imports = [
stage1CommonUnitOptions
sliceOptions
];
};
}

View file

@ -206,6 +206,7 @@ rec {
)];
};
in
lib.warnIf (t?machine) "In test `${name}': The `machine' attribute in NixOS tests (pkgs.nixosTest / make-test-pyton.nix / testing-python.nix / makeTest) is deprecated. Please use the equivalent `nodes.machine'."
build-vms.buildVirtualNetwork (
nodes // lib.optionalAttrs (machine != null) { inherit machine; }
);

View file

@ -197,5 +197,6 @@ rec {
systemdUtils = {
lib = import ./systemd-lib.nix { inherit lib config pkgs; };
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
types = import ./systemd-types.nix { inherit lib systemdUtils; };
};
}

View file

@ -15,6 +15,26 @@ let
mapAttrsToList (n: v: ''${n}=${escapeIfNeccessary (toString v)}'') attrs
);
osReleaseContents = {
NAME = "NixOS";
ID = "nixos";
VERSION = "${cfg.release} (${cfg.codeName})";
VERSION_CODENAME = toLower cfg.codeName;
VERSION_ID = cfg.release;
BUILD_ID = cfg.version;
PRETTY_NAME = "NixOS ${cfg.release} (${cfg.codeName})";
LOGO = "nix-snowflake";
HOME_URL = "https://nixos.org/";
DOCUMENTATION_URL = "https://nixos.org/learn.html";
SUPPORT_URL = "https://nixos.org/community.html";
BUG_REPORT_URL = "https://github.com/NixOS/nixpkgs/issues";
};
initrdReleaseContents = osReleaseContents // {
PRETTY_NAME = "${osReleaseContents.PRETTY_NAME} (Initrd)";
};
initrdRelease = pkgs.writeText "initrd-release" (attrsToText initrdReleaseContents);
in
{
imports = [
@ -119,20 +139,12 @@ in
DISTRIB_DESCRIPTION = "NixOS ${cfg.release} (${cfg.codeName})";
};
"os-release".text = attrsToText {
NAME = "NixOS";
ID = "nixos";
VERSION = "${cfg.release} (${cfg.codeName})";
VERSION_CODENAME = toLower cfg.codeName;
VERSION_ID = cfg.release;
BUILD_ID = cfg.version;
PRETTY_NAME = "NixOS ${cfg.release} (${cfg.codeName})";
LOGO = "nix-snowflake";
HOME_URL = "https://nixos.org/";
DOCUMENTATION_URL = "https://nixos.org/learn.html";
SUPPORT_URL = "https://nixos.org/community.html";
BUG_REPORT_URL = "https://github.com/NixOS/nixpkgs/issues";
};
"os-release".text = attrsToText osReleaseContents;
};
boot.initrd.systemd.contents = {
"/etc/os-release".source = initrdRelease;
"/etc/initrd-release".source = initrdRelease;
};
};

View file

@ -850,7 +850,6 @@
./services/networking/ofono.nix
./services/networking/oidentd.nix
./services/networking/onedrive.nix
./services/networking/openfire.nix
./services/networking/openvpn.nix
./services/networking/ostinato.nix
./services/networking/owamp.nix
@ -977,6 +976,7 @@
./services/security/shibboleth-sp.nix
./services/security/sks.nix
./services/security/sshguard.nix
./services/security/sslmate-agent.nix
./services/security/step-ca.nix
./services/security/tor.nix
./services/security/torify.nix
@ -1048,6 +1048,7 @@
./services/web-apps/mediawiki.nix
./services/web-apps/miniflux.nix
./services/web-apps/moodle.nix
./services/web-apps/netbox.nix
./services/web-apps/nextcloud.nix
./services/web-apps/nexus.nix
./services/web-apps/node-red.nix
@ -1179,6 +1180,7 @@
./system/boot/systemd/nspawn.nix
./system/boot/systemd/tmpfiles.nix
./system/boot/systemd/user.nix
./system/boot/systemd/initrd.nix
./system/boot/timesyncd.nix
./system/boot/tmp.nix
./system/etc/etc-activation.nix

View file

@ -3,67 +3,66 @@
with lib;
let
cfg = config.programs._1password-gui;
in {
in
{
options = {
programs._1password-gui = {
enable = mkEnableOption "The 1Password Desktop application with browser integration";
enable = mkEnableOption "the 1Password GUI application";
groupId = mkOption {
type = types.int;
gid = mkOption {
type = types.addCheck types.int (x: x >= 1000);
example = literalExpression "5000";
description = ''
The GroupID to assign to the onepassword group, which is needed for browser integration. The group ID must be 1000 or greater.
'';
The gid to assign to the onepassword group, which is needed for browser integration.
It must be 1000 or greater.
'';
};
polkitPolicyOwners = mkOption {
type = types.listOf types.str;
default = [];
example = literalExpression "[\"user1\" \"user2\" \"user3\"]";
default = [ ];
example = literalExpression ''["user1" "user2" "user3"]'';
description = ''
A list of users who should be able to integrate 1Password with polkit-based authentication mechanisms. By default, no users will have such access.
'';
A list of users who should be able to integrate 1Password with polkit-based authentication mechanisms.
'';
};
package = mkOption {
type = types.package;
default = pkgs._1password-gui;
defaultText = literalExpression "pkgs._1password-gui";
example = literalExpression "pkgs._1password-gui";
description = ''
The 1Password derivation to use. This can be used to upgrade from the stable release that we keep in nixpkgs to the betas.
'';
package = mkPackageOption pkgs "1Password GUI" {
default = [ "_1password-gui" ];
};
};
};
config = let
package = cfg.package.override {
polkitPolicyOwners = cfg.polkitPolicyOwners;
};
in mkIf cfg.enable {
environment.systemPackages = [ package ];
users.groups.onepassword.gid = cfg.groupId;
config =
let
package = cfg.package.override {
polkitPolicyOwners = cfg.polkitPolicyOwners;
};
in
mkIf cfg.enable {
environment.systemPackages = [ package ];
users.groups.onepassword.gid = cfg.gid;
security.wrappers = {
"1Password-BrowserSupport" =
{ source = "${cfg.package}/share/1password/1Password-BrowserSupport";
security.wrappers = {
"1Password-BrowserSupport" = {
source = "${package}/share/1password/1Password-BrowserSupport";
owner = "root";
group = "onepassword";
setuid = false;
setgid = true;
};
"1Password-KeyringHelper" =
{ source = "${cfg.package}/share/1password/1Password-KeyringHelper";
"1Password-KeyringHelper" = {
source = "${package}/share/1password/1Password-KeyringHelper";
owner = "root";
group = "onepassword";
setuid = true;
setgid = true;
};
};
};
};
};
}

View file

@ -3,35 +3,33 @@
with lib;
let
cfg = config.programs._1password;
in {
in
{
options = {
programs._1password = {
enable = mkEnableOption "The 1Password CLI tool with biometric unlock and integration with the 1Password GUI.";
enable = mkEnableOption "the 1Password CLI tool";
groupId = mkOption {
type = types.int;
gid = mkOption {
type = types.addCheck types.int (x: x >= 1000);
example = literalExpression "5001";
description = ''
The GroupID to assign to the onepassword-cli group, which is needed for integration with the 1Password GUI. The group ID must be 1000 or greater.
The gid to assign to the onepassword-cli group, which is needed for integration with the 1Password GUI.
It must be 1000 or greater.
'';
};
package = mkOption {
type = types.package;
default = pkgs._1password;
defaultText = literalExpression "pkgs._1password";
example = literalExpression "pkgs._1password";
description = ''
The 1Password CLI derivation to use.
'';
package = mkPackageOption pkgs "1Password CLI" {
default = [ "_1password" ];
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
users.groups.onepassword-cli.gid = cfg.groupId;
users.groups.onepassword-cli.gid = cfg.gid;
security.wrappers = {
"op" = {

View file

@ -23,8 +23,7 @@ with lib;
###### implementation
config = mkIf config.programs.adb.enable {
services.udev.packages = [ pkgs.android-udev-rules ];
# Give platform-tools lower priority so mke2fs+friends are taken from other packages first
environment.systemPackages = [ (lowPrio pkgs.androidenv.androidPkgs_9_0.platform-tools) ];
environment.systemPackages = [ pkgs.android-tools ];
users.groups.adbusers = {};
};
}

View file

@ -91,6 +91,7 @@ with lib;
(mkRemovedOptionModule [ "services" "shellinabox" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "gogoclient" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "virtuoso" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "services" "openfire" ] "The corresponding package was removed from nixpkgs.")
# Do NOT add any option renames here, see top of the file
];

View file

@ -38,6 +38,9 @@ in
environment.etc."zrepl/zrepl.yml".source = configFile;
systemd.packages = [ pkgs.zrepl ];
# Note that pkgs.zrepl copies and adapts the upstream systemd unit, and
# the fields defined here only override certain fields from that unit.
systemd.services.zrepl = {
requires = [ "local-fs.target" ];
wantedBy = [ "zfs.target" ];

View file

@ -1,4 +1,4 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.jenkinsSlave;
@ -46,6 +46,15 @@ in {
this is the home of the "jenkins" user.
'';
};
javaPackage = mkOption {
default = pkgs.jdk;
defaultText = literalExpression "pkgs.jdk";
description = ''
Java package to install.
'';
type = types.package;
};
};
};
@ -64,5 +73,10 @@ in {
uid = config.ids.uids.jenkins;
};
};
programs.java = {
enable = true;
package = cfg.javaPackage;
};
};
}

View file

@ -29,14 +29,7 @@
},
{
"name": "libpipewire-module-protocol-pulse",
"args": {
"server.address": [
"unix:native"
],
"vm.overrides": {
"pulse.min.quantum": "1024/48000"
}
}
"args": {}
}
],
"context.exec": [
@ -46,6 +39,14 @@
}
],
"stream.properties": {},
"pulse.properties": {
"server.address": [
"unix:native"
],
"vm.overrides": {
"pulse.min.quantum": "1024/48000"
}
},
"pulse.rules": [
{
"matches": [

View file

@ -38,7 +38,7 @@ in
environment.etc."wireplumber/main.lua.d/80-nixos.lua" = lib.mkIf (!pwUsedForAudio) {
text = ''
# Pipewire is not used for audio, so prevent it from grabbing audio devices
-- Pipewire is not used for audio, so prevent it from grabbing audio devices
alsa_monitor.enable = function() end
'';
};

View file

@ -194,6 +194,7 @@ in {
extraGroups = [ cfg.group ];
home = "/var/lib/jupyter";
createHome = true;
isSystemUser = true;
useDefaultShell = true; # needed so that the user can start a terminal.
};
})

View file

@ -5,7 +5,10 @@ with lib;
let
cfg = config.services.logrotate;
pathOpts = { name, ... }: {
# deprecated legacy compat settings
# these options will be removed before 22.11 in the following PR:
# https://github.com/NixOS/nixpkgs/pull/164169
pathOpts = { name, ... }: {
options = {
enable = mkOption {
type = types.bool;
@ -86,23 +89,113 @@ let
config.name = name;
};
mkConf = pathOpts: ''
# generated by NixOS using the `services.logrotate.paths.${pathOpts.name}` attribute set
${concatMapStringsSep " " (path: ''"${path}"'') (toList pathOpts.path)} {
${optionalString (pathOpts.user != null || pathOpts.group != null) "su ${pathOpts.user} ${pathOpts.group}"}
${pathOpts.frequency}
rotate ${toString pathOpts.keep}
${pathOpts.extraConfig}
}
'';
paths = sortProperties (attrValues (filterAttrs (_: pathOpts: pathOpts.enable) cfg.paths));
configFile = pkgs.writeText "logrotate.conf" (
concatStringsSep "\n" (
[ "missingok" "notifempty" cfg.extraConfig ] ++ (map mkConf paths)
)
generateLine = n: v:
if builtins.elem n [ "files" "priority" "enable" "global" ] || v == null then null
else if builtins.elem n [ "extraConfig" "frequency" ] then "${v}\n"
else if builtins.elem n [ "firstaction" "lastaction" "prerotate" "postrotate" "preremove" ]
then "${n}\n ${v}\n endscript\n"
else if isInt v then "${n} ${toString v}\n"
else if v == true then "${n}\n"
else if v == false then "no${n}\n"
else "${n} ${v}\n";
generateSection = indent: settings: concatStringsSep (fixedWidthString indent " " "") (
filter (x: x != null) (mapAttrsToList generateLine settings)
);
# generateSection includes a final newline hence weird closing brace
mkConf = settings:
if settings.global or false then generateSection 0 settings
else ''
${concatMapStringsSep "\n" (files: ''"${files}"'') (toList settings.files)} {
${generateSection 2 settings}}
'';
# below two mapPaths are compat functions
mapPathOptToSetting = n: v:
if n == "keep" then nameValuePair "rotate" v
else if n == "path" then nameValuePair "files" v
else nameValuePair n v;
mapPathsToSettings = path: pathOpts:
nameValuePair path (
filterAttrs (n: v: ! builtins.elem n [ "user" "group" "name" ] && v != "") (
(mapAttrs' mapPathOptToSetting pathOpts) //
{
su =
if pathOpts.user != null
then "${pathOpts.user} ${pathOpts.group}"
else null;
}
)
);
settings = sortProperties (attrValues (filterAttrs (_: settings: settings.enable) (
foldAttrs recursiveUpdate { } [
{
header = {
enable = true;
missingok = true;
notifempty = true;
frequency = "weekly";
rotate = 4;
};
# compat section
extraConfig = {
enable = (cfg.extraConfig != "");
global = true;
extraConfig = cfg.extraConfig;
priority = 101;
};
}
(mapAttrs' mapPathsToSettings cfg.paths)
cfg.settings
{ header = { global = true; priority = 100; }; }
]
)));
configFile = pkgs.writeTextFile {
name = "logrotate.conf";
text = concatStringsSep "\n" (
map mkConf settings
);
checkPhase = optionalString cfg.checkConfig ''
# logrotate --debug also checks that users specified in config
# file exist, but we only have sandboxed users here so brown these
# out. according to man page that means su, create and createolddir.
# files required to exist also won't be present, so missingok is forced.
user=$(${pkgs.coreutils}/bin/id -un)
group=$(${pkgs.coreutils}/bin/id -gn)
sed -e "s/\bsu\s.*/su $user $group/" \
-e "s/\b\(create\s\+[0-9]*\s*\|createolddir\s\+[0-9]*\s\+\).*/\1$user $group/" \
-e "1imissingok" -e "s/\bnomissingok\b//" \
$out > /tmp/logrotate.conf
# Since this makes for very verbose builds only show real error.
# There is no way to control log level, but logrotate hardcodes
# 'error:' at common log level, so we can use grep, taking care
# to keep error codes
set -o pipefail
if ! ${pkgs.logrotate}/sbin/logrotate --debug /tmp/logrotate.conf 2>&1 \
| ( ! grep "error:" ) > /tmp/logrotate-error; then
echo "Logrotate configuration check failed."
echo "The failing configuration (after adjustments to pass tests in sandbox) was:"
printf "%s\n" "-------"
cat /tmp/logrotate.conf
printf "%s\n" "-------"
echo "The error reported by logrotate was as follow:"
printf "%s\n" "-------"
cat /tmp/logrotate-error
printf "%s\n" "-------"
echo "You can disable this check with services.logrotate.checkConfig = false,"
echo "but if you think it should work please report this failure along with"
echo "the config file being tested!"
false
fi
'';
};
mailOption =
if foldr (n: a: a || n ? mail) false (attrValues cfg.settings)
then "--mail=${pkgs.mailutils}/bin/mail"
else "";
in
{
imports = [
@ -112,17 +205,121 @@ in
options = {
services.logrotate = {
enable = mkEnableOption "the logrotate systemd service" // {
default = foldr (n: a: a || n.enable) false (attrValues cfg.paths);
defaultText = literalExpression "cfg.paths != {}";
default = foldr (n: a: a || n.enable) false (attrValues cfg.settings);
defaultText = literalExpression "cfg.settings != {}";
};
settings = mkOption {
default = { };
description = ''
logrotate freeform settings: each attribute here will define its own section,
ordered by priority, which can either define files to rotate with their settings
or settings common to all further files settings.
Refer to <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
'';
type = types.attrsOf (types.submodule ({ name, ... }: {
freeformType = with types; attrsOf (nullOr (oneOf [ int bool str ]));
options = {
enable = mkEnableOption "setting individual kill switch" // {
default = true;
};
global = mkOption {
type = types.bool;
default = false;
description = ''
Whether this setting is a global option or not: set to have these
settings apply to all files settings with a higher priority.
'';
};
files = mkOption {
type = with types; either str (listOf str);
default = name;
defaultText = ''
The attrset name if not specified
'';
description = ''
Single or list of files for which rules are defined.
The files are quoted with double-quotes in logrotate configuration,
so globs and spaces are supported.
Note this setting is ignored if globals is true.
'';
};
frequency = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
How often to rotate the logs. Defaults to previously set global setting,
which itself defauts to weekly.
'';
};
priority = mkOption {
type = types.int;
default = 1000;
description = ''
Order of this logrotate block in relation to the others. The semantics are
the same as with `lib.mkOrder`. Smaller values are inserted first.
'';
};
};
}));
};
configFile = mkOption {
type = types.path;
default = configFile;
defaultText = ''
A configuration file automatically generated by NixOS.
'';
description = ''
Override the configuration file used by MySQL. By default,
NixOS generates one automatically from <xref linkend="opt-services.logrotate.settings"/>.
'';
example = literalExpression ''
pkgs.writeText "logrotate.conf" '''
missingok
"/var/log/*.log" {
rotate 4
weekly
}
''';
'';
};
checkConfig = mkOption {
type = types.bool;
default = true;
description = ''
Whether the config should be checked at build time.
Some options are not checkable at build time because of the build sandbox:
for example, the test does not know about existing files and system users are
not known.
These limitations mean we must adjust the file for tests (missingok is forced
and users are replaced by dummy users), so tests are complemented by a
logrotate-checkconf service that is enabled by default.
This extra check can be disabled by disabling it at the systemd level with the
<option>services.systemd.services.logrotate-checkconf.enable</option> option.
Conversely there are still things that might make this check fail incorrectly
(e.g. a file path where we don't have access to intermediate directories):
in this case you can disable the failing check with this option.
'';
};
# deprecated legacy compat settings
paths = mkOption {
type = with types; attrsOf (submodule pathOpts);
default = {};
default = { };
description = ''
Attribute set of paths to rotate. The order each block appears in the generated configuration file
can be controlled by the <link linkend="opt-services.logrotate.paths._name_.priority">priority</link> option
using the same semantics as `lib.mkOrder`. Smaller values have a greater priority.
This setting has been deprecated in favor of <link linkend="opt-services.logrotate.settings">logrotate settings</link>.
'';
example = literalExpression ''
{
@ -151,19 +348,37 @@ in
description = ''
Extra contents to append to the logrotate configuration file. Refer to
<link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
This setting has been deprecated in favor of
<link linkend="opt-services.logrotate.settings">logrotate settings</link>.
'';
};
};
};
config = mkIf cfg.enable {
assertions = mapAttrsToList (name: pathOpts:
{ assertion = (pathOpts.user != null) == (pathOpts.group != null);
message = ''
If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified.
'';
}
) cfg.paths;
assertions =
mapAttrsToList
(name: pathOpts:
{
assertion = (pathOpts.user != null) == (pathOpts.group != null);
message = ''
If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified.
'';
})
cfg.paths;
warnings =
(mapAttrsToList
(name: pathOpts: ''
Using config.services.logrotate.paths.${name} is deprecated and will become unsupported in a future release.
Please use services.logrotate.settings instead.
'')
cfg.paths
) ++
(optional (cfg.extraConfig != "") ''
Using config.services.logrotate.extraConfig is deprecated and will become unsupported in a future release.
Please use services.logrotate.settings with globals=true instead.
'');
systemd.services.logrotate = {
description = "Logrotate Service";
@ -172,7 +387,16 @@ in
serviceConfig = {
Restart = "no";
User = "root";
ExecStart = "${pkgs.logrotate}/sbin/logrotate ${configFile}";
ExecStart = "${pkgs.logrotate}/sbin/logrotate ${mailOption} ${cfg.configFile}";
};
};
systemd.services.logrotate-checkconf = {
description = "Logrotate configuration check";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${pkgs.logrotate}/sbin/logrotate --debug ${cfg.configFile}";
};
};
};

View file

@ -141,7 +141,7 @@ in {
enable = mkEnableOption "matrix.org synapse";
configFile = mkOption {
type = types.str;
type = types.path;
readOnly = true;
description = ''
Path to the configuration file on the target system. Useful to configure e.g. workers

View file

@ -848,10 +848,7 @@ in {
extraConfig = mkOption {
type = types.lines;
default = ''
copytruncate
compress
'';
default = "";
description = ''
Extra logrotate config options for this path. Refer to
<link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
@ -977,13 +974,14 @@ in {
# Enable rotation of log files
services.logrotate = {
enable = cfg.logrotate.enable;
paths = {
settings = {
gitlab = {
path = "${cfg.statePath}/log/*.log";
user = cfg.user;
group = cfg.group;
files = "${cfg.statePath}/log/*.log";
su = "${cfg.user} ${cfg.group}";
frequency = cfg.logrotate.frequency;
keep = cfg.logrotate.keep;
rotate = cfg.logrotate.keep;
copytruncate = true;
compress = true;
extraConfig = cfg.logrotate.extraConfig;
};
};

View file

@ -39,7 +39,7 @@ in
type = types.str;
example = "45min";
description = ''
Add a randomized delay before each automatic upgrade.
Add a randomized delay before each garbage collection.
The delay will be chosen between zero and this value.
This value must be a time span in the format specified by
<citerefentry><refentrytitle>systemd.time</refentrytitle>

View file

@ -215,6 +215,8 @@ in
Restart = "on-failure";
# The `mbind` syscall is needed for running the classifier.
SystemCallFilter = defaultServiceConfig.SystemCallFilter ++ [ "mbind" ];
# Needs to talk to mail server for automated import rules
PrivateNetwork = false;
};
environment = env;
wantedBy = [ "multi-user.target" ];
@ -257,8 +259,6 @@ in
'${cfg.passwordFile}' '${cfg.dataDir}/superuser-password'
'';
Type = "oneshot";
# Needs to talk to mail server for automated import rules
PrivateNetwork = false;
};
};

View file

@ -5,36 +5,15 @@ with lib;
let
cfg = config.services.collectd;
unvalidated_conf = pkgs.writeText "collectd-unvalidated.conf" ''
BaseDir "${cfg.dataDir}"
AutoLoadPlugin ${boolToString cfg.autoLoadPlugin}
Hostname "${config.networking.hostName}"
LoadPlugin syslog
<Plugin "syslog">
LogLevel "info"
NotifyLevel "OKAY"
</Plugin>
${concatStrings (mapAttrsToList (plugin: pluginConfig: ''
LoadPlugin ${plugin}
<Plugin "${plugin}">
${pluginConfig}
</Plugin>
'') cfg.plugins)}
${concatMapStrings (f: ''
Include "${f}"
'') cfg.include}
${cfg.extraConfig}
'';
baseDirLine = ''BaseDir "${cfg.dataDir}"'';
unvalidated_conf = pkgs.writeText "collectd-unvalidated.conf" cfg.extraConfig;
conf = if cfg.validateConfig then
pkgs.runCommand "collectd.conf" {} ''
echo testing ${unvalidated_conf}
cp ${unvalidated_conf} collectd.conf
# collectd -t fails if BaseDir does not exist.
sed '1s/^BaseDir.*$/BaseDir "."/' ${unvalidated_conf} > collectd.conf
substituteInPlace collectd.conf --replace ${lib.escapeShellArgs [ baseDirLine ]} 'BaseDir "."'
${package}/bin/collectd -t -C collectd.conf
cp ${unvalidated_conf} $out
'' else unvalidated_conf;
@ -123,7 +102,8 @@ in {
extraConfig = mkOption {
default = "";
description = ''
Extra configuration for collectd.
Extra configuration for collectd. Use mkBefore to add lines before the
default config, and mkAfter to add them below.
'';
type = lines;
};
@ -131,6 +111,30 @@ in {
};
config = mkIf cfg.enable {
# 1200 is after the default (1000) but before mkAfter (1500).
services.collectd.extraConfig = lib.mkOrder 1200 ''
${baseDirLine}
AutoLoadPlugin ${boolToString cfg.autoLoadPlugin}
Hostname "${config.networking.hostName}"
LoadPlugin syslog
<Plugin "syslog">
LogLevel "info"
NotifyLevel "OKAY"
</Plugin>
${concatStrings (mapAttrsToList (plugin: pluginConfig: ''
LoadPlugin ${plugin}
<Plugin "${plugin}">
${pluginConfig}
</Plugin>
'') cfg.plugins)}
${concatMapStrings (f: ''
Include "${f}"
'') cfg.include}
'';
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' - ${cfg.user} - - -"
];

View file

@ -17,7 +17,7 @@ in
};
birdSocket = mkOption {
type = types.path;
default = "/var/run/bird.ctl";
default = "/run/bird/bird.ctl";
description = ''
Path to BIRD2 (or BIRD1 v4) socket.
'';

View file

@ -9,20 +9,26 @@ with lib;
let
cfg = config.services.kea;
xor = x: y: (!x && y) || (x && !y);
format = pkgs.formats.json {};
ctrlAgentConfig = format.generate "kea-ctrl-agent.conf" {
chooseNotNull = x: y: if x != null then x else y;
ctrlAgentConfig = chooseNotNull cfg.ctrl-agent.configFile (format.generate "kea-ctrl-agent.conf" {
Control-agent = cfg.ctrl-agent.settings;
};
dhcp4Config = format.generate "kea-dhcp4.conf" {
});
dhcp4Config = chooseNotNull cfg.dhcp4.configFile (format.generate "kea-dhcp4.conf" {
Dhcp4 = cfg.dhcp4.settings;
};
dhcp6Config = format.generate "kea-dhcp6.conf" {
});
dhcp6Config = chooseNotNull cfg.dhcp6.configFile (format.generate "kea-dhcp6.conf" {
Dhcp6 = cfg.dhcp6.settings;
};
dhcpDdnsConfig = format.generate "kea-dhcp-ddns.conf" {
});
dhcpDdnsConfig = chooseNotNull cfg.dhcp-ddns.configFile (format.generate "kea-dhcp-ddns.conf" {
DhcpDdns = cfg.dhcp-ddns.settings;
};
});
package = pkgs.kea;
in
@ -45,6 +51,17 @@ in
'';
};
configFile = mkOption {
type = nullOr path;
default = null;
description = ''
Kea Control Agent configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html"/>.
Takes preference over <link linkend="opt-services.kea.ctrl-agent.settings">settings</link>.
Most users should prefer using <link linkend="opt-services.kea.ctrl-agent.settings">settings</link> instead.
'';
};
settings = mkOption {
type = format.type;
default = null;
@ -73,6 +90,17 @@ in
'';
};
configFile = mkOption {
type = nullOr path;
default = null;
description = ''
Kea DHCP4 configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp4-srv.html"/>.
Takes preference over <link linkend="opt-services.kea.dhcp4.settings">settings</link>.
Most users should prefer using <link linkend="opt-services.kea.dhcp4.settings">settings</link> instead.
'';
};
settings = mkOption {
type = format.type;
default = null;
@ -122,6 +150,17 @@ in
'';
};
configFile = mkOption {
type = nullOr path;
default = null;
description = ''
Kea DHCP6 configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp6-srv.html"/>.
Takes preference over <link linkend="opt-services.kea.dhcp6.settings">settings</link>.
Most users should prefer using <link linkend="opt-services.kea.dhcp6.settings">settings</link> instead.
'';
};
settings = mkOption {
type = format.type;
default = null;
@ -172,6 +211,17 @@ in
'';
};
configFile = mkOption {
type = nullOr path;
default = null;
description = ''
Kea DHCP-DDNS configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html"/>.
Takes preference over <link linkend="opt-services.kea.dhcp-ddns.settings">settings</link>.
Most users should prefer using <link linkend="opt-services.kea.dhcp-ddns.settings">settings</link> instead.
'';
};
settings = mkOption {
type = format.type;
default = null;
@ -214,6 +264,10 @@ in
}
(mkIf cfg.ctrl-agent.enable {
assertions = [{
assertion = xor (cfg.ctrl-agent.settings == null) (cfg.ctrl-agent.configFile == null);
message = "Either services.kea.ctrl-agent.settings or services.kea.ctrl-agent.configFile must be set to a non-null value.";
}];
environment.etc."kea/ctrl-agent.conf".source = ctrlAgentConfig;
@ -252,6 +306,10 @@ in
})
(mkIf cfg.dhcp4.enable {
assertions = [{
assertion = xor (cfg.dhcp4.settings == null) (cfg.dhcp4.configFile == null);
message = "Either services.kea.dhcp4.settings or services.kea.dhcp4.configFile must be set to a non-null value.";
}];
environment.etc."kea/dhcp4-server.conf".source = dhcp4Config;
@ -295,6 +353,10 @@ in
})
(mkIf cfg.dhcp6.enable {
assertions = [{
assertion = xor (cfg.dhcp6.settings == null) (cfg.dhcp6.configFile == null);
message = "Either services.kea.dhcp6.settings or services.kea.dhcp6.configFile must be set to a non-null value.";
}];
environment.etc."kea/dhcp6-server.conf".source = dhcp6Config;
@ -336,6 +398,10 @@ in
})
(mkIf cfg.dhcp-ddns.enable {
assertions = [{
assertion = xor (cfg.dhcp-ddns.settings == null) (cfg.dhcp-ddns.configFile == null);
message = "Either services.kea.dhcp-ddns.settings or services.kea.dhcp-ddns.configFile must be set to a non-null value.";
}];
environment.etc."kea/dhcp-ddns.conf".source = dhcpDdnsConfig;

View file

@ -51,18 +51,14 @@ in
environment.etc."lxd-image-server/config.toml".source = format.generate "config.toml" cfg.settings;
services.logrotate.paths.lxd-image-server = {
path = "/var/log/lxd-image-server/lxd-image-server.log";
services.logrotate.settings.lxd-image-server = {
files = "/var/log/lxd-image-server/lxd-image-server.log";
frequency = "daily";
keep = 21;
extraConfig = ''
create 755 lxd-image-server ${cfg.group}
missingok
compress
delaycompress
copytruncate
notifempty
'';
rotate = 21;
create = "755 lxd-image-server ${cfg.group}";
compress = true;
delaycompress = true;
copytruncate = true;
};
systemd.tmpfiles.rules = [

View file

@ -1,56 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
{
###### interface
options = {
services.openfire = {
enable = mkEnableOption "OpenFire XMPP server";
usePostgreSQL = mkOption {
type = types.bool;
default = true;
description = "
Whether you use PostgreSQL service for your storage back-end.
";
};
};
};
###### implementation
config = mkIf config.services.openfire.enable {
assertions = singleton
{ assertion = !(config.services.openfire.usePostgreSQL -> config.services.postgresql.enable);
message = "OpenFire configured to use PostgreSQL but services.postgresql.enable is not enabled.";
};
systemd.services.openfire = {
description = "OpenFire XMPP server";
wantedBy = [ "multi-user.target" ];
after = [ "networking.target" ] ++
optional config.services.openfire.usePostgreSQL "postgresql.service";
path = with pkgs; [ jre openfire coreutils which gnugrep gawk gnused ];
script = ''
export HOME=/tmp
mkdir /var/log/openfire || true
mkdir /etc/openfire || true
for i in ${pkgs.openfire}/conf.inst/*; do
if ! test -f /etc/openfire/$(basename $i); then
cp $i /etc/openfire/
fi
done
openfire start
''; # */
};
};
}

View file

@ -61,6 +61,15 @@ in
Group to use when running Syncplay.
'';
};
passwordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to the file that contains the server password. If
<literal>null</literal>, the server doesn't require a password.
'';
};
};
};
@ -71,10 +80,17 @@ in
after = [ "network-online.target" ];
serviceConfig = {
ExecStart = "${pkgs.syncplay}/bin/syncplay-server ${escapeShellArgs cmdArgs}";
User = cfg.user;
Group = cfg.group;
LoadCredential = lib.mkIf (cfg.passwordFile != null) "password:${cfg.passwordFile}";
};
script = ''
${lib.optionalString (cfg.passwordFile != null) ''
export SYNCPLAY_PASSWORD=$(cat "''${CREDENTIALS_DIRECTORY}/password")
''}
exec ${pkgs.syncplay}/bin/syncplay-server ${escapeShellArgs cmdArgs}
'';
};
};
}

View file

@ -571,8 +571,11 @@ in
users.users.oauth2_proxy = {
description = "OAuth2 Proxy";
isSystemUser = true;
group = "oauth2_proxy";
};
users.groups.oauth2_proxy = {};
systemd.services.oauth2_proxy = {
description = "OAuth2 Proxy";
path = [ cfg.package ];

View file

@ -159,7 +159,7 @@ in
'';
};
caddy.enable = mkEnableOption "Whether to enablle caddy reverse proxy to expose jitsi-meet";
caddy.enable = mkEnableOption "Whether to enable caddy reverse proxy to expose jitsi-meet";
prosody.enable = mkOption {
type = bool;

View file

@ -9,6 +9,8 @@ let
RAILS_ENV = "production";
NODE_ENV = "production";
LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
# mastodon-web concurrency.
WEB_CONCURRENCY = toString cfg.webProcesses;
MAX_THREADS = toString cfg.webThreads;
@ -121,7 +123,7 @@ in {
Make sure that websockets are forwarded properly. You might want to set up caching
of some requests. Take a look at mastodon's provided nginx configuration at
<code>https://github.com/tootsuite/mastodon/blob/master/dist/nginx.conf</code>.
<code>https://github.com/mastodon/mastodon/blob/master/dist/nginx.conf</code>.
'';
type = lib.types.bool;
default = false;

View file

@ -0,0 +1,265 @@
{ config, lib, pkgs, buildEnv, ... }:
with lib;
let
cfg = config.services.netbox;
staticDir = cfg.dataDir + "/static";
configFile = pkgs.writeTextFile {
name = "configuration.py";
text = ''
STATIC_ROOT = '${staticDir}'
ALLOWED_HOSTS = ['*']
DATABASE = {
'NAME': 'netbox',
'USER': 'netbox',
'HOST': '/run/postgresql',
}
# Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
# configuration exists for each. Full connection details are required in both sections, and it is strongly recommended
# to use two separate database IDs.
REDIS = {
'tasks': {
'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=0',
'SSL': False,
},
'caching': {
'URL': 'unix://${config.services.redis.servers.netbox.unixSocket}?db=1',
'SSL': False,
}
}
with open("${cfg.secretKeyFile}", "r") as file:
SECRET_KEY = file.readline()
${optionalString cfg.enableLdap "REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'"}
${cfg.extraConfig}
'';
};
pkg = (pkgs.netbox.overrideAttrs (old: {
installPhase = old.installPhase + ''
ln -s ${configFile} $out/opt/netbox/netbox/netbox/configuration.py
'' + optionalString cfg.enableLdap ''
ln -s ${ldapConfigPath} $out/opt/netbox/netbox/netbox/ldap_config.py
'';
})).override {
plugins = ps: ((cfg.plugins ps)
++ optional cfg.enableLdap [ ps.django-auth-ldap ]);
};
netboxManageScript = with pkgs; (writeScriptBin "netbox-manage" ''
#!${stdenv.shell}
export PYTHONPATH=${pkg.pythonPath}
sudo -u netbox ${pkg}/bin/netbox "$@"
'');
in {
options.services.netbox = {
enable = mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable Netbox.
This module requires a reverse proxy that serves <literal>/static</literal> separately.
See this <link xlink:href="https://github.com/netbox-community/netbox/blob/develop/contrib/nginx.conf/">example</link> on how to configure this.
'';
};
listenAddress = mkOption {
type = types.str;
default = "[::1]";
description = ''
Address the server will listen on.
'';
};
port = mkOption {
type = types.port;
default = 8001;
description = ''
Port the server will listen on.
'';
};
plugins = mkOption {
type = types.functionTo (types.listOf types.package);
default = _: [];
defaultText = literalExpression ''
python3Packages: with python3Packages; [];
'';
description = ''
List of plugin packages to install.
'';
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/netbox";
description = ''
Storage path of netbox.
'';
};
secretKeyFile = mkOption {
type = types.path;
description = ''
Path to a file containing the secret key.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Additional lines of configuration appended to the <literal>configuration.py</literal>.
See the <link xlink:href="https://netbox.readthedocs.io/en/stable/configuration/optional-settings/">documentation</link> for more possible options.
'';
};
enableLdap = mkOption {
type = types.bool;
default = false;
description = ''
Enable LDAP-Authentication for Netbox.
This requires a configuration file being pass through <literal>ldapConfigPath</literal>.
'';
};
ldapConfigPath = mkOption {
type = types.path;
default = "";
description = ''
Path to the Configuration-File for LDAP-Authentification, will be loaded as <literal>ldap_config.py</literal>.
See the <link xlink:href="https://netbox.readthedocs.io/en/stable/installation/6-ldap/#configuration">documentation</link> for possible options.
'';
};
};
config = mkIf cfg.enable {
services.redis.servers.netbox.enable = true;
services.postgresql = {
enable = true;
ensureDatabases = [ "netbox" ];
ensureUsers = [
{
name = "netbox";
ensurePermissions = {
"DATABASE netbox" = "ALL PRIVILEGES";
};
}
];
};
environment.systemPackages = [ netboxManageScript ];
systemd.targets.netbox = {
description = "Target for all NetBox services";
wantedBy = [ "multi-user.target" ];
after = [ "network-online.target" "redis-netbox.service" ];
};
systemd.services = let
defaultServiceConfig = {
WorkingDirectory = "${cfg.dataDir}";
User = "netbox";
Group = "netbox";
StateDirectory = "netbox";
StateDirectoryMode = "0750";
Restart = "on-failure";
};
in {
netbox-migration = {
description = "NetBox migrations";
wantedBy = [ "netbox.target" ];
environment = {
PYTHONPATH = pkg.pythonPath;
};
serviceConfig = defaultServiceConfig // {
Type = "oneshot";
ExecStart = ''
${pkg}/bin/netbox migrate
'';
};
};
netbox = {
description = "NetBox WSGI Service";
wantedBy = [ "netbox.target" ];
after = [ "netbox-migration.service" ];
preStart = ''
${pkg}/bin/netbox trace_paths --no-input
${pkg}/bin/netbox collectstatic --no-input
${pkg}/bin/netbox remove_stale_contenttypes --no-input
'';
environment = {
PYTHONPATH = pkg.pythonPath;
};
serviceConfig = defaultServiceConfig // {
ExecStart = ''
${pkgs.python3Packages.gunicorn}/bin/gunicorn netbox.wsgi \
--bind ${cfg.listenAddress}:${toString cfg.port} \
--pythonpath ${pkg}/opt/netbox/netbox
'';
};
};
netbox-rq = {
description = "NetBox Request Queue Worker";
wantedBy = [ "netbox.target" ];
after = [ "netbox.service" ];
environment = {
PYTHONPATH = pkg.pythonPath;
};
serviceConfig = defaultServiceConfig // {
ExecStart = ''
${pkg}/bin/netbox rqworker high default low
'';
};
};
netbox-housekeeping = {
description = "NetBox housekeeping job";
after = [ "netbox.service" ];
environment = {
PYTHONPATH = pkg.pythonPath;
};
serviceConfig = defaultServiceConfig // {
Type = "oneshot";
ExecStart = ''
${pkg}/bin/netbox housekeeping
'';
};
};
};
systemd.timers.netbox-housekeeping = {
description = "Run NetBox housekeeping job";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
};
};
users.users.netbox = {
home = "${cfg.dataDir}";
isSystemUser = true;
group = "netbox";
};
users.groups.netbox = {};
users.groups."${config.services.redis.servers.netbox.user}".members = [ "netbox" ];
};
}

View file

@ -710,20 +710,15 @@ in
services.logrotate = optionalAttrs (cfg.logFormat != "none") {
enable = mkDefault true;
paths.httpd = {
path = "${cfg.logDir}/*.log";
user = cfg.user;
group = cfg.group;
settings.httpd = {
files = "${cfg.logDir}/*.log";
su = "${cfg.user} ${cfg.group}";
frequency = "daily";
keep = 28;
extraConfig = ''
sharedscripts
compress
delaycompress
postrotate
systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
'';
rotate = 28;
sharedscripts = true;
compress = true;
delaycompress = true;
postrotate = "systemctl reload httpd.service > /dev/null 2>/dev/null || true";
};
};

View file

@ -989,17 +989,14 @@ in
nginx.gid = config.ids.gids.nginx;
};
services.logrotate.paths.nginx = mapAttrs (_: mkDefault) {
path = "/var/log/nginx/*.log";
services.logrotate.settings.nginx = mapAttrs (_: mkDefault) {
files = "/var/log/nginx/*.log";
frequency = "weekly";
keep = 26;
extraConfig = ''
compress
delaycompress
postrotate
[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`
endscript
'';
su = "${cfg.user} ${cfg.group}";
rotate = 26;
compress = true;
delaycompress = true;
postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`";
};
};
}

View file

@ -302,6 +302,7 @@ in
environment.systemPackages = with pkgs.pantheon; [
contractor
file-roller-contract
gnome-bluetooth-contract
];
environment.pathsToLink = [

View file

@ -99,6 +99,7 @@ in
ristretto
xfce4-appfinder
xfce4-notifyd
xfce4-screensaver
xfce4-screenshooter
xfce4-session
xfce4-settings
@ -168,5 +169,6 @@ in
xfce4-notifyd
];
security.pam.services.xfce4-screensaver.unixAuth = true;
};
}

View file

@ -241,7 +241,7 @@ in
"xhci_pci"
"usbhid"
"hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
"hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft"
"hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry"
] ++ optionals pkgs.stdenv.hostPlatform.isx86 [
# Misc. x86 keyboard stuff.

View file

@ -877,7 +877,7 @@ in
copy_bin_and_libs ${pkgs.yubikey-personalization}/bin/ykinfo
copy_bin_and_libs ${pkgs.openssl.bin}/bin/openssl
cc -O3 -I${pkgs.openssl.dev}/include -L${pkgs.openssl.out}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto
cc -O3 -I${pkgs.openssl.dev}/include -L${lib.getLib pkgs.openssl}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto
strip -s pbkdf2-sha512
copy_bin_and_libs pbkdf2-sha512

View file

@ -1867,6 +1867,48 @@ in
}));
};
systemd.network.wait-online = {
anyInterface = mkOption {
description = ''
Whether to consider the network online when any interface is online, as opposed to all of them.
This is useful on portable machines with a wired and a wireless interface, for example.
'';
type = types.bool;
default = false;
};
ignoredInterfaces = mkOption {
description = ''
Network interfaces to be ignored when deciding if the system is online.
'';
type = with types; listOf str;
default = [];
example = [ "wg0" ];
};
timeout = mkOption {
description = ''
Time to wait for the network to come online, in seconds. Set to 0 to disable.
'';
type = types.ints.unsigned;
default = 120;
example = 0;
};
extraArgs = mkOption {
description = ''
Extra command-line arguments to pass to systemd-networkd-wait-online.
These also affect per-interface <literal>systemd-network-wait-online@</literal> services.
See <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html">
<citerefentry><refentrytitle>systemd-networkd-wait-online.service</refentrytitle><manvolnum>8</manvolnum>
</citerefentry></link> for all available options.
'';
type = with types; listOf str;
default = [];
};
};
};
config = mkMerge [
@ -1875,6 +1917,11 @@ in
{
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
environment.etc = unitFiles;
systemd.network.wait-online.extraArgs =
[ "--timeout=${toString cfg.wait-online.timeout}" ]
++ optional cfg.wait-online.anyInterface "--any"
++ map (i: "--ignore=${i}") cfg.wait-online.ignoredInterfaces;
}
(mkIf config.systemd.network.enable {
@ -1905,6 +1952,10 @@ in
systemd.services.systemd-networkd-wait-online = {
wantedBy = [ "network-online.target" ];
serviceConfig.ExecStart = [
""
"${config.systemd.package}/lib/systemd/systemd-networkd-wait-online ${utils.escapeSystemdExecArgs cfg.wait-online.extraArgs}"
];
};
systemd.services."systemd-network-wait-online@" = {
@ -1915,7 +1966,7 @@ in
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I ${utils.escapeSystemdExecArgs cfg.wait-online.extraArgs}";
};
};

View file

@ -703,8 +703,12 @@ in
}
];
system.build =
{ inherit bootStage1 initialRamdisk initialRamdiskSecretAppender extraUtils; };
system.build = mkMerge [
{ inherit bootStage1 initialRamdiskSecretAppender extraUtils; }
# generated in nixos/modules/system/boot/systemd/initrd.nix
(mkIf (!config.boot.initrd.systemd.enable) { inherit initialRamdisk; })
];
system.requiredKernelConfig = with config.lib.kernelConfig; [
(isYes "TMPFS")

View file

@ -12,10 +12,6 @@ for o in $(</proc/cmdline); do
# Show each command.
set -x
;;
resume=*)
set -- $(IFS==; echo $o)
resumeDevice=$2
;;
esac
done
@ -72,46 +68,12 @@ if [ -n "@readOnlyStore@" ]; then
fi
# Provide a /etc/mtab.
install -m 0755 -d /etc
test -e /etc/fstab || touch /etc/fstab # to shut up mount
rm -f /etc/mtab* # not that we care about stale locks
ln -s /proc/mounts /etc/mtab
# More special file systems, initialise required directories.
[ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
install -m 01777 -d /tmp
install -m 0755 -d /var/{log,lib,db} /nix/var /etc/nixos/ \
/run/lock /home /bin # for the /bin/sh symlink
# Miscellaneous boot time cleanup.
rm -rf /var/run /var/lock
rm -f /etc/{group,passwd,shadow}.lock
# Also get rid of temporary GC roots.
rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots
# For backwards compatibility, symlink /var/run to /run, and /var/lock
# to /run/lock.
ln -s /run /var/run
ln -s /run/lock /var/lock
# Clear the resume device.
if test -n "$resumeDevice"; then
mkswap "$resumeDevice" || echo 'Failed to clear saved image.'
fi
# Use /etc/resolv.conf supplied by systemd-nspawn, if applicable.
if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then
resolvconf -m 1000 -a host </etc/resolv.conf
fi
# Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
# Only at this point are all the necessary prerequisites ready for these commands.
exec {logOutFd}>&1 {logErrFd}>&2
@ -127,28 +89,20 @@ else
fi
# Required by the activation script
install -m 0755 -d /etc /etc/nixos
install -m 01777 -d /tmp
# Run the script that performs all configuration activation that does
# not have to be done at boot time.
echo "running activation script..."
$systemConfig/activate
# Restore the system time from the hardware clock. We do this after
# running the activation script to be sure that /etc/localtime points
# at the current time zone.
if [ -e /dev/rtc ]; then
hwclock --hctosys
fi
# Record the boot configuration.
ln -sfn "$systemConfig" /run/booted-system
# Prevent the booted system from being garbage-collected. If it weren't
# a gcroot, if we were running a different kernel, switched system,
# and garbage collected all, we could not load kernel modules anymore.
ln -sfn /run/booted-system /nix/var/nix/gcroots/booted-system
# Run any user-specified commands.
@shell@ @postBootCommands@
@ -167,10 +121,6 @@ exec 1>&$logOutFd 2>&$logErrFd
exec {logOutFd}>&- {logErrFd}>&-
# Start systemd.
# Start systemd in a clean environment.
echo "starting systemd..."
PATH=/run/current-system/systemd/lib/systemd:@fsPackagesPath@ \
LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive @systemdUnitPathEnvVar@ \
TZDIR=/etc/zoneinfo \
exec @systemdExecutable@
exec @systemdExecutable@ "$@"

View file

@ -19,11 +19,6 @@ let
pkgs.coreutils
pkgs.util-linux
] ++ lib.optional useHostResolvConf pkgs.openresolv);
fsPackagesPath = lib.makeBinPath config.system.fsPackages;
systemdUnitPathEnvVar = lib.optionalString (config.boot.extraSystemdUnitPaths != [])
("SYSTEMD_UNIT_PATH="
+ builtins.concatStringsSep ":" config.boot.extraSystemdUnitPaths
+ ":"); # If SYSTEMD_UNIT_PATH ends with an empty component (":"), the usual unit load path will be appended to the contents of the variable
postBootCommands = pkgs.writeText "local-cmds"
''
${config.boot.postBootCommands}
@ -48,12 +43,10 @@ in
};
systemdExecutable = mkOption {
default = "systemd";
default = "/run/current-system/systemd/lib/systemd/systemd";
type = types.str;
description = ''
The program to execute to start systemd. Typically
<literal>systemd</literal>, which will find systemd in the
PATH.
The program to execute to start systemd.
'';
};

View file

@ -11,14 +11,7 @@ let
systemd = cfg.package;
inherit (systemdUtils.lib)
makeUnit
generateUnits
makeJobScript
unitConfig
serviceConfig
mountConfig
automountConfig
commonUnitText
targetToUnit
serviceToUnit
socketToUnit
@ -185,13 +178,7 @@ in
systemd.units = mkOption {
description = "Definition of systemd units.";
default = {};
type = with types; attrsOf (submodule (
{ name, config, ... }:
{ options = concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
}));
type = systemdUtils.types.units;
};
systemd.packages = mkOption {
@ -203,37 +190,37 @@ in
systemd.targets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig] );
type = systemdUtils.types.targets;
description = "Definition of systemd target units.";
};
systemd.services = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ]);
type = systemdUtils.types.services;
description = "Definition of systemd service units.";
};
systemd.sockets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ]);
type = systemdUtils.types.sockets;
description = "Definition of systemd socket units.";
};
systemd.timers = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ]);
type = systemdUtils.types.timers;
description = "Definition of systemd timer units.";
};
systemd.paths = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
type = systemdUtils.types.paths;
description = "Definition of systemd path units.";
};
systemd.mounts = mkOption {
default = [];
type = with types; listOf (submodule [ { options = mountOptions; } unitConfig mountConfig ]);
type = systemdUtils.types.mounts;
description = ''
Definition of systemd mount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
@ -243,7 +230,7 @@ in
systemd.automounts = mkOption {
default = [];
type = with types; listOf (submodule [ { options = automountOptions; } unitConfig automountConfig ]);
type = systemdUtils.types.automounts;
description = ''
Definition of systemd automount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
@ -253,7 +240,7 @@ in
systemd.slices = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = sliceOptions; } unitConfig] );
type = systemdUtils.types.slices;
description = "Definition of slice configurations.";
};
@ -302,6 +289,16 @@ in
'';
};
systemd.managerEnvironment = mkOption {
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
default = {};
example = { SYSTEMD_LOG_LEVEL = "debug"; };
description = ''
Environment variables of PID 1. These variables are
<emphasis>not</emphasis> passed to started units.
'';
};
systemd.enableCgroupAccounting = mkOption {
default = true;
type = types.bool;
@ -352,10 +349,11 @@ in
type = types.listOf types.str;
example = [ "systemd-backlight@.service" ];
description = ''
A list of units to suppress when generating system systemd configuration directory. This has
A list of units to skip when generating system systemd configuration directory. This has
priority over upstream units, <option>systemd.units</option>, and
<option>systemd.additionalUpstreamSystemUnits</option>. The main purpose of this is to
suppress a upstream systemd unit with any modifications made to it by other NixOS modules.
prevent a upstream systemd unit from being added to the initrd with any modifications made to it
by other NixOS modules.
'';
};
@ -470,11 +468,18 @@ in
enabledUpstreamSystemUnits = filter (n: ! elem n cfg.suppressedSystemUnits) upstreamSystemUnits;
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedSystemUnits) cfg.units;
in ({
"systemd/system".source = generateUnits "system" enabledUnits enabledUpstreamSystemUnits upstreamSystemWants;
"systemd/system".source = generateUnits {
type = "system";
units = enabledUnits;
upstreamUnits = enabledUpstreamSystemUnits;
upstreamWants = upstreamSystemWants;
};
"systemd/system.conf".text = ''
[Manager]
ManagerEnvironment=${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment)}
${optionalString config.systemd.enableCgroupAccounting ''
DefaultCPUAccounting=yes
DefaultIOAccounting=yes
@ -542,6 +547,17 @@ in
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
# Environment of PID 1
systemd.managerEnvironment = {
# Doesn't contain systemd itself - everything works so it seems to use the compiled-in value for its tools
PATH = lib.makeBinPath config.system.fsPackages;
LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
TZDIR = "/etc/zoneinfo";
# If SYSTEMD_UNIT_PATH ends with an empty component (":"), the usual unit load path will be appended to the contents of the variable
SYSTEMD_UNIT_PATH = lib.mkIf (config.boot.extraSystemdUnitPaths != []) "${builtins.concatStringsSep ":" config.boot.extraSystemdUnitPaths}:";
};
system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled
[ "DEVTMPFS" "CGROUPS" "INOTIFY_USER" "SIGNALFD" "TIMERFD" "EPOLL" "NET"
"SYSFS" "PROC_FS" "FHANDLE" "CRYPTO_USER_API_HASH" "CRYPTO_HMAC"
@ -589,22 +605,18 @@ in
boot.kernelParams = optional (!cfg.enableUnifiedCgroupHierarchy) "systemd.unified_cgroup_hierarchy=0";
services.logrotate.paths = {
services.logrotate.settings = {
"/var/log/btmp" = mapAttrs (_: mkDefault) {
frequency = "monthly";
keep = 1;
extraConfig = ''
create 0660 root ${config.users.groups.utmp.name}
minsize 1M
'';
rotate = 1;
create = "0660 root ${config.users.groups.utmp.name}";
minsize = "1M";
};
"/var/log/wtmp" = mapAttrs (_: mkDefault) {
frequency = "monthly";
keep = 1;
extraConfig = ''
create 0664 root ${config.users.groups.utmp.name}
minsize 1M
'';
rotate = 1;
create = "0664 root ${config.users.groups.utmp.name}";
minsize = "1M";
};
};
};

View file

@ -0,0 +1,417 @@
{ lib, config, utils, pkgs, ... }:
with lib;
let
inherit (utils) systemdUtils escapeSystemdPath;
inherit (systemdUtils.lib)
generateUnits
pathToUnit
serviceToUnit
sliceToUnit
socketToUnit
targetToUnit
timerToUnit
mountToUnit
automountToUnit;
cfg = config.boot.initrd.systemd;
# Copied from fedora
upstreamUnits = [
"basic.target"
"ctrl-alt-del.target"
"emergency.service"
"emergency.target"
"final.target"
"halt.target"
"initrd-cleanup.service"
"initrd-fs.target"
"initrd-parse-etc.service"
"initrd-root-device.target"
"initrd-root-fs.target"
"initrd-switch-root.service"
"initrd-switch-root.target"
"initrd.target"
"initrd-udevadm-cleanup-db.service"
"kexec.target"
"kmod-static-nodes.service"
"local-fs-pre.target"
"local-fs.target"
"multi-user.target"
"paths.target"
"poweroff.target"
"reboot.target"
"rescue.service"
"rescue.target"
"rpcbind.target"
"shutdown.target"
"sigpwr.target"
"slices.target"
"sockets.target"
"swap.target"
"sysinit.target"
"sys-kernel-config.mount"
"syslog.socket"
"systemd-ask-password-console.path"
"systemd-ask-password-console.service"
"systemd-fsck@.service"
"systemd-halt.service"
"systemd-hibernate-resume@.service"
"systemd-journald-audit.socket"
"systemd-journald-dev-log.socket"
"systemd-journald.service"
"systemd-journald.socket"
"systemd-kexec.service"
"systemd-modules-load.service"
"systemd-poweroff.service"
"systemd-random-seed.service"
"systemd-reboot.service"
"systemd-sysctl.service"
"systemd-tmpfiles-setup-dev.service"
"systemd-tmpfiles-setup.service"
"systemd-udevd-control.socket"
"systemd-udevd-kernel.socket"
"systemd-udevd.service"
"systemd-udev-settle.service"
"systemd-udev-trigger.service"
"systemd-vconsole-setup.service"
"timers.target"
"umount.target"
# TODO: Networking
# "network-online.target"
# "network-pre.target"
# "network.target"
# "nss-lookup.target"
# "nss-user-lookup.target"
# "remote-fs-pre.target"
# "remote-fs.target"
] ++ cfg.additionalUpstreamUnits;
upstreamWants = [
"sysinit.target.wants"
];
enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits;
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units;
stage1Units = generateUnits {
type = "initrd";
units = enabledUnits;
upstreamUnits = enabledUpstreamUnits;
inherit upstreamWants;
inherit (cfg) packages package;
};
fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
fstab = pkgs.writeText "fstab" (lib.concatMapStringsSep "\n"
({ fsType, mountPoint, device, options, autoFormat, autoResize, ... }@fs: let
opts = options ++ optional autoFormat "x-systemd.makefs" ++ optional autoResize "x-systemd.growfs";
in "${device} /sysroot${mountPoint} ${fsType} ${lib.concatStringsSep "," opts}") fileSystems);
kernel-name = config.boot.kernelPackages.kernel.name or "kernel";
modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; };
firmware = config.hardware.firmware;
# Determine the set of modules that we need to mount the root FS.
modulesClosure = pkgs.makeModulesClosure {
rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules;
kernel = modulesTree;
firmware = firmware;
allowMissing = false;
};
initrdBinEnv = pkgs.buildEnv {
name = "initrd-emergency-env";
paths = map getBin cfg.initrdBin;
pathsToLink = ["/bin" "/sbin"];
# Make recovery easier
postBuild = ''
ln -s ${cfg.package.util-linux}/bin/mount $out/bin/
ln -s ${cfg.package.util-linux}/bin/umount $out/bin/
'';
};
initialRamdisk = pkgs.makeInitrdNG {
contents = map (path: { object = path; symlink = ""; }) (subtractLists cfg.suppressedStorePaths cfg.storePaths)
++ mapAttrsToList (_: v: { object = v.source; symlink = v.target; }) (filterAttrs (_: v: v.enable) cfg.contents);
};
in {
options.boot.initrd.systemd = {
enable = mkEnableOption ''systemd in initrd.
Note: This is in very early development and is highly
experimental. Most of the features NixOS supports in initrd are
not yet supported by the intrd generated with this option.
'';
package = (mkPackageOption pkgs "systemd" {
default = "systemdMinimal";
}) // {
visible = false;
};
contents = mkOption {
description = "Set of files that have to be linked into the initrd";
example = literalExpression ''
{
"/etc/hostname".text = "mymachine";
}
'';
visible = false;
default = {};
type = types.attrsOf (types.submodule ({ config, options, name, ... }: {
options = {
enable = mkEnableOption "copying of this file to initrd and symlinking it" // { default = true; };
target = mkOption {
type = types.path;
description = ''
Path of the symlink.
'';
default = name;
};
text = mkOption {
default = null;
type = types.nullOr types.lines;
description = "Text of the file.";
};
source = mkOption {
type = types.path;
description = "Path of the source file.";
};
};
config = {
source = mkIf (config.text != null) (
let name' = "initrd-" + baseNameOf name;
in mkDerivedConfig options.text (pkgs.writeText name')
);
};
}));
};
storePaths = mkOption {
description = ''
Store paths to copy into the initrd as well.
'';
type = types.listOf types.singleLineStr;
default = [];
};
suppressedStorePaths = mkOption {
description = ''
Store paths specified in the storePaths option that
should not be copied.
'';
type = types.listOf types.singleLineStr;
default = [];
};
emergencyAccess = mkOption {
type = with types; oneOf [ bool singleLineStr ];
visible = false;
description = ''
Set to true for unauthenticated emergency access, and false for
no emergency access.
Can also be set to a hashed super user password to allow
authenticated access to the emergency mode.
'';
default = false;
};
initrdBin = mkOption {
type = types.listOf types.package;
default = [];
visible = false;
description = ''
Packages to include in /bin for the stage 1 emergency shell.
'';
};
additionalUpstreamUnits = mkOption {
default = [ ];
type = types.listOf types.str;
visible = false;
example = [ "debug-shell.service" "systemd-quotacheck.service" ];
description = ''
Additional units shipped with systemd that shall be enabled.
'';
};
suppressedUnits = mkOption {
default = [ ];
type = types.listOf types.str;
example = [ "systemd-backlight@.service" ];
visible = false;
description = ''
A list of units to skip when generating system systemd configuration directory. This has
priority over upstream units, <option>boot.initrd.systemd.units</option>, and
<option>boot.initrd.systemd.additionalUpstreamUnits</option>. The main purpose of this is to
prevent a upstream systemd unit from being added to the initrd with any modifications made to it
by other NixOS modules.
'';
};
units = mkOption {
description = "Definition of systemd units.";
default = {};
visible = false;
type = systemdUtils.types.units;
};
packages = mkOption {
default = [];
visible = false;
type = types.listOf types.package;
example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
description = "Packages providing systemd units and hooks.";
};
targets = mkOption {
default = {};
visible = false;
type = systemdUtils.types.initrdTargets;
description = "Definition of systemd target units.";
};
services = mkOption {
default = {};
type = systemdUtils.types.initrdServices;
visible = false;
description = "Definition of systemd service units.";
};
sockets = mkOption {
default = {};
type = systemdUtils.types.initrdSockets;
visible = false;
description = "Definition of systemd socket units.";
};
timers = mkOption {
default = {};
type = systemdUtils.types.initrdTimers;
visible = false;
description = "Definition of systemd timer units.";
};
paths = mkOption {
default = {};
type = systemdUtils.types.initrdPaths;
visible = false;
description = "Definition of systemd path units.";
};
mounts = mkOption {
default = [];
type = systemdUtils.types.initrdMounts;
visible = false;
description = ''
Definition of systemd mount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
the 'where' attribute.
'';
};
automounts = mkOption {
default = [];
type = systemdUtils.types.automounts;
visible = false;
description = ''
Definition of systemd automount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
the 'where' attribute.
'';
};
slices = mkOption {
default = {};
type = systemdUtils.types.slices;
visible = false;
description = "Definition of slice configurations.";
};
};
config = mkIf (config.boot.initrd.enable && cfg.enable) {
system.build = { inherit initialRamdisk; };
boot.initrd.systemd = {
initrdBin = [pkgs.bash pkgs.coreutils pkgs.kmod cfg.package] ++ config.system.fsPackages;
contents = {
"/init".source = "${cfg.package}/lib/systemd/systemd";
"/etc/systemd/system".source = stage1Units;
"/etc/systemd/system.conf".text = ''
[Manager]
DefaultEnvironment=PATH=/bin:/sbin
'';
"/etc/fstab".source = fstab;
"/lib/modules".source = "${modulesClosure}/lib/modules";
"/etc/modules-load.d/nixos.conf".text = concatStringsSep "\n" config.boot.initrd.kernelModules;
"/etc/passwd".source = "${pkgs.fakeNss}/etc/passwd";
"/etc/shadow".text = "root:${if isBool cfg.emergencyAccess then "!" else cfg.emergencyAccess}:::::::";
"/bin".source = "${initrdBinEnv}/bin";
"/sbin".source = "${initrdBinEnv}/sbin";
"/etc/sysctl.d/nixos.conf".text = "kernel.modprobe = /sbin/modprobe";
};
storePaths = [
# TODO: Limit this to the bare necessities
"${cfg.package}/lib"
"${cfg.package.util-linux}/bin/mount"
"${cfg.package.util-linux}/bin/umount"
"${cfg.package.util-linux}/bin/sulogin"
# so NSS can look up usernames
"${pkgs.glibc}/lib/libnss_files.so"
];
targets.initrd.aliases = ["default.target"];
units =
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers
// listToAttrs (map
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts)
// listToAttrs (map
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
services.emergency = mkIf (isBool cfg.emergencyAccess && cfg.emergencyAccess) {
environment.SYSTEMD_SULOGIN_FORCE = "1";
};
# The unit in /run/systemd/generator shadows the unit in
# /etc/systemd/system, but will still apply drop-ins from
# /etc/systemd/system/foo.service.d/
#
# We need IgnoreOnIsolate, otherwise the Requires dependency of
# a mount unit on its makefs unit causes it to be unmounted when
# we isolate for switch-root. Use a dummy package so that
# generateUnits will generate drop-ins instead of unit files.
packages = [(pkgs.runCommand "dummy" {} ''
mkdir -p $out/etc/systemd/system
touch $out/etc/systemd/system/systemd-{makefs,growfs}@.service
'')];
services."systemd-makefs@".unitConfig.IgnoreOnIsolate = true;
services."systemd-growfs@".unitConfig.IgnoreOnIsolate = true;
};
};
}

View file

@ -116,7 +116,13 @@ in {
in
mkMerge [
(mkIf (cfg != {}) {
environment.etc."systemd/nspawn".source = mkIf (cfg != {}) (generateUnits' false "nspawn" units [] []);
environment.etc."systemd/nspawn".source = mkIf (cfg != {}) (generateUnits {
allowCollisions = false;
type = "nspawn";
inherit units;
upstreamUnits = [];
upstreamWants = [];
});
})
{
systemd.targets.multi-user.wants = [ "machines.target" ];

View file

@ -100,5 +100,21 @@ in
'';
})
];
systemd.tmpfiles.rules = [
"d /nix/var 0755 root root - -"
"L+ /nix/var/nix/gcroots/booted-system 0755 root root - /run/booted-system"
"d /run/lock 0755 root root - -"
"d /var/db 0755 root root - -"
"L /etc/mtab - - - - ../proc/mounts"
"L /var/lock - - - - ../run/lock"
# Boot-time cleanup
"R! /etc/group.lock - - - - -"
"R! /etc/passwd.lock - - - - -"
"R! /etc/shadow.lock - - - - -"
"R! /etc/mtab* - - - - -"
"R! /nix/var/nix/gcroots/tmp - - - - -"
"R! /nix/var/nix/temproots - - - - -"
];
};
}

View file

@ -12,10 +12,6 @@ let
(systemdUtils.lib)
makeUnit
generateUnits
makeJobScript
unitConfig
serviceConfig
commonUnitText
targetToUnit
serviceToUnit
socketToUnit
@ -57,48 +53,42 @@ in {
systemd.user.units = mkOption {
description = "Definition of systemd per-user units.";
default = {};
type = with types; attrsOf (submodule (
{ name, config, ... }:
{ options = concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
}));
type = systemdUtils.types.units;
};
systemd.user.paths = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
type = systemdUtils.types.paths;
description = "Definition of systemd per-user path units.";
};
systemd.user.services = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ] );
type = systemdUtils.types.services;
description = "Definition of systemd per-user service units.";
};
systemd.user.slices = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = sliceOptions; } unitConfig ] );
type = systemdUtils.types.slices;
description = "Definition of systemd per-user slice units.";
};
systemd.user.sockets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ] );
type = systemdUtils.types.sockets;
description = "Definition of systemd per-user socket units.";
};
systemd.user.targets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig] );
type = systemdUtils.types.targets;
description = "Definition of systemd per-user target units.";
};
systemd.user.timers = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ] );
type = systemdUtils.types.timers;
description = "Definition of systemd per-user timer units.";
};
@ -119,7 +109,12 @@ in {
];
environment.etc = {
"systemd/user".source = generateUnits "user" cfg.units upstreamUserUnits [];
"systemd/user".source = generateUnits {
type = "user";
inherit (cfg) units;
upstreamUnits = upstreamUserUnits;
upstreamWants = [];
};
"systemd/user.conf".text = ''
[Manager]

View file

@ -90,7 +90,7 @@ in {
example = "45min";
description = ''
Add a randomized delay before each automatic upgrade.
The delay will be chozen between zero and this value.
The delay will be chosen between zero and this value.
This value must be a time span in the format specified by
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry>

View file

@ -352,7 +352,7 @@ in
unitConfig.DefaultDependencies = false; # needed to prevent a cycle
serviceConfig.Type = "oneshot";
};
in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems)) // {
in listToAttrs (map formatDevice (filter (fs: fs.autoFormat && !(utils.fsNeededForBoot fs)) fileSystems)) // {
# Mount /sys/fs/pstore for evacuating panic logs and crashdumps from persistent storage onto the disk using systemd-pstore.
# This cannot be done with the other special filesystems because the pstore module (which creates the mount point) is not loaded then.
"mount-pstore" = {

View file

@ -146,15 +146,11 @@ in
services.logrotate = {
enable = true;
extraConfig = ''
/var/log/waagent.log {
compress
monthly
rotate 6
notifempty
missingok
}
'';
settings."/var/log/waagent.log" = {
compress = true;
frequency = "monthly";
rotate = 6;
};
};
systemd.targets.provisioned = {

View file

@ -6,7 +6,10 @@ let
inherit (lib) mkOption types;
podmanPackage = (pkgs.podman.override { inherit (cfg) extraPackages; });
podmanPackage = (pkgs.podman.override {
extraPackages = cfg.extraPackages
++ lib.optional (builtins.elem "zfs" config.boot.supportedFilesystems) config.boot.zfs.package;
});
# Provides a fake "docker" binary mapping to podman
dockerCompat = pkgs.runCommand "${podmanPackage.pname}-docker-compat-${podmanPackage.version}" {

View file

@ -923,6 +923,8 @@ in
mkVMOverride (cfg.fileSystems //
{
"/".device = cfg.bootDevice;
"/".fsType = "ext4";
"/".autoFormat = true;
"/tmp" = mkIf config.boot.tmpOnTmpfs
{ device = "tmpfs";
@ -953,6 +955,28 @@ in
};
} // lib.mapAttrs' mkSharedDir cfg.sharedDirectories);
boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) {
mounts = [{
where = "/sysroot/nix/store";
what = "overlay";
type = "overlay";
options = "lowerdir=/sysroot/nix/.ro-store,upperdir=/sysroot/nix/.rw-store/store,workdir=/sysroot/nix/.rw-store/work";
wantedBy = ["local-fs.target"];
before = ["local-fs.target"];
requires = ["sysroot-nix-.ro\\x2dstore.mount" "sysroot-nix-.rw\\x2dstore.mount" "rw-store.service"];
after = ["sysroot-nix-.ro\\x2dstore.mount" "sysroot-nix-.rw\\x2dstore.mount" "rw-store.service"];
unitConfig.IgnoreOnIsolate = true;
}];
services.rw-store = {
after = ["sysroot-nix-.rw\\x2dstore.mount"];
unitConfig.DefaultDependencies = false;
serviceConfig = {
Type = "oneshot";
ExecStart = "/bin/mkdir -p 0755 /sysroot/nix/.rw-store/store /sysroot/nix/.rw-store/work /sysroot/nix/store";
};
};
};
swapDevices = mkVMOverride [ ];
boot.initrd.luks.devices = mkVMOverride {};
@ -961,7 +985,10 @@ in
services.qemuGuest.enable = cfg.qemu.guestAgent.enable;
system.build.vm = pkgs.runCommand "nixos-vm" { preferLocalBuild = true; }
system.build.vm = pkgs.runCommand "nixos-vm" {
preferLocalBuild = true;
meta.mainProgram = "run-${config.system.name}-vm";
}
''
mkdir -p $out/bin
ln -s ${config.system.build.toplevel} $out/system

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
maintainers = with lib.maintainers; [ veehaitch ];
};
machine = { lib, ... }: {
nodes.machine = { lib, ... }: {
services.aesmd = {
enable = true;
settings = {

View file

@ -15,7 +15,7 @@ in
maintainers = [ alexarice turion ];
};
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
environment.systemPackages = [
(pkgs.agda.withPackages {
pkgs = p: [ p.standard-library ];

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
maintainers = [ sumnerevans ];
};
machine =
nodes.machine =
{ pkgs, ... }:
{
services.airsonic = {

View file

@ -281,6 +281,7 @@ in
#logstash = handleTest ./logstash.nix {};
lorri = handleTest ./lorri/default.nix {};
maddy = handleTest ./maddy.nix {};
maestral = handleTest ./maestral.nix {};
magic-wormhole-mailbox-server = handleTest ./magic-wormhole-mailbox-server.nix {};
magnetico = handleTest ./magnetico.nix {};
mailcatcher = handleTest ./mailcatcher.nix {};
@ -315,6 +316,7 @@ in
moosefs = handleTest ./moosefs.nix {};
mpd = handleTest ./mpd.nix {};
mpv = handleTest ./mpv.nix {};
mtp = handleTest ./mtp.nix {};
mumble = handleTest ./mumble.nix {};
musescore = handleTest ./musescore.nix {};
munin = handleTest ./munin.nix {};
@ -341,6 +343,7 @@ in
networking.networkd = handleTest ./networking.nix { networkd = true; };
networking.scripted = handleTest ./networking.nix { networkd = false; };
specialisation = handleTest ./specialisation.nix {};
netbox = handleTest ./web-apps/netbox.nix {};
# TODO: put in networking.nix after the test becomes more complete
networkingProxy = handleTest ./networking-proxy.nix {};
nextcloud = handleTest ./nextcloud {};
@ -512,6 +515,7 @@ in
systemd-confinement = handleTest ./systemd-confinement.nix {};
systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {};
systemd-escaping = handleTest ./systemd-escaping.nix {};
systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {};
systemd-journal = handleTest ./systemd-journal.nix {};
systemd-machinectl = handleTest ./systemd-machinectl.nix {};
systemd-networkd = handleTest ./systemd-networkd.nix {};
@ -591,5 +595,6 @@ in
zigbee2mqtt = handleTest ./zigbee2mqtt.nix {};
zoneminder = handleTest ./zoneminder.nix {};
zookeeper = handleTest ./zookeeper.nix {};
zrepl = handleTest ./zrepl.nix {};
zsh-history = handleTest ./zsh-history.nix {};
}

View file

@ -18,7 +18,7 @@ makeTest {
meta = with maintainers; {
maintainers = [ urbas ];
};
machine = { ... }:
nodes.machine = { ... }:
{
imports = [ ../modules/profiles/headless.nix ../modules/virtualisation/amazon-init.nix ];
services.openssh.enable = true;

View file

@ -2,7 +2,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
name = "apfs";
meta.maintainers = with pkgs.lib.maintainers; [ Luflosi ];
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
virtualisation.emptyDiskImages = [ 1024 ];
boot.supportedFilesystems = [ "apfs" ];

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix ({ pkgs, ... } : {
maintainers = [ julm ];
};
machine =
nodes.machine =
{ lib, pkgs, config, ... }:
with lib;
{

View file

@ -6,7 +6,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
maintainers = [ bjornfor ];
};
machine =
nodes.machine =
{ ... }:
{ services.atd.enable = true;
users.users.alice = { isNormalUser = true; };

View file

@ -107,7 +107,7 @@ in
{
justThePackage = makeTest {
name = "atop-justThePackage";
machine = {
nodes.machine = {
environment.systemPackages = [ pkgs.atop ];
};
testScript = with assertions; builtins.concatStringsSep "\n" [
@ -123,7 +123,7 @@ in
};
defaults = makeTest {
name = "atop-defaults";
machine = {
nodes.machine = {
programs.atop = {
enable = true;
};
@ -141,7 +141,7 @@ in
};
minimal = makeTest {
name = "atop-minimal";
machine = {
nodes.machine = {
programs.atop = {
enable = true;
atopService.enable = false;
@ -162,7 +162,7 @@ in
};
netatop = makeTest {
name = "atop-netatop";
machine = {
nodes.machine = {
programs.atop = {
enable = true;
netatop.enable = true;
@ -181,7 +181,7 @@ in
};
atopgpu = makeTest {
name = "atop-atopgpu";
machine = {
nodes.machine = {
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (getName pkg) [
"cudatoolkit"
];
@ -204,7 +204,7 @@ in
};
everything = makeTest {
name = "atop-everthing";
machine = {
nodes.machine = {
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (getName pkg) [
"cudatoolkit"
];

View file

@ -2,7 +2,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
name = "bcachefs";
meta.maintainers = with pkgs.lib.maintainers; [ chiiruno ];
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
virtualisation.emptyDiskImages = [ 4096 ];
networking.hostId = "deadbeef";
boot.supportedFilesystems = [ "bcachefs" ];

View file

@ -28,7 +28,7 @@ in
name = "beanstalkd";
meta.maintainers = [ lib.maintainers.aanderse ];
machine =
nodes.machine =
{ ... }:
{ services.beanstalkd.enable = true;
};

View file

@ -2,7 +2,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }:
{
name = "bees";
machine = { config, pkgs, ... }: {
nodes.machine = { config, pkgs, ... }: {
boot.initrd.postDeviceCommands = ''
${pkgs.btrfs-progs}/bin/mkfs.btrfs -f -L aux1 /dev/vdb
${pkgs.btrfs-progs}/bin/mkfs.btrfs -f -L aux2 /dev/vdc

View file

@ -1,7 +1,7 @@
import ./make-test-python.nix {
name = "bind";
machine = { pkgs, lib, ... }: {
nodes.machine = { pkgs, lib, ... }: {
services.bind.enable = true;
services.bind.extraOptions = "empty-zones-enable no;";
services.bind.zones = lib.singleton {

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
maintainers = with maintainers; [ _1000101 ];
};
machine = { ... }: {
nodes.machine = { ... }: {
services.bitcoind."mainnet" = {
enable = true;
rpc = {

View file

@ -4,7 +4,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
maintainers = with maintainers; [ _1000101 ];
};
machine = { ... }: {
nodes.machine = { ... }: {
services.blockbook-frontend."test" = {
enable = true;
};

View file

@ -1,7 +1,7 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "boot-stage1";
machine = { config, pkgs, lib, ... }: {
nodes.machine = { config, pkgs, lib, ... }: {
boot.extraModulePackages = let
compileKernelModule = name: source: pkgs.runCommandCC name rec {
inherit source;

View file

@ -6,6 +6,10 @@ import ./make-test-python.nix ({ pkgs, lib, ...} :
nodes = {
machine = { config, ... }: {
networking.extraHosts = ''
127.0.0.1 all.api.radio-browser.info
'';
services.murmur = {
enable = true;
registerName = "NixOS tests";

View file

@ -2,7 +2,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
name = "bpf";
meta.maintainers = with pkgs.lib.maintainers; [ martinetd ];
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
programs.bcc.enable = true;
environment.systemPackages = with pkgs; [ bpftrace ];
};

View file

@ -2,7 +2,7 @@ import ./make-test-python.nix ({ lib, ... }: {
name = "breitbandmessung";
meta.maintainers = with lib.maintainers; [ b4dm4n ];
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
imports = [
./common/user-account.nix
./common/x11.nix

View file

@ -7,7 +7,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
maintainers = [ mattchrist ];
};
machine = { pkgs, ... }:
nodes.machine = { pkgs, ... }:
{
nixpkgs.config.allowUnfree = true;
hardware.sane = {

View file

@ -6,7 +6,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
maintainers = [ flokli ];
};
machine = { pkgs, ... }: {
nodes.machine = { pkgs, ... }: {
services.buildkite-agents = {
one = {
privateSshKeyPath = (import ./ssh-keys.nix pkgs).snakeOilPrivateKey;

View file

@ -6,7 +6,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
maintainers = [ matthewbauer ];
};
machine = { ... }:
nodes.machine = { ... }:
{
imports = [ ./common/user-account.nix ];

View file

@ -13,7 +13,7 @@ in
maintainers = [ berbiche ];
};
machine = { config, ... }:
nodes.machine = { config, ... }:
let
alice = config.users.users.alice;
in {

View file

@ -1,7 +1,7 @@
import ./make-test-python.nix ({ pkgs, ...} : {
name = "cfssl";
machine = { config, lib, pkgs, ... }:
nodes.machine = { config, lib, pkgs, ... }:
{
networking.firewall.allowedTCPPorts = [ config.services.cfssl.port ];

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