Project import generated by Copybara.

GitOrigin-RevId: 988cc958c57ce4350ec248d2d53087777f9e1949
This commit is contained in:
Default email 2023-02-22 11:55:15 +01:00
parent ffe3f91058
commit 5557ff764c
1009 changed files with 35449 additions and 25368 deletions

View file

@ -95,3 +95,9 @@ trim_trailing_whitespace = unset
[pkgs/tools/misc/timidity/timidity.cfg]
trim_trailing_whitespace = unset
[pkgs/tools/virtualization/ovftool/*.ova]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
charset = unset

View file

@ -75,7 +75,7 @@ in pkgs.runCommand "doc-support" {}
ln -s ${epub-xsl} ./epub.xsl
ln -s ${xhtml-xsl} ./xhtml.xsl
ln -s ${../../nixos/doc/xmlformat.conf} ./xmlformat.conf
ln -s ${./xmlformat.conf} ./xmlformat.conf
ln -s ${pkgs.documentation-highlighter} ./highlightjs
echo -n "${version}" > ./version

View file

@ -137,7 +137,12 @@ set the default version to a version older than the newest on Hackage. We do
this to get them or their reverse dependencies to compile in our package set.
4. For all packages, for which the newest Hackage version is not the default
version, there will also be a `haskellPackages.foo_x_y_z` package with the
newest version.
newest version. The `x_y_z` part encodes the version with dots replaced by
underscores. When the newest version changes by a new release to Hackage the
old package will disappear under that name and be replaced by a newer one under
the name with the new version. The package name including the version will
also disappear when the default version e.g. from Stackage catches up with the
newest version from Hackage.
5. For some packages, we also manually add other `haskellPackages.foo_x_y_z`
versions, if they are required for a certain build.
@ -161,12 +166,14 @@ given in the `.cabal` file of your package and all its dependencies.
The [Haskell builder in nixpkgs](#haskell-mkderivation) does no such thing.
It will simply take as input packages with names off the desired dependencies
and just check whether they fulfill the version bounds and (by default, see
`jailbreak`) fail if they dont.
and just check whether they fulfill the version bounds and fail if they dont
(by default, see `jailbreak` to circumvent this).
The package resolution is done by the `haskellPackages.callPackage` function
which will, e.g., use `haskellPackages.aeson` for a package input of name
`aeson`.
The `haskellPackages.callPackage` function does the package resolution.
It will, e.g., use `haskellPackages.aeson`which has the default version as
described above for a package input of name `aeson`. (More general:
`<packages>.callPackage f` will call `f` with named inputs provided from the
package set `<packages>`.)
While this is the default behavior, it is possible to override the dependencies
for a specific package, see
[`override` and `overrideScope`](#haskell-overriding-haskell-packages).

View file

@ -95,6 +95,27 @@ installPhase() {
genericBuild
```
### Building a `stdenv` package in `nix-shell` {#sec-building-stdenv-package-in-nix-shell}
To build a `stdenv` package in a [`nix-shell`](https://nixos.org/manual/nix/unstable/command-ref/nix-shell.html), use
```bash
nix-shell '<nixpkgs>' -A some_package
eval ${unpackPhase:-unpackPhase}
cd $sourceRoot
eval ${patchPhase:-patchPhase}
eval ${configurePhase:-configurePhase}
eval ${buildPhase:-buildPhase}
```
To modify a [phase](#sec-stdenv-phases), first print it with
```bash
type buildPhase
```
then change it in a text editor, and paste it back to the terminal.
## Tools provided by `stdenv` {#sec-tools-of-stdenv}
The standard environment provides the following packages:

View file

@ -337,19 +337,17 @@ rec {
# Helper functions.
/* Convert an option, described as a list of the option parts in to a
safe, human readable version.
/* Convert an option, described as a list of the option parts to a
human-readable version.
Example:
(showOption ["foo" "bar" "baz"]) == "foo.bar.baz"
(showOption ["foo" "bar.baz" "tux"]) == "foo.bar.baz.tux"
(showOption ["foo" "bar.baz" "tux"]) == "foo.\"bar.baz\".tux"
(showOption ["windowManager" "2bwm" "enable"]) == "windowManager.\"2bwm\".enable"
Placeholders will not be quoted as they are not actual values:
(showOption ["foo" "*" "bar"]) == "foo.*.bar"
(showOption ["foo" "<name>" "bar"]) == "foo.<name>.bar"
Unlike attributes, options can also start with numbers:
(showOption ["windowManager" "2bwm" "enable"]) == "windowManager.2bwm.enable"
*/
showOption = parts: let
escapeOptionPart = part:

View file

@ -1417,6 +1417,12 @@
githubId = 12958979;
name = "Mika Naylor";
};
avakhrenev = {
email = "avakhrenev@gmail.com";
github = "avakhrenev";
githubId = 1060224;
name = "Alexey Vakhrenev";
};
avaq = {
email = "nixpkgs@account.avaq.it";
github = "Avaq";
@ -2461,6 +2467,12 @@
githubId = 3471749;
name = "Claudio Bley";
};
cbrewster = {
email = "cbrewster@hey.com";
github = "cbrewster";
githubId = 9086315;
name = "Connor Brewster";
};
cburstedde = {
email = "burstedde@ins.uni-bonn.de";
github = "cburstedde";
@ -3398,6 +3410,12 @@
githubId = 6754950;
name = "David Armstrong Lewis";
};
davidcromp = {
email = "davidcrompton1192@gmail.com";
github = "DavidCromp";
githubId = 10701143;
name = "David Crompton";
};
davidrusu = {
email = "davidrusu.me@gmail.com";
github = "davidrusu";
@ -3756,12 +3774,6 @@
githubId = 14034137;
name = "Mostly Void";
};
dizfer = {
email = "david@izquierdofernandez.com";
github = "DIzFer";
githubId = 8852888;
name = "David Izquierdo";
};
djacu = {
email = "daniel.n.baker@gmail.com";
github = "djacu";
@ -5912,6 +5924,15 @@
githubId = 41522204;
name = "hexchen";
};
heyimnova = {
email = "git@heyimnova.dev";
github = "heyimnova";
githubId = 115728866;
name = "Nova Witterick";
keys = [{
fingerprint = "4304 6B43 8D83 078E 3DF7 10D6 DEB0 E15C 6D2A 5A7C";
}];
};
hh = {
email = "hh@m-labs.hk";
github = "HarryMakes";
@ -7293,6 +7314,12 @@
github = "jorsn";
githubId = 4646725;
};
joshniemela = {
name = "Joshua Niemelä";
email = "josh@jniemela.dk";
github = "joshniemela";
githubId = 88747315;
};
joshuafern = {
name = "Joshua Fern";
email = "joshuafern@protonmail.com";
@ -8573,6 +8600,12 @@
githubId = 22085373;
name = "Luis Hebendanz";
};
luizirber = {
email = "nixpkgs@luizirber.org";
github = "luizirber";
githubId = 6642;
name = "Luiz Irber";
};
luizribeiro = {
email = "nixpkgs@l9o.dev";
matrix = "@luizribeiro:matrix.org";
@ -9177,6 +9210,12 @@
githubId = 952712;
name = "Matt Christ";
};
matthew-levan = {
email = "matthew@coeli.network";
github = "matthew-levan";
githubId = 91502660;
name = "Matthew LeVan";
};
matthewcroughan = {
email = "matt@croughan.sh";
github = "MatthewCroughan";
@ -11317,6 +11356,12 @@
githubId = 15645854;
name = "Brad Christensen";
};
paveloom = {
email = "paveloom@riseup.net";
github = "paveloom";
githubId = 49961859;
name = "Pavel Sobolev";
};
payas = {
email = "relekarpayas@gmail.com";
github = "bhankas";
@ -14915,7 +14960,7 @@
};
toastal = {
email = "toastal+nix@posteo.net";
matrix = "@toastal:chat.mozilla.org";
matrix = "@toastal:mozilla.org";
github = "toastal";
githubId = 561087;
name = "toastal";

View file

@ -66,6 +66,28 @@ let
if !builtins.isList files then [ files ] else files
);
packageSetsWithVersionedHead = pkgs.haskell.packages // (
let
headSet = pkgs.haskell.packages.ghcHEAD;
# Determine the next GHC release version following GHC HEAD.
# GHC HEAD always has an uneven, tentative version number, e.g. 9.7.
# GHC releases always have even numbers, i.e. GHC 9.8 is branched off from
# GHC HEAD 9.7. Since we use the to be release number for GHC HEAD's
# configuration file, we need to calculate this here.
headVersion = lib.pipe headSet.ghc.version [
lib.versions.splitVersion
(lib.take 2)
lib.concatStrings
lib.strings.toInt
(builtins.add 1)
toString
];
in
{
"ghc${headVersion}" = headSet;
}
);
setsForFile = fileName:
let
# extract the unique part of the config's file name
@ -77,12 +99,12 @@ let
builtins.match "ghc-([0-9]+).([0-9]+).x" configName
);
# return all package sets under haskell.packages matching the version components
setsForVersion = builtins.map (name: pkgs.haskell.packages.${name}) (
setsForVersion = builtins.map (name: packageSetsWithVersionedHead.${name}) (
builtins.filter (setName:
lib.hasPrefix "ghc${configVersion}" setName
&& (skipBinaryGHCs -> !(lib.hasInfix "Binary" setName))
) (
builtins.attrNames pkgs.haskell.packages
builtins.attrNames packageSetsWithVersionedHead
)
);

View file

@ -63,11 +63,13 @@ sed -r \
-e '/ lsp-test /d' \
-e '/ hie-bios /d' \
-e '/ ShellCheck /d' \
-e '/ Agda /d' \
< "${tmpfile_new}" >> $stackage_config
# Explanations:
# cabal2nix, distribution-nixpkgs, jailbreak-cabal, language-nix: These are our packages and we know what we are doing.
# lsp, lsp-types, lsp-test, hie-bios: These are tightly coupled to hls which is not in stackage. They have no rdeps in stackage.
# ShellCheck: latest version of command-line dev tool.
# Agda: The Agda community is fast-moving; we strive to always include the newest versions of Agda and the Agda packages in nixpkgs.
if [[ "${1:-}" == "--do-commit" ]]; then
git add $stackage_config

View file

@ -1,2 +0,0 @@
generated
manual-combined.xml

View file

@ -1,30 +0,0 @@
.PHONY: all
all: manual-combined.xml
.PHONY: debug
debug: generated manual-combined.xml
manual-combined.xml: generated *.xml **/*.xml
rm -f ./manual-combined.xml
nix-shell --pure -Q --packages xmloscopy \
--run "xmloscopy --docbook5 ./manual.xml ./manual-combined.xml"
.PHONY: format
format:
nix-shell --pure -Q --packages xmlformat \
--run "find ../../ -iname '*.xml' -type f -print0 | xargs -0 -I{} -n1 \
xmlformat --config-file '../xmlformat.conf' -i {}"
.PHONY: fix-misc-xml
fix-misc-xml:
find . -iname '*.xml' -type f \
-exec ../varlistentry-fixer.rb {} ';'
.PHONY: clean
clean:
rm -f manual-combined.xml generated
generated:
nix-build ../../release.nix \
--attr manualGeneratedSources.x86_64-linux \
--out-link ./generated

View file

@ -21,8 +21,8 @@ which is often not what you want. By contrast, in the imperative
approach, containers are configured and updated independently from the
host system.
```{=docbook}
<xi:include href="imperative-containers.section.xml" />
<xi:include href="declarative-containers.section.xml" />
<xi:include href="container-networking.section.xml" />
```{=include=} sections
imperative-containers.section.md
declarative-containers.section.md
container-networking.section.md
```

View file

@ -0,0 +1,14 @@
# Administration {#ch-running}
This chapter describes various aspects of managing a running NixOS system, such as how to use the {command}`systemd` service manager.
```{=include=} chapters
service-mgmt.chapter.md
rebooting.chapter.md
user-sessions.chapter.md
control-groups.chapter.md
logging.chapter.md
cleaning-store.chapter.md
containers.chapter.md
troubleshooting.chapter.md
```

View file

@ -1,21 +0,0 @@
<part xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-running">
<title>Administration</title>
<partintro xml:id="ch-running-intro">
<para>
This chapter describes various aspects of managing a running NixOS system,
such as how to use the <command>systemd</command> service manager.
</para>
</partintro>
<xi:include href="../from_md/administration/service-mgmt.chapter.xml" />
<xi:include href="../from_md/administration/rebooting.chapter.xml" />
<xi:include href="../from_md/administration/user-sessions.chapter.xml" />
<xi:include href="../from_md/administration/control-groups.chapter.xml" />
<xi:include href="../from_md/administration/logging.chapter.xml" />
<xi:include href="../from_md/administration/cleaning-store.chapter.xml" />
<xi:include href="../from_md/administration/containers.chapter.xml" />
<xi:include href="../from_md/administration/troubleshooting.chapter.xml" />
</part>

View file

@ -3,10 +3,10 @@
This chapter describes solutions to common problems you might encounter
when you manage your NixOS system.
```{=docbook}
<xi:include href="boot-problems.section.xml" />
<xi:include href="maintenance-mode.section.xml" />
<xi:include href="rollback.section.xml" />
<xi:include href="store-corruption.section.xml" />
<xi:include href="network-problems.section.xml" />
```{=include=} sections
boot-problems.section.md
maintenance-mode.section.md
rollback.section.md
store-corruption.section.md
network-problems.section.md
```

View file

@ -11,8 +11,8 @@ manual](https://nixos.org/nix/manual/#chap-writing-nix-expressions), but
here we give a short overview of the most important constructs useful in
NixOS configuration files.
```{=docbook}
<xi:include href="config-file.section.xml" />
<xi:include href="abstractions.section.xml" />
<xi:include href="modularity.section.xml" />
```{=include=} sections
config-file.section.md
abstractions.section.md
modularity.section.md
```

View file

@ -0,0 +1,27 @@
# Configuration {#ch-configuration}
This chapter describes how to configure various aspects of a NixOS machine through the configuration file {file}`/etc/nixos/configuration.nix`. As described in [](#sec-changing-config), changes to this file only take effect after you run {command}`nixos-rebuild`.
```{=include=} chapters
config-syntax.chapter.md
package-mgmt.chapter.md
user-mgmt.chapter.md
file-systems.chapter.md
x-windows.chapter.md
wayland.chapter.md
gpu-accel.chapter.md
xfce.chapter.md
networking.chapter.md
linux-kernel.chapter.md
subversion.chapter.md
```
```{=include=} chapters
@MODULE_CHAPTERS@
```
```{=include=} chapters
profiles.chapter.md
kubernetes.chapter.md
```
<!-- Apache; libvirtd virtualisation -->

View file

@ -1,31 +0,0 @@
<part xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-configuration">
<title>Configuration</title>
<partintro xml:id="ch-configuration-intro">
<para>
This chapter describes how to configure various aspects of a NixOS machine
through the configuration file
<filename>/etc/nixos/configuration.nix</filename>. As described in
<xref linkend="sec-changing-config" />, changes to this file only take
effect after you run <command>nixos-rebuild</command>.
</para>
</partintro>
<xi:include href="../from_md/configuration/config-syntax.chapter.xml" />
<xi:include href="../from_md/configuration/package-mgmt.chapter.xml" />
<xi:include href="../from_md/configuration/user-mgmt.chapter.xml" />
<xi:include href="../from_md/configuration/file-systems.chapter.xml" />
<xi:include href="../from_md/configuration/x-windows.chapter.xml" />
<xi:include href="../from_md/configuration/wayland.chapter.xml" />
<xi:include href="../from_md/configuration/gpu-accel.chapter.xml" />
<xi:include href="../from_md/configuration/xfce.chapter.xml" />
<xi:include href="../from_md/configuration/networking.chapter.xml" />
<xi:include href="../from_md/configuration/linux-kernel.chapter.xml" />
<xi:include href="../from_md/configuration/subversion.chapter.xml" />
<xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" />
<xi:include href="../from_md/configuration/profiles.chapter.xml" />
<xi:include href="../from_md/configuration/kubernetes.chapter.xml" />
<!-- Apache; libvirtd virtualisation -->
</part>

View file

@ -40,7 +40,7 @@ configuration use `pkgs` prefix (variable).
To "uninstall" a package, simply remove it from
[](#opt-environment.systemPackages) and run `nixos-rebuild switch`.
```{=docbook}
<xi:include href="customizing-packages.section.xml" />
<xi:include href="adding-custom-packages.section.xml" />
```{=include=} sections
customizing-packages.section.md
adding-custom-packages.section.md
```

View file

@ -36,7 +36,7 @@ dropping you to the emergency shell. You can make a mount asynchronous
and non-critical by adding `options = [ "nofail" ];`.
:::
```{=docbook}
<xi:include href="luks-file-systems.section.xml" />
<xi:include href="sshfs-file-systems.section.xml" />
```{=include=} sections
luks-file-systems.section.md
sshfs-file-systems.section.md
```

View file

@ -3,14 +3,14 @@
This section describes how to configure networking components
on your NixOS machine.
```{=docbook}
<xi:include href="network-manager.section.xml" />
<xi:include href="ssh.section.xml" />
<xi:include href="ipv4-config.section.xml" />
<xi:include href="ipv6-config.section.xml" />
<xi:include href="firewall.section.xml" />
<xi:include href="wireless.section.xml" />
<xi:include href="ad-hoc-network-config.section.xml" />
<xi:include href="renaming-interfaces.section.xml" />
```{=include=} sections
network-manager.section.md
ssh.section.md
ipv4-config.section.md
ipv6-config.section.md
firewall.section.md
wireless.section.md
ad-hoc-network-config.section.md
renaming-interfaces.section.md
```
<!-- TODO: OpenVPN, NAT -->

View file

@ -12,7 +12,7 @@ NixOS has two distinct styles of package management:
`nix-env` command. This style allows mixing packages from different
Nixpkgs versions. It's the only choice for non-root users.
```{=docbook}
<xi:include href="declarative-packages.section.xml" />
<xi:include href="ad-hoc-packages.section.xml" />
```{=include=} sections
declarative-packages.section.md
ad-hoc-packages.section.md
```

View file

@ -19,16 +19,16 @@ install media, many are actually intended to be used in real installs.
What follows is a brief explanation on the purpose and use-case for each
profile. Detailing each option configured by each one is out of scope.
```{=docbook}
<xi:include href="profiles/all-hardware.section.xml" />
<xi:include href="profiles/base.section.xml" />
<xi:include href="profiles/clone-config.section.xml" />
<xi:include href="profiles/demo.section.xml" />
<xi:include href="profiles/docker-container.section.xml" />
<xi:include href="profiles/graphical.section.xml" />
<xi:include href="profiles/hardened.section.xml" />
<xi:include href="profiles/headless.section.xml" />
<xi:include href="profiles/installation-device.section.xml" />
<xi:include href="profiles/minimal.section.xml" />
<xi:include href="profiles/qemu-guest.section.xml" />
```{=include=} sections
profiles/all-hardware.section.md
profiles/base.section.md
profiles/clone-config.section.md
profiles/demo.section.md
profiles/docker-container.section.md
profiles/graphical.section.md
profiles/hardened.section.md
profiles/headless.section.md
profiles/installation-device.section.md
profiles/minimal.section.md
profiles/qemu-guest.section.md
```

View file

@ -68,56 +68,6 @@ let
optionIdPrefix = "test-opt-";
};
sources = runCommand "manual-sources" {
inputs = lib.sourceFilesBySuffices ./. [ ".xml" ".md" ];
nativeBuildInputs = [ pkgs.nixos-render-docs ];
} ''
mkdir $out
cd $out
cp -r --no-preserve=all $inputs/* .
declare -a convert_args
while read -r mf; do
if [[ "$mf" = *.chapter.md ]]; then
convert_args+=("--chapter")
else
convert_args+=("--section")
fi
convert_args+=("from_md/''${mf%.md}.xml" "$mf")
done < <(find . -type f -name '*.md')
nixos-render-docs manual docbook-fragment \
--manpage-urls ${manpageUrls} \
"''${convert_args[@]}"
'';
modulesDoc = runCommand "modules.xml" {
nativeBuildInputs = [ pkgs.nixos-render-docs ];
} ''
nixos-render-docs manual docbook-section \
--manpage-urls ${manpageUrls} \
"$out" \
--section \
--section-id modules \
--chapters ${lib.concatMapStrings (p: "${p.value} ") config.meta.doc}
'';
generatedSources = runCommand "generated-docbook" {} ''
mkdir $out
ln -s ${modulesDoc} $out/modules.xml
ln -s ${optionsDoc.optionsDocBook} $out/options-db.xml
ln -s ${testOptionsDoc.optionsDocBook} $out/test-options-db.xml
printf "%s" "${version}" > $out/version
'';
copySources =
''
cp -prd $sources/* . # */
ln -s ${generatedSources} ./generated
chmod -R u+w .
'';
toc = builtins.toFile "toc.xml"
''
<toc role="chunk-toc">
@ -148,70 +98,102 @@ let
"--stringparam chunk.toc ${toc}"
];
linterFunctions = ''
# outputs the context of an xmllint error output
# LEN lines around the failing line are printed
function context {
# length of context
local LEN=6
# lines to print before error line
local BEFORE=4
# xmllint output lines are:
# file.xml:1234: there was an error on line 1234
while IFS=':' read -r file line rest; do
echo
if [[ -n "$rest" ]]; then
echo "$file:$line:$rest"
local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1))
# number lines & filter context
nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p"
else
if [[ -n "$line" ]]; then
echo "$file:$line"
else
echo "$file"
fi
fi
done
}
function lintrng {
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
"$1" \
2>&1 | context 1>&2
# ^ redirect assumes xmllint doesnt print to stdout
}
'';
manual-combined = runCommand "nixos-manual-combined"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
{ inputs = lib.sourceFilesBySuffices ./. [ ".xml" ".md" ];
nativeBuildInputs = [ pkgs.nixos-render-docs pkgs.libxml2.bin pkgs.libxslt.bin ];
meta.description = "The NixOS manual as plain docbook XML";
}
''
${copySources}
cp -r --no-preserve=all $inputs/* .
xmllint --xinclude --output ./manual-combined.xml ./manual.xml
xmllint --xinclude --noxincludenode \
--output ./man-pages-combined.xml ./man-pages.xml
substituteInPlace ./manual.md \
--replace '@NIXOS_VERSION@' "${version}"
substituteInPlace ./configuration/configuration.md \
--replace \
'@MODULE_CHAPTERS@' \
${lib.escapeShellArg (lib.concatMapStringsSep "\n" (p: "${p.value}") config.meta.doc)}
substituteInPlace ./nixos-options.md \
--replace \
'@NIXOS_OPTIONS_JSON@' \
${optionsDoc.optionsJSON}/share/doc/nixos/options.json
substituteInPlace ./development/writing-nixos-tests.section.md \
--replace \
'@NIXOS_TEST_OPTIONS_JSON@' \
${testOptionsDoc.optionsJSON}/share/doc/nixos/options.json
# outputs the context of an xmllint error output
# LEN lines around the failing line are printed
function context {
# length of context
local LEN=6
# lines to print before error line
local BEFORE=4
nixos-render-docs -j $NIX_BUILD_CORES manual docbook \
--manpage-urls ${manpageUrls} \
--revision ${lib.escapeShellArg revision} \
./manual.md \
./manual-combined.xml
# xmllint output lines are:
# file.xml:1234: there was an error on line 1234
while IFS=':' read -r file line rest; do
echo
if [[ -n "$rest" ]]; then
echo "$file:$line:$rest"
local FROM=$(($line>$BEFORE ? $line - $BEFORE : 1))
# number lines & filter context
nl --body-numbering=a "$file" | sed -n "$FROM,+$LEN p"
else
if [[ -n "$line" ]]; then
echo "$file:$line"
else
echo "$file"
fi
fi
done
}
function lintrng {
xmllint --debug --noout --nonet \
--relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
"$1" \
2>&1 | context 1>&2
# ^ redirect assumes xmllint doesnt print to stdout
}
${linterFunctions}
mkdir $out
cp manual-combined.xml $out/
cp man-pages-combined.xml $out/
lintrng $out/manual-combined.xml
lintrng $out/man-pages-combined.xml
'';
manpages-combined = runCommand "nixos-manpages-combined.xml"
{ nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The NixOS manpages as plain docbook XML";
}
''
mkdir generated
cp -prd ${./man-pages.xml} man-pages.xml
ln -s ${optionsDoc.optionsDocBook} generated/options-db.xml
xmllint --xinclude --noxincludenode --output $out ./man-pages.xml
${linterFunctions}
lintrng $out
'';
in rec {
inherit generatedSources;
inherit (optionsDoc) optionsJSON optionsNix optionsDocBook optionsUsedDocbook;
# Generate the NixOS manual.
manualHTML = runCommand "nixos-manual-html"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
{ nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin ];
meta.description = "The NixOS manual in HTML format";
allowedReferences = ["out"];
}
@ -248,8 +230,7 @@ in rec {
manualHTMLIndex = "${manualHTML}/share/doc/nixos/index.html";
manualEpub = runCommand "nixos-manual-epub"
{ inherit sources;
nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin buildPackages.zip ];
{ nativeBuildInputs = [ buildPackages.libxml2.bin buildPackages.libxslt.bin buildPackages.zip ];
}
''
# Generate the epub manual.
@ -300,11 +281,11 @@ in rec {
--param man.endnotes.are.numbered 0 \
--param man.break.after.slash 1 \
${docbook_xsl_ns}/xml/xsl/docbook/manpages/docbook.xsl \
${manual-combined}/man-pages-combined.xml
${manpages-combined}
''
else ''
mkdir -p $out/share/man/man5
nixos-render-docs options manpage \
nixos-render-docs -j $NIX_BUILD_CORES options manpage \
--revision ${lib.escapeShellArg revision} \
${optionsJSON}/share/doc/nixos/options.json \
$out/share/man/man5/configuration.nix.5

View file

@ -0,0 +1,43 @@
# Developing the NixOS Test Driver {#chap-developing-the-test-driver}
The NixOS test framework is a project of its own.
It consists of roughly the following components:
- `nixos/lib/test-driver`: The Python framework that sets up the test and runs the [`testScript`](#test-opt-testScript)
- `nixos/lib/testing`: The Nix code responsible for the wiring, written using the (NixOS) Module System.
These components are exposed publicly through:
- `nixos/lib/default.nix`: The public interface that exposes the `nixos/lib/testing` entrypoint.
- `flake.nix`: Exposes the `lib.nixos`, including the public test interface.
Beyond the test driver itself, its integration into NixOS and Nixpkgs is important.
- `pkgs/top-level/all-packages.nix`: Defines the `nixosTests` attribute, used
by the package `tests` attributes and OfBorg.
- `nixos/release.nix`: Defines the `tests` attribute built by Hydra, independently, but analogous to `nixosTests`
- `nixos/release-combined.nix`: Defines which tests are channel blockers.
Finally, we have legacy entrypoints that users should move away from, but are cared for on a best effort basis.
These include `pkgs.nixosTest`, `testing-python.nix` and `make-test-python.nix`.
## Testing changes to the test framework {#sec-test-the-test-framework}
When making significant changes to the test framework, we run the tests on Hydra, to avoid disrupting the larger NixOS project.
For this, we use the `python-test-refactoring` branch in the `NixOS/nixpkgs` repository, and its [corresponding Hydra jobset](https://hydra.nixos.org/jobset/nixos/python-test-refactoring).
This branch is used as a pointer, and not as a feature branch.
1. Rebase the PR onto a recent, good evaluation of `nixos-unstable`
2. Create a baseline evaluation by force-pushing this revision of `nixos-unstable` to `python-test-refactoring`.
3. Note the evaluation number (we'll call it `<previous>`)
4. Push the PR to `python-test-refactoring` and evaluate the PR on Hydra
5. Create a comparison URL by navigating to the latest build of the PR and adding to the URL `?compare=<previous>`. This is not necessary for the evaluation that comes right after the baseline.
Review the removed tests and newly failed tests using the constructed URL; otherwise you will accidentally compare iterations of the PR instead of changes to the PR base.
As we currently have some flaky tests, newly failing tests are expected, but should be reviewed to make sure that
- The number of failures did not increase significantly.
- All failures that do occur can reasonably be assumed to fail for a different reason than the changes.

View file

@ -0,0 +1,15 @@
# Development {#ch-development}
This chapter describes how you can modify and extend NixOS.
```{=include=} chapters
sources.chapter.md
writing-modules.chapter.md
building-parts.chapter.md
bootspec.chapter.md
what-happens-during-a-system-switch.chapter.md
writing-documentation.chapter.md
nixos-tests.chapter.md
developing-the-test-driver.chapter.md
testing-installer.chapter.md
```

View file

@ -1,20 +0,0 @@
<part xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-development">
<title>Development</title>
<partintro xml:id="ch-development-intro">
<para>
This chapter describes how you can modify and extend NixOS.
</para>
</partintro>
<xi:include href="../from_md/development/sources.chapter.xml" />
<xi:include href="../from_md/development/writing-modules.chapter.xml" />
<xi:include href="../from_md/development/building-parts.chapter.xml" />
<xi:include href="../from_md/development/bootspec.chapter.xml" />
<xi:include href="../from_md/development/what-happens-during-a-system-switch.chapter.xml" />
<xi:include href="../from_md/development/writing-documentation.chapter.xml" />
<xi:include href="../from_md/development/nixos-tests.chapter.xml" />
<xi:include href="../from_md/development/testing-installer.chapter.xml" />
</part>

View file

@ -5,9 +5,9 @@ NixOS tests are kept in the directory `nixos/tests`, and are executed
(using Nix) by a testing framework that automatically starts one or more
virtual machines containing the NixOS system(s) required for the test.
```{=docbook}
<xi:include href="writing-nixos-tests.section.xml" />
<xi:include href="running-nixos-tests.section.xml" />
<xi:include href="running-nixos-tests-interactively.section.xml" />
<xi:include href="linking-nixos-tests-to-packages.section.xml" />
```{=include=} sections
writing-nixos-tests.section.md
running-nixos-tests.section.md
running-nixos-tests-interactively.section.md
linking-nixos-tests-to-packages.section.md
```

View file

@ -47,7 +47,7 @@ Most of these actions are either self-explaining but some of them have to do
with our units or the activation script. For this reason, these topics are
explained in the next sections.
```{=docbook}
<xi:include href="unit-handling.section.xml" />
<xi:include href="activation-script.section.xml" />
```{=include=} sections
unit-handling.section.md
activation-script.section.md
```

View file

@ -83,7 +83,7 @@ Keep the following guidelines in mind when you create and add a topic:
## Adding a Topic to the Book {#sec-writing-docs-adding-a-topic}
Open the parent XML file and add an `xi:include` element to the list of
Open the parent CommonMark file and add a line to the list of
chapters with the file name of the topic that you created. If you
created a `section`, you add the file to the `chapter` file. If you created
a `chapter`, you add the file to the `part` file.

View file

@ -189,14 +189,14 @@ in {
```
:::
```{=docbook}
<xi:include href="option-declarations.section.xml" />
<xi:include href="option-types.section.xml" />
<xi:include href="option-def.section.xml" />
<xi:include href="assertions.section.xml" />
<xi:include href="meta-attributes.section.xml" />
<xi:include href="importing-modules.section.xml" />
<xi:include href="replace-modules.section.xml" />
<xi:include href="freeform-modules.section.xml" />
<xi:include href="settings-options.section.xml" />
```{=include=} sections
option-declarations.section.md
option-types.section.md
option-def.section.md
assertions.section.md
meta-attributes.section.md
importing-modules.section.md
replace-modules.section.md
freeform-modules.section.md
settings-options.section.md
```

View file

@ -470,6 +470,8 @@ In that case, `numpy` is chosen from the generic `python3Packages`.
The following options can be used when writing tests.
```{=docbook}
<xi:include href="../../generated/test-options-db.xml" xpointer="test-options-list"/>
```{=include=} options
id-prefix: test-opt-
list-id: test-options-list
source: @NIXOS_TEST_OPTIONS_JSON@
```

View file

@ -0,0 +1,11 @@
# Installation {#ch-installation}
This section describes how to obtain, install, and configure NixOS for first-time use.
```{=include=} chapters
obtaining.chapter.md
installing.chapter.md
changing-config.chapter.md
upgrading.chapter.md
building-nixos.chapter.md
```

View file

@ -1,18 +0,0 @@
<part xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-installation">
<title>Installation</title>
<partintro xml:id="ch-installation-intro">
<para>
This section describes how to obtain, install, and configure NixOS for
first-time use.
</para>
</partintro>
<xi:include href="../from_md/installation/obtaining.chapter.xml" />
<xi:include href="../from_md/installation/installing.chapter.xml" />
<xi:include href="../from_md/installation/changing-config.chapter.xml" />
<xi:include href="../from_md/installation/upgrading.chapter.xml" />
<xi:include href="../from_md/installation/building-nixos.chapter.xml" />
</part>

View file

@ -602,11 +602,11 @@ With a partitioned disk.
## Additional installation notes {#sec-installation-additional-notes}
```{=docbook}
<xi:include href="installing-usb.section.xml" />
<xi:include href="installing-pxe.section.xml" />
<xi:include href="installing-kexec.section.xml" />
<xi:include href="installing-virtualbox-guest.section.xml" />
<xi:include href="installing-from-other-distro.section.xml" />
<xi:include href="installing-behind-a-proxy.section.xml" />
```{=include=} sections
installing-usb.section.md
installing-pxe.section.md
installing-kexec.section.md
installing-virtualbox-guest.section.md
installing-from-other-distro.section.md
installing-behind-a-proxy.section.md
```

View file

@ -1,31 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle><filename>configuration.nix</filename>
</refentrytitle><manvolnum>5</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><filename>configuration.nix</filename></refname>
<refpurpose>NixOS system configuration specification</refpurpose>
</refnamediv>
<refsection>
<title>Description</title>
<para>
The file <filename>/etc/nixos/configuration.nix</filename> contains the
declarative specification of your NixOS system configuration. The command
<command>nixos-rebuild</command> takes this file and realises the system
configuration specified therein.
</para>
</refsection>
<refsection>
<title>Options</title>
<para>
You can use the following options in <filename>configuration.nix</filename>.
</para>
<xi:include href="./generated/options-db.xml"
xpointer="configuration-variable-list" />
</refsection>
</refentry>

View file

@ -14,5 +14,33 @@
<copyright><year>2007-2022</year><holder>Eelco Dolstra and the Nixpkgs/NixOS contributors</holder>
</copyright>
</info>
<xi:include href="man-configuration.xml" />
<refentry>
<refmeta>
<refentrytitle><filename>configuration.nix</filename>
</refentrytitle><manvolnum>5</manvolnum>
<refmiscinfo class="source">NixOS</refmiscinfo>
<!-- <refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo> -->
</refmeta>
<refnamediv>
<refname><filename>configuration.nix</filename></refname>
<refpurpose>NixOS system configuration specification</refpurpose>
</refnamediv>
<refsection>
<title>Description</title>
<para>
The file <filename>/etc/nixos/configuration.nix</filename> contains the
declarative specification of your NixOS system configuration. The command
<command>nixos-rebuild</command> takes this file and realises the system
configuration specified therein.
</para>
</refsection>
<refsection>
<title>Options</title>
<para>
You can use the following options in <filename>configuration.nix</filename>.
</para>
<xi:include href="./generated/options-db.xml"
xpointer="configuration-variable-list" />
</refsection>
</refentry>
</reference>

View file

@ -0,0 +1,53 @@
# NixOS Manual {#book-nixos-manual}
## Version @NIXOS_VERSION@
<!--
this is the top-level structure file for the nixos manual.
the manual structure extends the nixpkgs commonmark further with include
blocks to allow better organization of input text. there are six types of
include blocks: preface, parts, chapters, sections, appendix, and options.
each type except `options`` corresponds to the docbook elements of (roughly)
the same name, and can itself can further include blocks to denote its
substructure.
non-`options`` include blocks are fenced code blocks that list a number of
files to include, in the form
```{=include=} <type>
<file-name-1>
<file-name-2>
<...>
```
`options` include blocks do not list file names but contain a list of key-value
pairs that describe the options to be included and how to convert them into
elements of the manual output type:
```{=include=} options
id-prefix: <options id prefix>
list-id: <variable list element id>
source: <path to options.json>
```
-->
```{=include=} preface
preface.md
```
```{=include=} parts
installation/installation.md
configuration/configuration.md
administration/running.md
development/development.md
```
```{=include=} chapters
contributing-to-this-manual.chapter.md
```
```{=include=} appendix
nixos-options.md
release-notes/release-notes.md
```

View file

@ -1,23 +0,0 @@
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="book-nixos-manual">
<info>
<title>NixOS Manual</title>
<subtitle>Version <xi:include href="./generated/version" parse="text" />
</subtitle>
</info>
<xi:include href="preface.xml" />
<xi:include href="installation/installation.xml" />
<xi:include href="configuration/configuration.xml" />
<xi:include href="administration/running.xml" />
<xi:include href="development/development.xml" />
<xi:include href="./from_md/contributing-to-this-manual.chapter.xml" />
<appendix xml:id="ch-options">
<title>Configuration Options</title>
<xi:include href="./generated/options-db.xml"
xpointer="configuration-variable-list" />
</appendix>
<xi:include href="release-notes/release-notes.xml" />
</book>

View file

@ -0,0 +1,7 @@
# Configuration Options {#ch-options}
```{=include=} options
id-prefix: opt-
list-id: configuration-variable-list
source: @NIXOS_OPTIONS_JSON@
```

View file

@ -0,0 +1,11 @@
# Preface {#preface}
This manual describes how to install, use and extend NixOS, a Linux distribution based on the purely functional package management system [Nix](https://nixos.org/nix), that is composed using modules and packages defined in the [Nixpkgs](https://nixos.org/nixpkgs) project.
Additional information regarding the Nix package manager and the Nixpkgs project can be found in respectively the [Nix manual](https://nixos.org/nix/manual) and the [Nixpkgs manual](https://nixos.org/nixpkgs/manual).
If you encounter problems, please report them on the [`Discourse`](https://discourse.nixos.org), the [Matrix room](https://matrix.to/#nix:nixos.org), or on the [`#nixos` channel on Libera.Chat](irc://irc.libera.chat/#nixos). Alternatively, consider [contributing to this manual](#chap-contributing). Bugs should be reported in [NixOS GitHub issue tracker](https://github.com/NixOS/nixpkgs/issues).
::: {.note}
Commands prefixed with `#` have to be run as root, either requiring to login as root user or temporarily switching to it using `sudo` for example.
:::

View file

@ -1,42 +0,0 @@
<preface xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="preface">
<title>Preface</title>
<para>
This manual describes how to install, use and extend NixOS, a Linux
distribution based on the purely functional package management system
<link xlink:href="https://nixos.org/nix">Nix</link>, that is composed
using modules and packages defined in the
<link xlink:href="https://nixos.org/nixpkgs">Nixpkgs</link> project.
</para>
<para>
Additional information regarding the Nix package manager and the Nixpkgs
project can be found in respectively the
<link xlink:href="https://nixos.org/nix/manual">Nix manual</link> and the
<link xlink:href="https://nixos.org/nixpkgs/manual">Nixpkgs manual</link>.
</para>
<para>
If you encounter problems, please report them on the
<literal
xlink:href="https://discourse.nixos.org">Discourse</literal>,
the <link
xlink:href="https://matrix.to/#nix:nixos.org">Matrix room</link>,
or on the <link
xlink:href="irc://irc.libera.chat/#nixos">
<literal>#nixos</literal> channel on Libera.Chat</link>.
Alternatively, consider <link
xlink:href="#chap-contributing">
contributing to this manual</link>. Bugs should be
reported in
<link
xlink:href="https://github.com/NixOS/nixpkgs/issues">NixOS
GitHub issue tracker</link>.
</para>
<note>
<para>
Commands prefixed with <literal>#</literal> have to be run as root, either
requiring to login as root user or temporarily switching to it using
<literal>sudo</literal> for example.
</para>
</note>
</preface>

View file

@ -0,0 +1,25 @@
# Release Notes {#ch-release-notes}
This section lists the release notes for each stable version of NixOS and current unstable revision.
```{=include=} sections
rl-2305.section.md
rl-2211.section.md
rl-2205.section.md
rl-2111.section.md
rl-2105.section.md
rl-2009.section.md
rl-2003.section.md
rl-1909.section.md
rl-1903.section.md
rl-1809.section.md
rl-1803.section.md
rl-1709.section.md
rl-1703.section.md
rl-1609.section.md
rl-1603.section.md
rl-1509.section.md
rl-1412.section.md
rl-1404.section.md
rl-1310.section.md
```

View file

@ -1,30 +0,0 @@
<appendix xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="ch-release-notes">
<title>Release Notes</title>
<para>
This section lists the release notes for each stable version of NixOS and
current unstable revision.
</para>
<xi:include href="../from_md/release-notes/rl-2305.section.xml" />
<xi:include href="../from_md/release-notes/rl-2211.section.xml" />
<xi:include href="../from_md/release-notes/rl-2205.section.xml" />
<xi:include href="../from_md/release-notes/rl-2111.section.xml" />
<xi:include href="../from_md/release-notes/rl-2105.section.xml" />
<xi:include href="../from_md/release-notes/rl-2009.section.xml" />
<xi:include href="../from_md/release-notes/rl-2003.section.xml" />
<xi:include href="../from_md/release-notes/rl-1909.section.xml" />
<xi:include href="../from_md/release-notes/rl-1903.section.xml" />
<xi:include href="../from_md/release-notes/rl-1809.section.xml" />
<xi:include href="../from_md/release-notes/rl-1803.section.xml" />
<xi:include href="../from_md/release-notes/rl-1709.section.xml" />
<xi:include href="../from_md/release-notes/rl-1703.section.xml" />
<xi:include href="../from_md/release-notes/rl-1609.section.xml" />
<xi:include href="../from_md/release-notes/rl-1603.section.xml" />
<xi:include href="../from_md/release-notes/rl-1509.section.xml" />
<xi:include href="../from_md/release-notes/rl-1412.section.xml" />
<xi:include href="../from_md/release-notes/rl-1404.section.xml" />
<xi:include href="../from_md/release-notes/rl-1310.section.xml" />
</appendix>

View file

@ -40,8 +40,12 @@ In addition to numerous new and upgraded packages, this release has the followin
- [goeland](https://github.com/slurdge/goeland), an alternative to rss2email written in golang with many filters. Available as [services.goeland](#opt-services.goeland.enable).
- [tts](https://github.com/coqui-ai/TTS), a battle-tested deep learning toolkit for Text-to-Speech. Mutiple servers may be configured below [services.tts.servers](#opt-services.tts.servers).
- [atuin](https://github.com/ellie/atuin), a sync server for shell history. Available as [services.atuin](#opt-services.atuin.enable).
- [networkd-dispatcher](https://gitlab.com/craftyguy/networkd-dispatcher), a dispatcher service for systemd-networkd connection status changes. Available as [services.networkd-dispatcher](#opt-services.networkd-dispatcher.enable).
- [mmsd](https://gitlab.com/kop316/mmsd), a lower level daemon that transmits and recieves MMSes. Available as [services.mmsd](#opt-services.mmsd.enable).
- [QDMR](https://dm3mat.darc.de/qdmr/), a GUI application and command line tool for programming DMR radios [programs.qdmr](#opt-programs.qdmr.enable)

View file

@ -1,8 +0,0 @@
let
pkgs = import ../../.. { };
in
pkgs.mkShell {
name = "nixos-manual";
packages = with pkgs; [ xmlformat jing xmloscopy ruby ];
}

View file

@ -1,124 +0,0 @@
#!/usr/bin/env ruby
# This script is written intended as a living, evolving tooling
# to fix oopsies within the docbook documentation.
#
# This is *not* a formatter. It, instead, handles some known cases
# where something bad happened, and fixing it manually is tedious.
#
# Read the code to see the different cases it handles.
#
# ALWAYS `make format` after fixing with this!
# ALWAYS read the changes, this tool isn't yet proven to be always right.
require "rexml/document"
include REXML
if ARGV.length < 1 then
$stderr.puts "Needs a filename."
exit 1
end
filename = ARGV.shift
doc = Document.new(File.open(filename))
$touched = false
# Fixing varnames having a sibling element without spacing.
# This is to fix an initial `xmlformat` issue where `term`
# would mangle as spaces.
#
# <varlistentry>
# <term><varname>types.separatedString</varname><replaceable>sep</replaceable> <----
# </term>
# ...
#
# Generates: types.separatedStringsep
# ^^^^
#
# <varlistentry xml:id='fun-makeWrapper'>
# <term>
# <function>makeWrapper</function><replaceable>executable</replaceable><replaceable>wrapperfile</replaceable><replaceable>args</replaceable> <----
# </term>
#
# Generates: makeWrapperexecutablewrapperfileargs
# ^^^^ ^^^^ ^^ ^^
#
# <term>
# <option>--option</option><replaceable>name</replaceable><replaceable>value</replaceable> <-----
# </term>
#
# Generates: --optionnamevalue
# ^^ ^^
doc.elements.each("//varlistentry/term") do |term|
["varname", "function", "option", "replaceable"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
# <cmdsynopsis>
# <command>nixos-option</command>
# <arg>
# <option>-I</option><replaceable>path</replaceable> <------
# </arg>
#
# Generates: -Ipath
# ^^
doc.elements.each("//cmdsynopsis/arg") do |term|
["option", "replaceable"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
# <cmdsynopsis>
# <arg>
# <group choice='req'>
# <arg choice='plain'>
# <option>--profile-name</option>
# </arg>
#
# <arg choice='plain'>
# <option>-p</option>
# </arg>
# </group><replaceable>name</replaceable> <----
# </arg>
#
# Generates: [{--profile-name | -p }name]
# ^^^^
doc.elements.each("//cmdsynopsis/arg") do |term|
["group"].each do |prev_name|
term.elements.each(prev_name) do |el|
if el.next_element and
el.next_element.name == "replaceable" and
el.next_sibling_node.class == Element
then
$touched = true
term.insert_after(el, Text.new(" "))
end
end
end
end
if $touched then
doc.context[:attribute_quote] = :quote
doc.write(output: File.open(filename, "w"))
end

View file

@ -91,18 +91,24 @@ let
in rec {
inherit optionsNix;
optionsAsciiDoc = pkgs.runCommand "options.adoc" {} ''
${pkgs.python3Minimal}/bin/python ${./generateDoc.py} \
--format asciidoc \
optionsAsciiDoc = pkgs.runCommand "options.adoc" {
nativeBuildInputs = [ pkgs.nixos-render-docs ];
} ''
nixos-render-docs -j $NIX_BUILD_CORES options asciidoc \
--manpage-urls ${pkgs.path + "/doc/manpage-urls.json"} \
--revision ${lib.escapeShellArg revision} \
${optionsJSON}/share/doc/nixos/options.json \
> $out
$out
'';
optionsCommonMark = pkgs.runCommand "options.md" {} ''
${pkgs.python3Minimal}/bin/python ${./generateDoc.py} \
--format commonmark \
optionsCommonMark = pkgs.runCommand "options.md" {
nativeBuildInputs = [ pkgs.nixos-render-docs ];
} ''
nixos-render-docs -j $NIX_BUILD_CORES options commonmark \
--manpage-urls ${pkgs.path + "/doc/manpage-urls.json"} \
--revision ${lib.escapeShellArg revision} \
${optionsJSON}/share/doc/nixos/options.json \
> $out
$out
'';
optionsJSON = pkgs.runCommand "options.json"
@ -152,7 +158,7 @@ in rec {
pkgs.nixos-render-docs
];
} ''
nixos-render-docs options docbook \
nixos-render-docs -j $NIX_BUILD_CORES options docbook \
--manpage-urls ${pkgs.path + "/doc/manpage-urls.json"} \
--revision ${lib.escapeShellArg revision} \
--document-type ${lib.escapeShellArg documentType} \

View file

@ -1,112 +0,0 @@
import argparse
import json
import sys
formats = ['commonmark', 'asciidoc']
parser = argparse.ArgumentParser(
description = 'Generate documentation for a set of JSON-formatted NixOS options'
)
parser.add_argument(
'nix_options_path',
help = 'a path to a JSON file containing the NixOS options'
)
parser.add_argument(
'-f',
'--format',
choices = formats,
required = True,
help = f'the documentation format to generate'
)
args = parser.parse_args()
class OptionsEncoder(json.JSONEncoder):
def encode(self, obj):
# Unpack literal expressions and other Nix types.
# Don't escape the strings: they were escaped when initially serialized to JSON.
if isinstance(obj, dict):
_type = obj.get('_type')
if _type is not None:
if _type == 'literalExpression' or _type == 'literalDocBook':
return obj['text']
if _type == 'derivation':
return obj['name']
raise Exception(f'Unexpected type `{_type}` in {json.dumps(obj)}')
return super().encode(obj)
def generate_commonmark(options):
for (name, value) in options.items():
print('##', name.replace('<', '&lt;').replace('>', '&gt;'))
print(value['description'])
print()
if 'type' in value:
print('*_Type_*')
print ('```')
print(value['type'])
print ('```')
print()
print()
if 'default' in value:
print('*_Default_*')
print('```')
print(json.dumps(value['default'], cls=OptionsEncoder, ensure_ascii=False, separators=(',', ':')))
print('```')
print()
print()
if 'example' in value:
print('*_Example_*')
print('```')
print(json.dumps(value['example'], cls=OptionsEncoder, ensure_ascii=False, separators=(',', ':')))
print('```')
print()
print()
# TODO: declarations: link to github
def generate_asciidoc(options):
for (name, value) in options.items():
print(f'== {name}')
print()
print(value['description'])
print()
print('[discrete]')
print('=== details')
print()
print(f'Type:: {value["type"]}')
if 'default' in value:
print('Default::')
print('+')
print('----')
print(json.dumps(value['default'], cls=OptionsEncoder, ensure_ascii=False, separators=(',', ':')))
print('----')
print()
else:
print('No Default:: {blank}')
if value['readOnly']:
print('Read Only:: {blank}')
else:
print()
if 'example' in value:
print('Example::')
print('+')
print('----')
print(json.dumps(value['example'], cls=OptionsEncoder, ensure_ascii=False, separators=(',', ':')))
print('----')
print()
else:
print('No Example:: {blank}')
print()
with open(args.nix_options_path) as nix_options_json:
options = json.load(nix_options_json)
if args.format == 'commonmark':
generate_commonmark(options)
elif args.format == 'asciidoc':
generate_asciidoc(options)
else:
raise Exception(f'Unsupported documentation format `--format {args.format}`')

View file

@ -22,7 +22,7 @@ in
};
timeout = lib.mkOption {
type = types.nullOr types.int;
default = null; # NOTE: null values are filtered out by `meta`.
default = 3600; # 1 hour
description = mdDoc ''
The [{option}`test`](#test-opt-test)'s [`meta.timeout`](https://nixos.org/manual/nixpkgs/stable/#var-meta-timeout) in seconds.
'';

View file

@ -168,7 +168,6 @@ in
"${config.boot.initrd.systemd.package.kbd}/bin/setfont"
"${config.boot.initrd.systemd.package.kbd}/bin/loadkeys"
"${config.boot.initrd.systemd.package.kbd.gzip}/bin/gzip" # Fonts and keyboard layouts are compressed
"${config.boot.initrd.systemd.package.kbd.gzip}/bin/.gzip-wrapped"
] ++ optionals (hasPrefix builtins.storeDir cfg.font) [
"${cfg.font}"
] ++ optionals (hasPrefix builtins.storeDir cfg.keyMap) [

View file

@ -67,6 +67,7 @@ with lib;
stoken = super.stoken.override { withGTK3 = false; };
# translateManpages -> perlPackages.po4a -> texlive-combined-basic -> texlive-core-big -> libX11
util-linux = super.util-linux.override { translateManpages = false; };
vim-full = super.vim-full.override { guiSupport = false; };
zbar = super.zbar.override { enableVideo = false; withXorg = false; };
}));
};

View file

@ -65,8 +65,6 @@ in {
] ++ optional pkgs.stdenv.hostPlatform.isAarch raspberrypiWirelessFirmware
++ optionals (versionOlder config.boot.kernelPackages.kernel.version "4.13") [
rtl8723bs-firmware
] ++ optionals (versionOlder config.boot.kernelPackages.kernel.version "5.16") [
rtw89-firmware
];
hardware.wirelessRegulatoryDatabase = true;
})

View file

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.hardware.flipperzero;
in
{
options.hardware.flipperzero.enable = mkEnableOption (mdDoc "udev rules and software for Flipper Zero devices");
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.qFlipper ];
services.udev.packages = [ pkgs.qFlipper ];
};
}

View file

@ -392,7 +392,7 @@ in
tape = 25;
video = 26;
dialout = 27;
#polkituser = 28; # currently unused, polkitd doesn't need a group
polkituser = 28;
utmp = 29;
# ddclient = 30; # converted to DynamicUser = true
davfs2 = 31;

View file

@ -53,6 +53,7 @@
./hardware/cpu/intel-sgx.nix
./hardware/device-tree.nix
./hardware/digitalbitbox.nix
./hardware/flipperzero.nix
./hardware/flirc.nix
./hardware/gkraken.nix
./hardware/gpgsmartcards.nix
@ -314,6 +315,7 @@
./services/audio/snapserver.nix
./services/audio/spotifyd.nix
./services/audio/squeezelite.nix
./services/audio/tts.nix
./services/audio/ympd.nix
./services/backup/automysqlbackup.nix
./services/backup/bacula.nix
@ -912,6 +914,7 @@
./services/networking/ndppd.nix
./services/networking/nebula.nix
./services/networking/netbird.nix
./services/networking/networkd-dispatcher.nix
./services/networking/networkmanager.nix
./services/networking/nextdns.nix
./services/networking/nftables.nix

View file

@ -22,6 +22,5 @@ in
config = mkIf cfg.enable {
services.udev.packages = [ cfg.package ];
environment.systemPackages = [ cfg.package ];
users.groups.flashrom = { };
};
}

View file

@ -113,7 +113,7 @@ in
group = "polkituser";
};
users.groups.polkituser = {};
users.groups.polkituser.gid = config.ids.gids.polkituser;
};
}

View file

@ -0,0 +1,151 @@
{ config
, lib
, pkgs
, ...
}:
let
cfg = config.services.tts;
in
{
options.services.tts = let
inherit (lib) literalExpression mkOption mdDoc mkEnableOption types;
in {
servers = mkOption {
type = types.attrsOf (types.submodule (
{ ... }: {
options = {
enable = mkEnableOption (mdDoc "Coqui TTS server");
port = mkOption {
type = types.port;
example = 5000;
description = mdDoc ''
Port to bind the TTS server to.
'';
};
model = mkOption {
type = types.nullOr types.str;
default = "tts_models/en/ljspeech/tacotron2-DDC";
example = null;
description = mdDoc ''
Name of the model to download and use for speech synthesis.
Check `tts-server --list_models` for possible values.
Set to `null` to use a custom model.
'';
};
useCuda = mkOption {
type = types.bool;
default = false;
example = true;
description = mdDoc ''
Whether to offload computation onto a CUDA compatible GPU.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
description = mdDoc ''
Extra arguments to pass to the server commandline.
'';
};
};
}
));
default = {};
example = literalExpression ''
{
english = {
port = 5300;
model = "tts_models/en/ljspeech/tacotron2-DDC";
};
german = {
port = 5301;
model = "tts_models/de/thorsten/tacotron2-DDC";
};
dutch = {
port = 5302;
model = "tts_models/nl/mai/tacotron2-DDC";
};
}
'';
description = mdDoc ''
TTS server instances.
'';
};
};
config = let
inherit (lib) mkIf mapAttrs' nameValuePair optionalString concatMapStringsSep escapeShellArgs;
in mkIf (cfg.servers != {}) {
systemd.services = mapAttrs' (server: options:
nameValuePair "tts-${server}" {
description = "Coqui TTS server instance ${server}";
after = [
"network-online.target"
];
wantedBy = [
"multi-user.target"
];
path = with pkgs; [
espeak-ng
];
environment.HOME = "/var/lib/tts";
serviceConfig = {
DynamicUser = true;
User = "tts";
StateDirectory = "tts";
ExecStart = "${pkgs.tts}/bin/tts-server --port ${toString options.port}"
+ optionalString (options.model != null) " --model_name ${options.model}"
+ optionalString (options.useCuda) " --use_cuda"
+ (concatMapStringsSep " " escapeShellArgs options.extraArgs);
CapabilityBoundingSet = "";
DeviceAllow = if options.useCuda then [
# https://docs.nvidia.com/dgx/pdf/dgx-os-5-user-guide.pdf
"/dev/nvidia1"
"/dev/nvidia2"
"/dev/nvidia3"
"/dev/nvidia4"
"/dev/nvidia-caps/nvidia-cap1"
"/dev/nvidia-caps/nvidia-cap2"
"/dev/nvidiactl"
"/dev/nvidia-modeset"
"/dev/nvidia-uvm"
"/dev/nvidia-uvm-tools"
] else "";
DevicePolicy = "closed";
LockPersonality = true;
# jit via numba->llvmpipe
MemoryDenyWriteExecute = false;
PrivateDevices = true;
PrivateUsers = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
ProtectProc = "invisible";
ProcSubset = "pid";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
UMask = "0077";
};
}) cfg.servers;
};
}

View file

@ -128,7 +128,7 @@ To backup your home directory to borgbase you have to:
- Initialize the repository on the server. Eg.
sudo borg init --encryption=repokey-blake2 \
-rsh "ssh -i /run/keys/id_ed25519_borgbase" \
--rsh "ssh -i /run/keys/id_ed25519_borgbase" \
zzz2aaaaa@zzz2aaaaa.repo.borgbase.com:repo
- Add it to your NixOS configuration, e.g.

View file

@ -34,7 +34,7 @@ let
text = if (cfg.configFile != null) then ''
cp ${cfg.configFile} ${configPath}
# make config file readable by service
chown -R --reference=$HOME $(dirname ${configPath})
chown -R --reference="$HOME" "$(dirname ${configPath})"
'' else ''
export CONFIG_FILE=${configPath}

View file

@ -8,19 +8,9 @@ let
keyboard = {
options = {
devices = mkOption {
type = types.addCheck (types.listOf types.str)
(devices: (length devices) > 0);
type = types.listOf types.str;
example = [ "/dev/input/by-id/usb-0000_0000-event-kbd" ];
# TODO replace note with tip, which has not been implemented yet in
# nixos/lib/make-options-doc/mergeJSON.py
description = mdDoc ''
Paths to keyboard devices.
::: {.note}
To avoid unnecessary triggers of the service unit, unplug devices in
the order of the list.
:::
'';
description = mdDoc "Paths to keyboard devices.";
};
config = mkOption {
type = types.lines;
@ -44,8 +34,10 @@ let
cap (tap-hold 100 100 caps lctl))
'';
description = mdDoc ''
Configuration other than `defcfg`. See [example config
files](https://github.com/jtroo/kanata) for more information.
Configuration other than `defcfg`.
See [example config files](https://github.com/jtroo/kanata)
for more information.
'';
};
extraDefCfg = mkOption {
@ -53,8 +45,12 @@ let
default = "";
example = "danger-enable-cmd yes";
description = mdDoc ''
Configuration of `defcfg` other than `linux-dev`. See [example
config files](https://github.com/jtroo/kanata) for more information.
Configuration of `defcfg` other than `linux-dev` (generated
from the devices option) and
`linux-continue-if-no-devs-found` (hardcoded to be yes).
See [example config files](https://github.com/jtroo/kanata)
for more information.
'';
};
extraArgs = mkOption {
@ -67,8 +63,7 @@ let
default = null;
example = 6666;
description = mdDoc ''
Port to run the notification server on. `null` will not run the
server.
Port to run the TCP server on. `null` will not run the server.
'';
};
};
@ -76,28 +71,23 @@ let
mkName = name: "kanata-${name}";
mkDevices = devices: concatStringsSep ":" devices;
mkDevices = devices:
optionalString ((length devices) > 0) "linux-dev ${concatStringsSep ":" devices}";
mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" ''
(defcfg
${keyboard.extraDefCfg}
linux-dev ${mkDevices keyboard.devices})
${mkDevices keyboard.devices}
linux-continue-if-no-devs-found yes)
${keyboard.config}
'';
mkService = name: keyboard: nameValuePair (mkName name) {
description = "kanata for ${mkDevices keyboard.devices}";
# Because path units are used to activate service units, which
# will start the old stopped services during "nixos-rebuild
# switch", stopIfChanged here is a workaround to make sure new
# services are running after "nixos-rebuild switch".
stopIfChanged = false;
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = ''
${cfg.package}/bin/kanata \
${getExe cfg.package} \
--cfg ${mkConfig name keyboard} \
--symlink-path ''${RUNTIME_DIRECTORY}/${name} \
${optionalString (keyboard.port != null) "--port ${toString keyboard.port}"} \
@ -146,37 +136,10 @@ let
UMask = "0077";
};
};
mkPathName = i: name: "${mkName name}-${toString i}";
mkPath = name: n: i: device:
nameValuePair (mkPathName i name) {
description =
"${toString (i+1)}/${toString n} kanata trigger for ${name}, watching ${device}";
wantedBy = optional (i == 0) "multi-user.target";
pathConfig = {
PathExists = device;
# (ab)use systemd.path to construct a trigger chain so that the
# service unit is only started when all paths exist
# however, manual of systemd.path says Unit's suffix is not ".path"
Unit =
if (i + 1) == n
then "${mkName name}.service"
else "${mkPathName (i + 1) name}.path";
};
unitConfig.StopPropagatedFrom = optional (i > 0) "${mkName name}.service";
};
mkPaths = name: keyboard:
let
n = length keyboard.devices;
in
imap0 (mkPath name n) keyboard.devices
;
in
{
options.services.kanata = {
enable = mkEnableOption (lib.mdDoc "kanata");
enable = mkEnableOption (mdDoc "kanata");
package = mkOption {
type = types.package;
default = pkgs.kanata;
@ -201,14 +164,7 @@ in
config = mkIf cfg.enable {
hardware.uinput.enable = true;
systemd = {
paths = trivial.pipe cfg.keyboards [
(mapAttrsToList mkPaths)
concatLists
listToAttrs
];
services = mapAttrs' mkService cfg.keyboards;
};
systemd.services = mapAttrs' mkService cfg.keyboards;
};
meta.maintainers = with maintainers; [ linj ];

View file

@ -409,6 +409,7 @@ in {
(optionalString (cfg.config != null) copyConfig) +
(optionalString (cfg.lovelaceConfig != null) copyLovelaceConfig)
;
environment.PYTHONPATH = package.pythonPath;
serviceConfig = let
# List of capabilities to equip home-assistant with, depending on configured components
capabilities = lib.unique ([

View file

@ -223,22 +223,59 @@ in {
'';
};
ensureAccounts = mkOption {
type = types.listOf types.str;
default = [];
description = lib.mdDoc ''
List of IMAP accounts which get automatically created. Note that for
a complete setup, user credentials for these accounts are required too
and can be created using the command `maddyctl creds`.
This option does not delete accounts which are not (anymore) listed.
'';
example = [
"user1@localhost"
"user2@localhost"
];
};
};
};
config = mkIf cfg.enable {
systemd = {
packages = [ pkgs.maddy ];
services.maddy = {
serviceConfig = {
User = cfg.user;
Group = cfg.group;
StateDirectory = [ "maddy" ];
services = {
maddy = {
serviceConfig = {
User = cfg.user;
Group = cfg.group;
StateDirectory = [ "maddy" ];
};
restartTriggers = [ config.environment.etc."maddy/maddy.conf".source ];
wantedBy = [ "multi-user.target" ];
};
restartTriggers = [ config.environment.etc."maddy/maddy.conf".source ];
wantedBy = [ "multi-user.target" ];
maddy-ensure-accounts = {
script = ''
${optionalString (cfg.ensureAccounts != []) ''
${concatMapStrings (account: ''
if ! ${pkgs.maddy}/bin/maddyctl imap-acct list | grep "${account}"; then
${pkgs.maddy}/bin/maddyctl imap-acct create ${account}
fi
'') cfg.ensureAccounts}
''}
'';
serviceConfig = {
Type = "oneshot";
User= "maddy";
};
after = [ "maddy.service" ];
wantedBy = [ "multi-user.target" ];
};
};
};
environment.etc."maddy/maddy.conf" = {

View file

@ -96,7 +96,7 @@ in {
type = types.nullOr types.path;
default = null;
description = lib.mdDoc ''
File containing environment variables to be passed to the mautrix-telegram service.
File containing environment variables to be passed to the mautrix-facebook service.
Any config variable can be overridden by setting `MAUTRIX_FACEBOOK_SOME_KEY` to override the `some.key` variable.
'';

View file

@ -137,7 +137,7 @@ in {
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ] ++ cfg.serviceDependencies;
after = [ "network-online.target" ] ++ cfg.serviceDependencies;
path = [ pkgs.lottieconverter ];
path = [ pkgs.lottieconverter pkgs.ffmpeg-full ];
# mautrix-telegram tries to generate a dotfile in the home directory of
# the running user if using a postgresql database:

View file

@ -1,5 +1,4 @@
{ config, lib, pkgs, ... }:
with lib;
let
@ -16,17 +15,19 @@ in {
type = types.package;
default = pkgs.mbpfan;
defaultText = literalExpression "pkgs.mbpfan";
description = lib.mdDoc ''
The package used for the mbpfan daemon.
'';
description = lib.mdDoc "The package used for the mbpfan daemon.";
};
verbose = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
If true, sets the log level to verbose.
'';
description = lib.mdDoc "If true, sets the log level to verbose.";
};
aggressive = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "If true, favors higher default fan speeds.";
};
settings = mkOption {
@ -35,24 +36,14 @@ in {
type = types.submodule {
freeformType = settingsFormat.type;
options.general.min_fan1_speed = mkOption {
type = types.nullOr types.int;
default = 2000;
description = lib.mdDoc ''
You can check minimum and maximum fan limits with
`cat /sys/devices/platform/applesmc.768/fan*_min` and
`cat /sys/devices/platform/applesmc.768/fan*_max` respectively.
Setting to null implies using default value from applesmc.
'';
};
options.general.low_temp = mkOption {
type = types.int;
default = 55;
default = 63;
description = lib.mdDoc "If temperature is below this, fans will run at minimum speed.";
};
options.general.high_temp = mkOption {
type = types.int;
default = 58;
default = 66;
description = lib.mdDoc "If temperature is above this, fan speed will gradually increase.";
};
options.general.max_temp = mkOption {
@ -79,10 +70,16 @@ in {
];
config = mkIf cfg.enable {
boot.kernelModules = [ "coretemp" "applesmc" ];
services.mbpfan.settings = mkIf cfg.aggressive {
general.min_fan1_speed = mkDefault 2000;
general.low_temp = mkDefault 55;
general.high_temp = mkDefault 58;
general.max_temp = mkDefault 70;
};
environment.etc."mbpfan.conf".source = settingsFile;
boot.kernelModules = [ "coretemp" "applesmc" ];
environment.systemPackages = [ cfg.package ];
environment.etc."mbpfan.conf".source = settingsFile;
systemd.services.mbpfan = {
description = "A fan manager daemon for MacBook Pro";

View file

@ -25,6 +25,13 @@ in {
Specify a configuration file that Mimir should use.
'';
};
package = mkOption {
default = pkgs.mimir;
defaultText = lib.literalExpression "pkgs.mimir";
type = types.package;
description = lib.mdDoc ''Mimir package to use.'';
};
};
config = mkIf cfg.enable {
@ -53,7 +60,7 @@ in {
else cfg.configFile;
in
{
ExecStart = "${pkgs.mimir}/bin/mimir --config.file=${conf}";
ExecStart = "${cfg.package}/bin/mimir --config.file=${conf}";
DynamicUser = true;
Restart = "always";
ProtectSystem = "full";

View file

@ -409,7 +409,7 @@ in
provision = {
enable = cfg.provision.grafana.datasource || cfg.provision.grafana.dashboard;
datasources =
datasources.settings.datasources =
let
esVersion = lib.getVersion config.services.elasticsearch.package;
in
@ -435,7 +435,7 @@ in
};
}
];
dashboards = lib.mkIf cfg.provision.grafana.dashboard [{
dashboards.settings.providers = lib.mkIf cfg.provision.grafana.dashboard [{
name = "parsedmarc";
options.path = "${pkgs.python3Packages.parsedmarc.dashboard}";
}];

View file

@ -0,0 +1,63 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.networkd-dispatcher;
in {
options = {
services.networkd-dispatcher = {
enable = mkEnableOption (mdDoc ''
Networkd-dispatcher service for systemd-networkd connection status
change. See [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions)
for usage.
'');
scriptDir = mkOption {
type = types.path;
default = "/var/lib/networkd-dispatcher";
description = mdDoc ''
This directory is used for keeping various scripts read and run by
networkd-dispatcher. See [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions)
for directory structure and script usage.
'';
};
};
};
config = mkIf cfg.enable {
systemd = {
packages = [ pkgs.networkd-dispatcher ];
services.networkd-dispatcher = {
wantedBy = [ "multi-user.target" ];
# Override existing ExecStart definition
serviceConfig.ExecStart = [
""
"${pkgs.networkd-dispatcher}/bin/networkd-dispatcher -v --script-dir ${cfg.scriptDir} $networkd_dispatcher_args"
];
};
# Directory structure required according to upstream instructions
# https://gitlab.com/craftyguy/networkd-dispatcher
tmpfiles.rules = [
"d '${cfg.scriptDir}' 0750 root root - -"
"d '${cfg.scriptDir}/routable.d' 0750 root root - -"
"d '${cfg.scriptDir}/dormant.d' 0750 root root - -"
"d '${cfg.scriptDir}/no-carrier.d' 0750 root root - -"
"d '${cfg.scriptDir}/off.d' 0750 root root - -"
"d '${cfg.scriptDir}/carrier.d' 0750 root root - -"
"d '${cfg.scriptDir}/degraded.d' 0750 root root - -"
"d '${cfg.scriptDir}/configuring.d' 0750 root root - -"
"d '${cfg.scriptDir}/configured.d' 0750 root root - -"
];
};
};
}

View file

@ -82,8 +82,8 @@ in {
};
boot.kernel.sysctl = mkIf (cfg.useRoutingFeatures == "server" || cfg.useRoutingFeatures == "both") {
"net.ipv4.conf.all.forwarding" = mkDefault true;
"net.ipv6.conf.all.forwarding" = mkDefault true;
"net.ipv4.conf.all.forwarding" = mkOverride 97 true;
"net.ipv6.conf.all.forwarding" = mkOverride 97 true;
};
networking.firewall.checkReversePath = mkIf (cfg.useRoutingFeatures == "client" || cfg.useRoutingFeatures == "both") "loose";

View file

@ -12,27 +12,38 @@ with lib;
config = mkIf config.services.v2raya.enable {
environment.systemPackages = [ pkgs.v2raya ];
systemd.services.v2raya = {
unitConfig = {
Description = "v2rayA service";
Documentation = "https://github.com/v2rayA/v2rayA/wiki";
After = [ "network.target" "nss-lookup.target" "iptables.service" "ip6tables.service" ];
Wants = [ "network.target" ];
};
systemd.services.v2raya =
let
nftablesEnabled = config.networking.nftables.enable;
iptablesServices = [
"iptables.service"
] ++ optional config.networking.enableIPv6 "ip6tables.service";
tableServices = if nftablesEnabled then [ "nftables.service" ] else iptablesServices;
in
{
unitConfig = {
Description = "v2rayA service";
Documentation = "https://github.com/v2rayA/v2rayA/wiki";
After = [
"network.target"
"nss-lookup.target"
] ++ tableServices;
Wants = [ "network.target" ];
};
serviceConfig = {
User = "root";
ExecStart = "${getExe pkgs.v2raya} --log-disable-timestamp";
Environment = [ "V2RAYA_LOG_FILE=/var/log/v2raya/v2raya.log" ];
LimitNPROC = 500;
LimitNOFILE = 1000000;
Restart = "on-failure";
Type = "simple";
};
serviceConfig = {
User = "root";
ExecStart = "${getExe pkgs.v2raya} --log-disable-timestamp";
Environment = [ "V2RAYA_LOG_FILE=/var/log/v2raya/v2raya.log" ];
LimitNPROC = 500;
LimitNOFILE = 1000000;
Restart = "on-failure";
Type = "simple";
};
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ iptables bash iproute2 ]; # required by v2rayA TProxy functionality
};
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ iptables bash iproute2 ]; # required by v2rayA TProxy functionality
};
};
meta.maintainers = with maintainers; [ elliot ];

View file

@ -615,6 +615,7 @@ in
s3_endpoint = null;
s3_http_continue_timeout = null;
s3_install_cors_rule = null;
s3_asset_cdn_url = null;
max_user_api_reqs_per_minute = 20;
max_user_api_reqs_per_day = 2880;
@ -647,6 +648,9 @@ in
multisite_config_path = "config/multisite.yml";
enable_long_polling = null;
long_polling_interval = null;
preload_link_header = false;
redirect_avatar_requests = false;
pg_force_readonly_mode = false;
};
services.redis.servers.discourse =
@ -1011,6 +1015,7 @@ in
notification_email = cfg.mail.notificationEmailAddress;
contact_email = cfg.mail.contactEmailAddress;
};
security.force_https = tlsEnabled;
email = {
manual_polling_enabled = cfg.mail.incoming.enable;
reply_by_email_enabled = cfg.mail.incoming.enable;

View file

@ -270,7 +270,7 @@ in
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${cfg.package.fhs}/bin/onlyoffice-wrapper DocService/docservice /run/onlyoffice/config";
ExecStartPre = onlyoffice-prestart;
ExecStartPre = [ onlyoffice-prestart ];
Group = "onlyoffice";
Restart = "always";
RuntimeDirectory = "onlyoffice";

View file

@ -316,11 +316,13 @@ in {
mkdir -p -m 0755 /run/binfmt
${lib.concatStringsSep "\n" (lib.mapAttrsToList activationSnippet config.boot.binfmt.registrations)}
'';
systemd.additionalUpstreamSystemUnits = lib.mkIf (config.boot.binfmt.registrations != {}) [
"proc-sys-fs-binfmt_misc.automount"
"proc-sys-fs-binfmt_misc.mount"
"systemd-binfmt.service"
];
systemd.services.systemd-binfmt.restartTriggers = [ (builtins.toJSON config.boot.binfmt.registrations) ];
systemd = lib.mkIf (config.boot.binfmt.registrations != {}) {
additionalUpstreamSystemUnits = [
"proc-sys-fs-binfmt_misc.automount"
"proc-sys-fs-binfmt_misc.mount"
"systemd-binfmt.service"
];
services.systemd-binfmt.restartTriggers = [ (builtins.toJSON config.boot.binfmt.registrations) ];
};
};
}

View file

@ -427,9 +427,6 @@ in {
# fido2 support
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"
"${pkgs.libfido2}/lib/libfido2.so.1"
# the unwrapped systemd-cryptsetup executable
"${cfg.package}/lib/systemd/.systemd-cryptsetup-wrapped"
] ++ jobScripts;
targets.initrd.aliases = ["default.target"];

View file

@ -1,7 +1,8 @@
{ config, pkgs, lib, ... }:
let
cfg = config.boot.initrd.systemd.repart;
cfg = config.systemd.repart;
initrdCfg = config.boot.initrd.systemd.repart;
writeDefinition = name: partitionConfig: pkgs.writeText
"${name}.conf"
@ -24,45 +25,59 @@ let
'';
in
{
options.boot.initrd.systemd.repart = {
enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
options = {
boot.initrd.systemd.repart.enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
description = lib.mdDoc ''
Grow and add partitions to a partition table a boot time in the initrd.
Grow and add partitions to a partition table at boot time in the initrd.
systemd-repart only works with GPT partition tables.
To run systemd-repart after the initrd, see
`options.systemd.repart.enable`.
'';
};
partitions = lib.mkOption {
type = with lib.types; attrsOf (attrsOf (oneOf [ str int bool ]));
default = { };
example = {
"10-root" = {
Type = "root";
};
"20-home" = {
Type = "home";
SizeMinBytes = "512M";
SizeMaxBytes = "2G";
};
systemd.repart = {
enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
description = lib.mdDoc ''
Grow and add partitions to a partition table.
systemd-repart only works with GPT partition tables.
To run systemd-repart while in the initrd, see
`options.boot.initrd.systemd.repart.enable`.
'';
};
partitions = lib.mkOption {
type = with lib.types; attrsOf (attrsOf (oneOf [ str int bool ]));
default = { };
example = {
"10-root" = {
Type = "root";
};
"20-home" = {
Type = "home";
SizeMinBytes = "512M";
SizeMaxBytes = "2G";
};
};
description = lib.mdDoc ''
Specify partitions as a set of the names of the definition files as the
key and the partition configuration as its value. The partition
configuration can use all upstream options. See <link
xlink:href="https://www.freedesktop.org/software/systemd/man/repart.d.html"/>
for all available options.
'';
};
description = lib.mdDoc ''
Specify partitions as a set of the names of the definition files as the
key and the partition configuration as its value. The partition
configuration can use all upstream options. See <link
xlink:href="https://www.freedesktop.org/software/systemd/man/repart.d.html"/>
for all available options.
'';
};
};
config = lib.mkIf cfg.enable {
# Link the definitions into /etc so that they are included in the
# /nix/store of the sysroot. This also allows the user to run the
# systemd-repart binary after activation manually while automatically
# picking up the definition files.
config = lib.mkIf (cfg.enable || initrdCfg.enable) {
# Always link the definitions into /etc so that they are also included in
# the /nix/store of the sysroot during early userspace (i.e. while in the
# initrd).
environment.etc."repart.d".source = definitionsDirectory;
boot.initrd.systemd = {
boot.initrd.systemd = lib.mkIf initrdCfg.enable {
additionalUpstreamUnits = [
"systemd-repart.service"
];
@ -73,7 +88,7 @@ in
# Override defaults in upstream unit.
services.systemd-repart = {
# Unset the coniditions as they cannot be met before activation because
# Unset the conditions as they cannot be met before activation because
# the definition files are not stored in the expected locations.
unitConfig.ConditionDirectoryNotEmpty = [
" " # required to unset the previous value.
@ -97,5 +112,12 @@ in
after = [ "sysroot.mount" ];
};
};
systemd = lib.mkIf cfg.enable {
additionalUpstreamSystemUnits = [
"systemd-repart.service"
];
};
};
}

View file

@ -163,7 +163,7 @@ in
###### implementation
config = mkIf cfg.enable (mkMerge [{
boot.kernelModules = [ "bridge" "veth" ];
boot.kernelModules = [ "bridge" "veth" "br_netfilter" "xt_nat" ];
boot.kernel.sysctl = {
"net.ipv4.conf.all.forwarding" = mkOverride 98 true;
"net.ipv4.conf.default.forwarding" = mkOverride 98 true;

View file

@ -514,6 +514,7 @@ in
};
in [ extraConfig ] ++ (map (x: x.value) defs);
prefix = [ "containers" name ];
inherit (config) specialArgs;
}).config;
};
};
@ -555,6 +556,16 @@ in
'';
};
specialArgs = mkOption {
type = types.attrsOf types.unspecified;
default = {};
description = lib.mdDoc ''
A set of special arguments to be passed to NixOS modules.
This will be merged into the `specialArgs` used to evaluate
the NixOS configurations.
'';
};
ephemeral = mkOption {
type = types.bool;
default = false;

View file

@ -9,8 +9,7 @@ let
extraPackages = cfg.extraPackages
# setuid shadow
++ [ "/run/wrappers" ]
# include pkgs.zfs by default in the wrapped podman used by the module so it is cached
++ (if (builtins.elem "zfs" config.boot.supportedFilesystems) then [ config.boot.zfs.package ] else [ pkgs.zfs ]);
++ lib.optional (builtins.elem "zfs" config.boot.supportedFilesystems) config.boot.zfs.package;
});
# Provides a fake "docker" binary mapping to podman
@ -184,6 +183,10 @@ in
systemd.packages = [ cfg.package ];
systemd.services.podman.serviceConfig = {
ExecStart = [ "" "${cfg.package}/bin/podman $LOGGING system service" ];
};
systemd.services.podman-prune = {
description = "Prune podman resources";
@ -204,6 +207,10 @@ in
systemd.sockets.podman.wantedBy = [ "sockets.target" ];
systemd.sockets.podman.socketConfig.SocketGroup = "podman";
systemd.user.services.podman.serviceConfig = {
ExecStart = [ "" "${cfg.package}/bin/podman $LOGGING system service" ];
};
systemd.user.sockets.podman.wantedBy = [ "sockets.target" ];
systemd.tmpfiles.packages = [

View file

@ -144,7 +144,6 @@ in rec {
manual = manualHTML; # TODO(@oxij): remove eventually
manualEpub = (buildFromConfig ({ ... }: { }) (config: config.system.build.manual.manualEpub));
manpages = buildFromConfig ({ ... }: { }) (config: config.system.build.manual.manpages);
manualGeneratedSources = buildFromConfig ({ ... }: { }) (config: config.system.build.manual.generatedSources);
options = (buildFromConfig ({ ... }: { }) (config: config.system.build.manual.optionsJSON)).x86_64-linux;

View file

@ -368,6 +368,7 @@ in {
login = handleTest ./login.nix {};
logrotate = handleTest ./logrotate.nix {};
loki = handleTest ./loki.nix {};
luks = handleTest ./luks.nix {};
lvm2 = handleTest ./lvm2 {};
lxd = handleTest ./lxd.nix {};
lxd-nftables = handleTest ./lxd-nftables.nix {};
@ -646,6 +647,7 @@ in {
systemd-confinement = handleTest ./systemd-confinement.nix {};
systemd-coredump = handleTest ./systemd-coredump.nix {};
systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {};
systemd-credentials-tpm2 = handleTest ./systemd-credentials-tpm2.nix {};
systemd-escaping = handleTest ./systemd-escaping.nix {};
systemd-initrd-btrfs-raid = handleTest ./systemd-initrd-btrfs-raid.nix {};
systemd-initrd-luks-fido2 = handleTest ./systemd-initrd-luks-fido2.nix {};
@ -656,6 +658,7 @@ in {
systemd-initrd-shutdown = handleTest ./systemd-shutdown.nix { systemdStage1 = true; };
systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {};
systemd-initrd-swraid = handleTest ./systemd-initrd-swraid.nix {};
systemd-initrd-vconsole = handleTest ./systemd-initrd-vconsole.nix {};
systemd-journal = handleTest ./systemd-journal.nix {};
systemd-machinectl = handleTest ./systemd-machinectl.nix {};
systemd-networkd = handleTest ./systemd-networkd.nix {};

View file

@ -40,7 +40,7 @@ import ./make-test-python.nix (
networking.extraHosts = ''
127.0.0.1 ${discourseDomain}
${nodes.client.config.networking.primaryIPAddress} ${clientDomain}
${nodes.client.networking.primaryIPAddress} ${clientDomain}
'';
services.postfix = {
@ -90,7 +90,7 @@ import ./make-test-python.nix (
networking.extraHosts = ''
127.0.0.1 ${clientDomain}
${nodes.discourse.config.networking.primaryIPAddress} ${discourseDomain}
${nodes.discourse.networking.primaryIPAddress} ${discourseDomain}
'';
services.dovecot2 = {
@ -178,8 +178,8 @@ import ./make-test-python.nix (
discourse.wait_until_succeeds("curl -sS -f https://${discourseDomain}")
discourse.succeed(
"curl -sS -f https://${discourseDomain}/session/csrf -c cookie -b cookie -H 'Accept: application/json' | jq -r '\"X-CSRF-Token: \" + .csrf' > csrf_token",
"curl -sS -f https://${discourseDomain}/session -c cookie -b cookie -H @csrf_token -H 'Accept: application/json' -d 'login=${nodes.discourse.config.services.discourse.admin.username}' -d \"password=${adminPassword}\" | jq -e '.user.username == \"${nodes.discourse.config.services.discourse.admin.username}\"'",
"curl -sS -f https://${discourseDomain}/login -v -H 'Accept: application/json' -c cookie -b cookie 2>&1 | grep ${nodes.discourse.config.services.discourse.admin.username}",
"curl -sS -f https://${discourseDomain}/session -c cookie -b cookie -H @csrf_token -H 'Accept: application/json' -d 'login=${nodes.discourse.services.discourse.admin.username}' -d \"password=${adminPassword}\" | jq -e '.user.username == \"${nodes.discourse.services.discourse.admin.username}\"'",
"curl -sS -f https://${discourseDomain}/login -v -H 'Accept: application/json' -c cookie -b cookie 2>&1 | grep ${nodes.discourse.services.discourse.admin.username}",
)
client.wait_for_unit("postfix.service")

View file

@ -103,6 +103,16 @@ class ReqHandler(BaseHTTPRequestHandler):
self._send_json_ok(gen_mockuser(username=username, uid=uid, gid=uid, home_directory=f"/home/{username}", snakeoil_pubkey=SNAKEOIL_PUBLIC_KEY))
return
# we need to provide something at the groups endpoint.
# the nss module does segfault if we don't.
elif pu.path == "/computeMetadata/v1/oslogin/groups":
self._send_json_ok({
"posixGroups": [
{"name" : "demo", "gid" : 4294967295}
],
})
return
# authorize endpoint
elif pu.path == "/computeMetadata/v1/oslogin/authorize":
# is user allowed to login?

View file

@ -22,22 +22,23 @@ in {
enable = true;
inherit configDir;
# tests loading components by overriding the package
# provide dependencies through package overrides
package = (pkgs.home-assistant.override {
extraPackages = ps: with ps; [
colorama
];
extraComponents = [ "zha" ];
}).overrideAttrs (oldAttrs: {
doInstallCheck = false;
extraComponents = [
# test char-tty device allow propagation into the service
"zha"
];
});
# tests loading components from the module
# provide component dependencies explicitly from the module
extraComponents = [
"wake_on_lan"
"mqtt"
];
# test extra package passing from the module
# provide package for postgresql support
extraPackages = python3Packages: with python3Packages; [
psycopg2
];
@ -111,36 +112,38 @@ in {
};
testScript = { nodes, ... }: let
system = nodes.hass.config.system.build.toplevel;
system = nodes.hass.system.build.toplevel;
in
''
import re
import json
start_all()
# Parse the package path out of the systemd unit, as we cannot
# access the final package, that is overridden inside the module,
# by any other means.
pattern = re.compile(r"path=(?P<path>[\/a-z0-9-.]+)\/bin\/hass")
response = hass.execute("systemctl show -p ExecStart home-assistant.service")[1]
match = pattern.search(response)
assert match
package = match.group('path')
def get_journal_cursor(host) -> str:
exit, out = host.execute("journalctl -u home-assistant.service -n1 -o json-pretty --output-fields=__CURSOR")
def get_journal_cursor() -> str:
exit, out = hass.execute("journalctl -u home-assistant.service -n1 -o json-pretty --output-fields=__CURSOR")
assert exit == 0
return json.loads(out)["__CURSOR"]
def wait_for_homeassistant(host, cursor):
host.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u home-assistant.service | grep -q 'Home Assistant initialized in'")
def get_journal_since(cursor) -> str:
exit, out = hass.execute(f"journalctl --after-cursor='{cursor}' -u home-assistant.service")
assert exit == 0
return out
def get_unit_property(property) -> str:
exit, out = hass.execute(f"systemctl show --property={property} home-assistant.service")
assert exit == 0
return out
def wait_for_homeassistant(cursor):
hass.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u home-assistant.service | grep -q 'Home Assistant initialized in'")
hass.wait_for_unit("home-assistant.service")
cursor = get_journal_cursor(hass)
cursor = get_journal_cursor()
with subtest("Check that YAML configuration file is in place"):
hass.succeed("test -L ${configDir}/configuration.yaml")
@ -148,19 +151,22 @@ in {
with subtest("Check the lovelace config is copied because lovelaceConfigWritable = true"):
hass.succeed("test -f ${configDir}/ui-lovelace.yaml")
with subtest("Check extraComponents and extraPackages are considered from the package"):
hass.succeed(f"grep -q 'colorama' {package}/extra_packages")
hass.succeed(f"grep -q 'zha' {package}/extra_components")
with subtest("Check extraComponents and extraPackages are considered from the module"):
hass.succeed(f"grep -q 'psycopg2' {package}/extra_packages")
hass.succeed(f"grep -q 'wake_on_lan' {package}/extra_components")
with subtest("Check that Home Assistant's web interface and API can be reached"):
wait_for_homeassistant(hass, cursor)
wait_for_homeassistant(cursor)
hass.wait_for_open_port(8123)
hass.succeed("curl --fail http://localhost:8123/lovelace")
with subtest("Check that optional dependencies are in the PYTHONPATH"):
env = get_unit_property("Environment")
python_path = env.split("PYTHONPATH=")[1].split()[0]
for package in ["colorama", "paho-mqtt", "psycopg2"]:
assert package in python_path, f"{package} not in PYTHONPATH"
with subtest("Check that declaratively configured components get setup"):
journal = get_journal_since(cursor)
for domain in ["emulated_hue", "wake_on_lan"]:
assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
hass.wait_for_open_port(80)
hass.succeed("curl --fail http://localhost:80/description.xml")
@ -169,25 +175,28 @@ in {
hass.succeed("systemctl show -p DeviceAllow home-assistant.service | grep -q char-ttyUSB")
with subtest("Check service reloads when configuration changes"):
# store the old pid of the process
pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
cursor = get_journal_cursor(hass)
hass.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
assert pid == new_pid, "The PID of the process should not change between process reloads"
wait_for_homeassistant(hass, cursor)
pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
cursor = get_journal_cursor()
hass.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
assert pid == new_pid, "The PID of the process should not change between process reloads"
wait_for_homeassistant(cursor)
with subtest("check service restarts when package changes"):
pid = new_pid
cursor = get_journal_cursor(hass)
hass.succeed("${system}/specialisation/newFeature/bin/switch-to-configuration test")
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
assert pid != new_pid, "The PID of the process shoudl change when the HA binary changes"
wait_for_homeassistant(hass, cursor)
with subtest("Check service restarts when dependencies change"):
pid = new_pid
cursor = get_journal_cursor()
hass.succeed("${system}/specialisation/newFeature/bin/switch-to-configuration test")
new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
assert pid != new_pid, "The PID of the process should change when its PYTHONPATH changess"
wait_for_homeassistant(cursor)
with subtest("Check that new components get setup after restart"):
journal = get_journal_since(cursor)
for domain in ["esphome"]:
assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
with subtest("Check that no errors were logged"):
output_log = hass.succeed("cat ${configDir}/home-assistant.log")
assert "ERROR" not in output_log
hass.fail("journalctl -u home-assistant -o cat | grep -q ERROR")
with subtest("Check systemd unit hardening"):
hass.log(hass.succeed("systemctl cat home-assistant.service"))

View file

@ -77,6 +77,9 @@ import ../make-test-python.nix ({ pkgs, lib, k3s, ... }:
machine.succeed("k3s kubectl wait --for 'condition=Ready' pod/test")
machine.succeed("k3s kubectl delete -f ${testPodYaml}")
# regression test for #176445
machine.fail("journalctl -o cat -u k3s.service | grep 'ipset utility not found'")
machine.shutdown()
'';
})

View file

@ -4,6 +4,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
name = "keepassxc";
meta = with pkgs.lib.maintainers; {
maintainers = [ turion ];
timeout = 1800;
};
nodes.machine = { ... }:
@ -55,9 +56,12 @@ import ./make-test-python.nix ({ pkgs, ...} :
machine.sleep(5)
# Regression #163482: keepassxc did not crash
machine.succeed("ps -e | grep keepassxc")
machine.wait_for_text("foo.kdbx")
machine.wait_for_text("Open database")
machine.send_key("ret")
machine.sleep(1)
# Wait for the enter password screen to appear.
machine.wait_for_text("/home/alice/foo.kdbx")
# Click on "Browse" button to select keyfile
machine.send_key("tab")
machine.send_chars("/home/alice/foo.keyfile")

View file

@ -0,0 +1,69 @@
import ./make-test-python.nix ({ lib, pkgs, ... }: {
name = "luks";
nodes.machine = { pkgs, ... }: {
# Use systemd-boot
virtualisation = {
emptyDiskImages = [ 512 512 ];
useBootLoader = true;
useEFIBoot = true;
};
boot.loader.systemd-boot.enable = true;
boot.kernelParams = lib.mkOverride 5 [ "console=tty1" ];
environment.systemPackages = with pkgs; [ cryptsetup ];
specialisation = rec {
boot-luks.configuration = {
boot.initrd.luks.devices = lib.mkVMOverride {
# We have two disks and only type one password - key reuse is in place
cryptroot.device = "/dev/vdc";
cryptroot2.device = "/dev/vdd";
};
virtualisation.bootDevice = "/dev/mapper/cryptroot";
};
boot-luks-custom-keymap.configuration = lib.mkMerge [
boot-luks.configuration
{
console.keyMap = "neo";
}
];
};
};
enableOCR = true;
testScript = ''
# Create encrypted volume
machine.wait_for_unit("multi-user.target")
machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -")
machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdd -")
# Boot from the encrypted disk
machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf")
machine.succeed("sync")
machine.crash()
# Boot and decrypt the disk
machine.start()
machine.wait_for_text("Passphrase for")
machine.send_chars("supersecret\n")
machine.wait_for_unit("multi-user.target")
assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount")
# Boot from the encrypted disk with custom keymap
machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks-custom-keymap.conf")
machine.succeed("sync")
machine.crash()
# Boot and decrypt the disk
machine.start()
machine.wait_for_text("Passphrase for")
machine.send_chars("havfkhfrkfl\n")
machine.wait_for_unit("multi-user.target")
assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount")
'';
})

View file

@ -9,6 +9,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
hostname = "server";
primaryDomain = "server";
openFirewall = true;
ensureAccounts = [ "postmaster@server" ];
};
};
@ -50,7 +51,6 @@ import ./make-test-python.nix ({ pkgs, ... }: {
server.wait_for_open_port(587)
server.succeed("maddyctl creds create --password test postmaster@server")
server.succeed("maddyctl imap-acct create postmaster@server")
client.succeed("send-testmail")
client.succeed("test-imap")

View file

@ -3,7 +3,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
meta = {
maintainers = with lib.maintainers; [ OPNA2608 ];
# FIXME On ARM Miriway inside the VM doesn't receive keyboard inputs, why?
# Natively running Mir has problems with capturing the first registered libinput device.
# In our VM runners on ARM and on some hardware configs (my RPi4, distro-independent), this misses the keyboard.
# It can be worked around by dis- and reconnecting the affected hardware, but we can't do this in these tests.
# https://github.com/MirServer/mir/issues/2837
broken = pkgs.stdenv.hostPlatform.isAarch;
};
@ -30,6 +33,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
enable = true;
config = ''
add-wayland-extensions=all
enable-x11=
ctrl-alt=t:foot --maximized
ctrl-alt=a:env WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY=invalid alacritty --option window.startup_mode=maximized

View file

@ -1,6 +1,6 @@
import ./make-test-python.nix ({ pkgs, lib, ... }: {
name = "pass-secret-service";
meta.maintainers = with lib; [ aidalgol ];
meta.maintainers = [ lib.maintainers.aidalgol ];
nodes.machine = { nodes, pkgs, ... }:
{

View file

@ -6,7 +6,10 @@ import ../make-test-python.nix (
};
nodes = {
podman = { pkgs, ... }: {
rootful = { pkgs, ... }: {
virtualisation.podman.enable = true;
};
rootless = { pkgs, ... }: {
virtualisation.podman.enable = true;
users.users.alice = {
@ -49,101 +52,109 @@ import ../make-test-python.nix (
return f"su {user} -l -c {cmd}"
podman.wait_for_unit("sockets.target")
rootful.wait_for_unit("sockets.target")
rootless.wait_for_unit("sockets.target")
dns.wait_for_unit("sockets.target")
docker.wait_for_unit("sockets.target")
start_all()
with subtest("Run container as root with runc"):
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
podman.succeed(
rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
rootful.succeed(
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
podman.succeed("podman ps | grep sleeping")
podman.succeed("podman stop sleeping")
podman.succeed("podman rm sleeping")
rootful.succeed("podman ps | grep sleeping")
rootful.succeed("podman stop sleeping")
rootful.succeed("podman rm sleeping")
with subtest("Run container as root with crun"):
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
podman.succeed(
rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
rootful.succeed(
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
podman.succeed("podman ps | grep sleeping")
podman.succeed("podman stop sleeping")
podman.succeed("podman rm sleeping")
rootful.succeed("podman ps | grep sleeping")
rootful.succeed("podman stop sleeping")
rootful.succeed("podman rm sleeping")
with subtest("Run container as root with the default backend"):
podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
podman.succeed(
rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
rootful.succeed(
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
podman.succeed("podman ps | grep sleeping")
podman.succeed("podman stop sleeping")
podman.succeed("podman rm sleeping")
rootful.succeed("podman ps | grep sleeping")
rootful.succeed("podman stop sleeping")
rootful.succeed("podman rm sleeping")
# start systemd session for rootless
podman.succeed("loginctl enable-linger alice")
podman.succeed(su_cmd("whoami"))
podman.sleep(1)
rootless.succeed("loginctl enable-linger alice")
rootless.succeed(su_cmd("whoami"))
rootless.sleep(1)
with subtest("Run container rootless with runc"):
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
podman.succeed(
rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
rootless.succeed(
su_cmd(
"podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
)
podman.succeed(su_cmd("podman ps | grep sleeping"))
podman.succeed(su_cmd("podman stop sleeping"))
podman.succeed(su_cmd("podman rm sleeping"))
rootless.succeed(su_cmd("podman ps | grep sleeping"))
rootless.succeed(su_cmd("podman stop sleeping"))
rootless.succeed(su_cmd("podman rm sleeping"))
with subtest("Run container rootless with crun"):
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
podman.succeed(
rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
rootless.succeed(
su_cmd(
"podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
)
podman.succeed(su_cmd("podman ps | grep sleeping"))
podman.succeed(su_cmd("podman stop sleeping"))
podman.succeed(su_cmd("podman rm sleeping"))
rootless.succeed(su_cmd("podman ps | grep sleeping"))
rootless.succeed(su_cmd("podman stop sleeping"))
rootless.succeed(su_cmd("podman rm sleeping"))
with subtest("Run container rootless with the default backend"):
podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
podman.succeed(
rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
rootless.succeed(
su_cmd(
"podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
)
)
podman.succeed(su_cmd("podman ps | grep sleeping"))
podman.succeed(su_cmd("podman stop sleeping"))
podman.succeed(su_cmd("podman rm sleeping"))
rootless.succeed(su_cmd("podman ps | grep sleeping"))
rootless.succeed(su_cmd("podman stop sleeping"))
rootless.succeed(su_cmd("podman rm sleeping"))
with subtest("rootlessport"):
rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
rootless.succeed(
su_cmd(
"podman run -d -p 9000:8888 --name=rootlessport -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Testing</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8888"
)
)
rootless.succeed(su_cmd("podman ps | grep rootlessport"))
rootless.wait_until_succeeds(su_cmd("${pkgs.curl}/bin/curl localhost:9000 | grep Testing"))
rootless.succeed(su_cmd("podman stop rootlessport"))
rootless.succeed(su_cmd("podman rm rootlessport"))
with subtest("Run container with init"):
podman.succeed(
rootful.succeed(
"tar cv -C ${pkgs.pkgsStatic.busybox} . | podman import - busybox"
)
pid = podman.succeed("podman run --rm busybox readlink /proc/self").strip()
pid = rootful.succeed("podman run --rm busybox readlink /proc/self").strip()
assert pid == "1"
pid = podman.succeed("podman run --rm --init busybox readlink /proc/self").strip()
pid = rootful.succeed("podman run --rm --init busybox readlink /proc/self").strip()
assert pid == "2"
with subtest("aardvark-dns"):
dns.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
dns.succeed(
"podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Hi</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8000"
)
dns.succeed("podman ps | grep webserver")
dns.succeed("""
for i in `seq 0 120`; do
podman run --rm --name=client -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg ${pkgs.curl}/bin/curl http://webserver:8000 >/dev/console \
&& exit 0
sleep 0.5
done
exit 1
""")
dns.succeed("podman stop webserver")
dns.succeed("podman rm webserver")
dns.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
dns.succeed(
"podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Testing</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8000"
)
dns.succeed("podman ps | grep webserver")
dns.wait_until_succeeds(
"podman run --rm --name=client -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg ${pkgs.curl}/bin/curl http://webserver:8000 | grep Testing"
)
dns.succeed("podman stop webserver")
dns.succeed("podman rm webserver")
with subtest("A podman member can use the docker cli"):
docker.succeed(su_cmd("docker version"))

View file

@ -1,4 +1,4 @@
import ./make-test-python.nix ({ pkgs, ...} :
import ./make-test-python.nix ({ pkgs, lib, ...} :
let
@ -11,9 +11,9 @@ let
};
# Only allow the demo data to be used (only if it's unfreeRedistributable).
unfreePredicate = pkg: with pkgs.lib; let
unfreePredicate = pkg: with lib; let
allowPackageNames = [ "quake3-demodata" "quake3-pointrelease" ];
allowLicenses = [ pkgs.lib.licenses.unfreeRedistributable ];
allowLicenses = [ lib.licenses.unfreeRedistributable ];
in elem pkg.pname allowPackageNames &&
elem (pkg.meta.license or null) allowLicenses;
@ -31,7 +31,7 @@ in
rec {
name = "quake3";
meta = with pkgs.stdenv.lib.maintainers; {
meta = with lib.maintainers; {
maintainers = [ domenkozar eelco ];
};

View file

@ -0,0 +1,124 @@
import ./make-test-python.nix ({ lib, pkgs, system, ... }:
let
tpmSocketPath = "/tmp/swtpm-sock";
tpmDeviceModels = {
x86_64-linux = "tpm-tis";
aarch64-linux = "tpm-tis-device";
};
in
{
name = "systemd-credentials-tpm2";
meta = {
maintainers = with pkgs.lib.maintainers; [ tmarkus ];
};
nodes.machine = { pkgs, ... }: {
virtualisation = {
qemu.options = [
"-chardev socket,id=chrtpm,path=${tpmSocketPath}"
"-tpmdev emulator,id=tpm_dev_0,chardev=chrtpm"
"-device ${tpmDeviceModels.${system}},tpmdev=tpm_dev_0"
];
};
boot.initrd.availableKernelModules = [ "tpm_tis" ];
environment.systemPackages = with pkgs; [ diffutils ];
};
testScript = ''
import subprocess
from tempfile import TemporaryDirectory
# From systemd-initrd-luks-tpm2.nix
class Tpm:
def __init__(self):
self.state_dir = TemporaryDirectory()
self.start()
def start(self):
self.proc = subprocess.Popen(["${pkgs.swtpm}/bin/swtpm",
"socket",
"--tpmstate", f"dir={self.state_dir.name}",
"--ctrl", "type=unixio,path=${tpmSocketPath}",
"--tpm2",
])
# Check whether starting swtpm failed
try:
exit_code = self.proc.wait(timeout=0.2)
if exit_code is not None and exit_code != 0:
raise Exception("failed to start swtpm")
except subprocess.TimeoutExpired:
pass
"""Check whether the swtpm process exited due to an error"""
def check(self):
exit_code = self.proc.poll()
if exit_code is not None and exit_code != 0:
raise Exception("swtpm process died")
CRED_NAME = "testkey"
CRED_RAW_FILE = f"/root/{CRED_NAME}"
CRED_FILE = f"/root/{CRED_NAME}.cred"
def systemd_run(machine, cmd):
machine.log(f"Executing command (via systemd-run): \"{cmd}\"")
(status, out) = machine.execute( " ".join([
"systemd-run",
"--service-type=exec",
"--quiet",
"--wait",
"-E PATH=\"$PATH\"",
"-p StandardOutput=journal",
"-p StandardError=journal",
f"-p LoadCredentialEncrypted={CRED_NAME}:{CRED_FILE}",
f"$SHELL -c '{cmd}'"
]) )
if status != 0:
raise Exception(f"systemd_run failed (status {status})")
machine.log("systemd-run finished successfully")
tpm = Tpm()
@polling_condition
def swtpm_running():
tpm.check()
machine.wait_for_unit("multi-user.target")
with subtest("Check whether TPM device exists"):
machine.succeed("test -e /dev/tpm0")
machine.succeed("test -e /dev/tpmrm0")
with subtest("Check whether systemd-creds detects TPM2 correctly"):
cmd = "systemd-creds has-tpm2"
machine.log(f"Running \"{cmd}\"")
(status, _) = machine.execute(cmd)
# Check exit code equals 0 or 1 (1 means firmware support is missing, which is OK here)
if status != 0 and status != 1:
raise Exception("systemd-creds failed to detect TPM2")
with subtest("Encrypt credential using systemd-creds"):
machine.succeed(f"dd if=/dev/urandom of={CRED_RAW_FILE} bs=1k count=16")
machine.succeed(f"systemd-creds --with-key=host+tpm2 encrypt --name=testkey {CRED_RAW_FILE} {CRED_FILE}")
with subtest("Write provided credential and check for equality"):
CRED_OUT_FILE = f"/root/{CRED_NAME}.out"
systemd_run(machine, f"systemd-creds cat testkey > {CRED_OUT_FILE}")
machine.succeed(f"cmp --silent -- {CRED_RAW_FILE} {CRED_OUT_FILE}")
with subtest("Check whether systemd service can see credential in systemd-creds list"):
systemd_run(machine, f"systemd-creds list | grep {CRED_NAME}")
with subtest("Check whether systemd service can access credential in $CREDENTIALS_DIRECTORY"):
systemd_run(machine, f"cmp --silent -- $CREDENTIALS_DIRECTORY/{CRED_NAME} {CRED_RAW_FILE}")
'';
})

View file

@ -0,0 +1,33 @@
import ./make-test-python.nix ({ lib, pkgs, ... }: {
name = "systemd-initrd-vconsole";
nodes.machine = { pkgs, ... }: {
boot.kernelParams = [ "rd.systemd.unit=rescue.target" ];
boot.initrd.systemd = {
enable = true;
emergencyAccess = true;
};
console = {
earlySetup = true;
keyMap = "colemak";
};
};
testScript = ''
# Boot into rescue shell in initrd
machine.start()
machine.wait_for_console_text("Press Enter for maintenance")
machine.send_console("\n")
machine.wait_for_console_text("Logging in with home")
# Check keymap
machine.send_console("(printf '%s to receive text: \\n' Ready && read text && echo \"$text\") </dev/tty1\n")
machine.wait_for_console_text("Ready to receive text:")
for key in "asdfjkl;\n":
machine.send_key(key)
machine.wait_for_console_text("arstneio")
machine.send_console("systemctl poweroff\n")
'';
})

View file

@ -52,9 +52,6 @@ let
};
};
boot.initrd.systemd.enable = true;
boot.initrd.systemd.repart.enable = true;
# systemd-repart operates on disks with a partition table. The qemu module,
# however, creates separate filesystem images without a partition table, so
# we have to create a disk image manually.
@ -88,7 +85,10 @@ in
nodes.machine = { config, pkgs, ... }: {
imports = [ common ];
boot.initrd.systemd.repart.partitions = {
boot.initrd.systemd.enable = true;
boot.initrd.systemd.repart.enable = true;
systemd.repart.partitions = {
"10-root" = {
Type = "linux-generic";
};
@ -105,4 +105,30 @@ in
assert "Growing existing partition 1." in systemd_repart_logs
'';
};
after-initrd = makeTest {
name = "systemd-repart-after-initrd";
meta.maintainers = with maintainers; [ nikstur ];
nodes.machine = { config, pkgs, ... }: {
imports = [ common ];
systemd.repart.enable = true;
systemd.repart.partitions = {
"10-root" = {
Type = "linux-generic";
};
};
};
testScript = { nodes, ... }: ''
${useDiskImage nodes.machine}
machine.start()
machine.wait_for_unit("multi-user.target")
systemd_repart_logs = machine.succeed("journalctl --unit systemd-repart.service")
assert "Growing existing partition 1." in systemd_repart_logs
'';
};
}

View file

@ -19,20 +19,20 @@
stdenv.mkDerivation rec {
pname = "amberol";
version = "0.9.2";
version = "unstable-2023-01-12";
src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "World";
repo = pname;
rev = version;
hash = "sha256-L8yHKwtCAZC1myIouL0Oq3lj0QPWn5dVe0g3nkyAKI8=";
rev = "0623386c813d0d68564002324958cef7217cec7f";
hash = "sha256-nVL4ydTg4ncDCA9J9qWv+RPDC0Txr/qpo5XxIUiV0zQ=";
};
cargoDeps = rustPlatform.fetchCargoTarball {
inherit src;
name = "${pname}-${version}";
hash = "sha256-0XuWBUG37GNHRXgjz0/Vv6VSqaPG36xTj7oN0ukFIJY=";
hash = "sha256-E0ivUWD3jP/T1GOJ11grDwcF+m92I+W2a2HhZX1bCso=";
};
postPatch = ''

View file

@ -39,7 +39,7 @@ stdenv.mkDerivation rec {
meta = with lib; {
description = "Realtime modular synthesizer for ALSA";
homepage = "http://alsamodular.sourceforge.net";
homepage = "https://alsamodular.sourceforge.net";
license = licenses.gpl2;
platforms = platforms.linux;
maintainers = with maintainers; [ sjfloat ];

View file

@ -11,13 +11,13 @@
stdenv.mkDerivation rec {
pname = "ashuffle";
version = "3.13.4";
version = "3.13.6";
src = fetchFromGitHub {
owner = "joshkunz";
repo = "ashuffle";
rev = "v${version}";
sha256 = "sha256-J6NN0Rsc9Zw9gagksDlwpwEErs+4XmrGF9YHKlAE1FA=";
sha256 = "sha256-8XjLs4MI5MXvA6veCoTAj8tlYDe7YTggutO3F9eNyMM=";
fetchSubmodules = true;
};

View file

@ -32,7 +32,7 @@ stdenv.mkDerivation rec {
meta = with lib; {
description = "A range of synthesiser, electric piano and organ emulations";
homepage = "http://bristol.sourceforge.net";
homepage = "https://bristol.sourceforge.net";
license = licenses.gpl3;
platforms = ["x86_64-linux" "i686-linux"];
maintainers = [ maintainers.goibhniu ];

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