Merge staging-next into staging

This commit is contained in:
Frederik Rietdijk 2018-10-09 15:37:52 +02:00
commit bc9bd012c4
597 changed files with 14496 additions and 7862 deletions

View File

@ -20,6 +20,8 @@ under the terms of [COPYING](../COPYING), which is an MIT-like license.
(Motivation for change. Additional information.)
```
For consistency, there should not be a period at the end of the commit message.
Examples:
* nginx: init at 2.0.1

View File

@ -12,12 +12,12 @@ build daemon as so-called channels. To get channel information via git, add
```
For stability and maximum binary package support, it is recommended to maintain
custom changes on top of one of the channels, e.g. `nixos-18.03` for the latest
custom changes on top of one of the channels, e.g. `nixos-18.09` for the latest
release and `nixos-unstable` for the latest successful build of master:
```
% git remote update channels
% git rebase channels/nixos-18.03
% git rebase channels/nixos-18.09
```
For pull-requests, please rebase onto nixpkgs `master`.
@ -31,9 +31,9 @@ For pull-requests, please rebase onto nixpkgs `master`.
* [Manual (NixOS)](https://nixos.org/nixos/manual/)
* [Community maintained wiki](https://nixos.wiki/)
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for 18.03 release](https://hydra.nixos.org/jobset/nixos/release-18.03)
* [Continuous package builds for 18.09 release](https://hydra.nixos.org/jobset/nixos/release-18.09)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for 18.03 release](https://hydra.nixos.org/job/nixos/release-18.03/tested#tabs-constituents)
* [Tests for 18.09 release](https://hydra.nixos.org/job/nixos/release-18.09/tested#tabs-constituents)
Communication:

View File

@ -18,7 +18,7 @@ if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.
For more information, please see the NixOS release notes at
https://nixos.org/nixos/manual or locally at
${toString ./doc/manual/release-notes}.
${toString ./nixos/doc/manual/release-notes}.
If you need further help, see https://nixos.org/nixos/support.html
''

1
doc/.gitignore vendored
View File

@ -4,3 +4,4 @@
out
manual-full.xml
highlightjs
functions/library/locations.xml

View File

@ -19,7 +19,7 @@ fix-misc-xml:
.PHONY: clean
clean:
rm -f ${MD_TARGETS} .version manual-full.xml
rm -f ${MD_TARGETS} .version manual-full.xml functions/library/locations.xml
rm -rf ./out/ ./highlightjs
.PHONY: validate
@ -69,13 +69,17 @@ highlightjs:
cp -r "$$HIGHLIGHTJS/loader.js" highlightjs/
manual-full.xml: ${MD_TARGETS} .version *.xml
manual-full.xml: ${MD_TARGETS} .version functions/library/locations.xml *.xml **/*.xml **/**/*.xml
xmllint --nonet --xinclude --noxincludenode manual.xml --output manual-full.xml
.version:
nix-instantiate --eval \
-E '(import ../lib).version' > .version
functions/library/locations.xml:
nix-build ./lib-function-locations.nix \
--out-link ./functions/library/locations.xml
%.section.xml: %.section.md
pandoc $^ -w docbook+smart \
-f markdown+smart \

View File

@ -47,9 +47,10 @@
<para>
In Nixpkgs, these three platforms are defined as attribute sets under the
names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>, and
<literal>targetPlatform</literal>. They are always defined as attributes in
the standard environment. That means one can access them like:
names <literal>buildPlatform</literal>, <literal>hostPlatform</literal>,
and <literal>targetPlatform</literal>. They are always defined as
attributes in the standard environment. That means one can access them
like:
<programlisting>{ stdenv, fooDep, barDep, .. }: ...stdenv.buildPlatform...</programlisting>
.
</para>

View File

@ -1,6 +1,7 @@
{ pkgs ? (import ./.. { }), nixpkgs ? { }}:
let
pkgs = import ./.. { };
lib = pkgs.lib;
locationsXml = import ./lib-function-locations.nix { inherit pkgs nixpkgs; };
in
pkgs.stdenv.mkDerivation {
name = "nixpkgs-manual";
@ -29,6 +30,8 @@ pkgs.stdenv.mkDerivation {
];
postPatch = ''
rm -rf ./functions/library/locations.xml
ln -s ${locationsXml} ./functions/library/locations.xml
echo ${lib.version} > .version
'';

File diff suppressed because it is too large Load Diff

21
doc/functions/debug.xml Normal file
View File

@ -0,0 +1,21 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-debug">
<title>Debugging Nix Expressions</title>
<para>
Nix is a unityped, dynamic language, this means every value can potentially
appear anywhere. Since it is also non-strict, evaluation order and what
ultimately is evaluated might surprise you. Therefore it is important to be
able to debug nix expressions.
</para>
<para>
In the <literal>lib/debug.nix</literal> file you will find a number of
functions that help (pretty-)printing values while evaluation is runnnig. You
can even specify how deep these values should be printed recursively, and
transform them on the fly. Please consult the docstrings in
<literal>lib/debug.nix</literal> for usage information.
</para>
</section>

View File

@ -0,0 +1,564 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-dockerTools">
<title>pkgs.dockerTools</title>
<para>
<varname>pkgs.dockerTools</varname> is a set of functions for creating and
manipulating Docker images according to the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#docker-image-specification-v120">
Docker Image Specification v1.2.0 </link>. Docker itself is not used to
perform any of the operations done by these functions.
</para>
<warning>
<para>
The <varname>dockerTools</varname> API is unstable and may be subject to
backwards-incompatible changes in the future.
</para>
</warning>
<section xml:id="ssec-pkgs-dockerTools-buildImage">
<title>buildImage</title>
<para>
This function is analogous to the <command>docker build</command> command,
in that can used to build a Docker-compatible repository tarball containing
a single image with one or multiple layers. As such, the result is suitable
for being loaded in Docker with <command>docker load</command>.
</para>
<para>
The parameters of <varname>buildImage</varname> with relative example values
are described below:
</para>
<example xml:id='ex-dockerTools-buildImage'>
<title>Docker build</title>
<programlisting>
buildImage {
name = "redis"; <co xml:id='ex-dockerTools-buildImage-1' />
tag = "latest"; <co xml:id='ex-dockerTools-buildImage-2' />
fromImage = someBaseImage; <co xml:id='ex-dockerTools-buildImage-3' />
fromImageName = null; <co xml:id='ex-dockerTools-buildImage-4' />
fromImageTag = "latest"; <co xml:id='ex-dockerTools-buildImage-5' />
contents = pkgs.redis; <co xml:id='ex-dockerTools-buildImage-6' />
runAsRoot = '' <co xml:id='ex-dockerTools-buildImage-runAsRoot' />
#!${stdenv.shell}
mkdir -p /data
'';
config = { <co xml:id='ex-dockerTools-buildImage-8' />
Cmd = [ "/bin/redis-server" ];
WorkingDir = "/data";
Volumes = {
"/data" = {};
};
};
}
</programlisting>
</example>
<para>
The above example will build a Docker image <literal>redis/latest</literal>
from the given base image. Loading and running this image in Docker results
in <literal>redis-server</literal> being started automatically.
</para>
<calloutlist>
<callout arearefs='ex-dockerTools-buildImage-1'>
<para>
<varname>name</varname> specifies the name of the resulting image. This is
the only required argument for <varname>buildImage</varname>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-2'>
<para>
<varname>tag</varname> specifies the tag of the resulting image. By
default it's <literal>null</literal>, which indicates that the nix output
hash will be used as tag.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-3'>
<para>
<varname>fromImage</varname> is the repository tarball containing the base
image. It must be a valid Docker image, such as exported by
<command>docker save</command>. By default it's <literal>null</literal>,
which can be seen as equivalent to <literal>FROM scratch</literal> of a
<filename>Dockerfile</filename>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-4'>
<para>
<varname>fromImageName</varname> can be used to further specify the base
image within the repository, in case it contains multiple images. By
default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first image available in the
repository.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-5'>
<para>
<varname>fromImageTag</varname> can be used to further specify the tag of
the base image within the repository, in case an image contains multiple
tags. By default it's <literal>null</literal>, in which case
<varname>buildImage</varname> will peek the first tag available for the
base image.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-6'>
<para>
<varname>contents</varname> is a derivation that will be copied in the new
layer of the resulting image. This can be similarly seen as <command>ADD
contents/ /</command> in a <filename>Dockerfile</filename>. By default
it's <literal>null</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-runAsRoot'>
<para>
<varname>runAsRoot</varname> is a bash script that will run as root in an
environment that overlays the existing layers of the base image with the
new resulting layer, including the previously copied
<varname>contents</varname> derivation. This can be similarly seen as
<command>RUN ...</command> in a <filename>Dockerfile</filename>.
<note>
<para>
Using this parameter requires the <literal>kvm</literal> device to be
available.
</para>
</note>
</para>
</callout>
<callout arearefs='ex-dockerTools-buildImage-8'>
<para>
<varname>config</varname> is used to specify the configuration of the
containers that will be started off the built image in Docker. The
available options are listed in the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0 </link>.
</para>
</callout>
</calloutlist>
<para>
After the new layer has been created, its closure (to which
<varname>contents</varname>, <varname>config</varname> and
<varname>runAsRoot</varname> contribute) will be copied in the layer itself.
Only new dependencies that are not already in the existing layers will be
copied.
</para>
<para>
At the end of the process, only one new single layer will be produced and
added to the resulting image.
</para>
<para>
The resulting repository will only list the single image
<varname>image/tag</varname>. In the case of
<xref linkend='ex-dockerTools-buildImage'/> it would be
<varname>redis/latest</varname>.
</para>
<para>
It is possible to inspect the arguments with which an image was built using
its <varname>buildArgs</varname> attribute.
</para>
<note>
<para>
If you see errors similar to <literal>getProtocolByName: does not exist (no
such protocol name: tcp)</literal> you may need to add
<literal>pkgs.iana-etc</literal> to <varname>contents</varname>.
</para>
</note>
<note>
<para>
If you see errors similar to <literal>Error_Protocol ("certificate has
unknown CA",True,UnknownCa)</literal> you may need to add
<literal>pkgs.cacert</literal> to <varname>contents</varname>.
</para>
</note>
<example xml:id="example-pkgs-dockerTools-buildImage-creation-date">
<title>Impurely Defining a Docker Layer's Creation Date</title>
<para>
By default <function>buildImage</function> will use a static date of one
second past the UNIX Epoch. This allows <function>buildImage</function> to
produce binary reproducible images. When listing images with
<command>docker list images</command>, the newly created images will be
listed like this:
</para>
<screen><![CDATA[
$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest 08c791c7846e 48 years ago 25.2MB
]]></screen>
<para>
You can break binary reproducibility but have a sorted, meaningful
<literal>CREATED</literal> column by setting <literal>created</literal> to
<literal>now</literal>.
</para>
<programlisting><![CDATA[
pkgs.dockerTools.buildImage {
name = "hello";
tag = "latest";
created = "now";
contents = pkgs.hello;
config.Cmd = [ "/bin/hello" ];
}
]]></programlisting>
<para>
and now the Docker CLI will display a reasonable date and sort the images
as expected:
<screen><![CDATA[
$ docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest de2bf4786de6 About a minute ago 25.2MB
]]></screen>
however, the produced images will not be binary reproducible.
</para>
</example>
</section>
<section xml:id="ssec-pkgs-dockerTools-buildLayeredImage">
<title>buildLayeredImage</title>
<para>
Create a Docker image with many of the store paths being on their own layer
to improve sharing between images.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the resulting image.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>tag</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Tag of the generated image.
</para>
<para>
<emphasis>Default:</emphasis> the output path's hash
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>contents</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Top level paths in the container. Either a single derivation, or a list
of derivations.
</para>
<para>
<emphasis>Default:</emphasis> <literal>[]</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>config</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Run-time configuration of the container. A full list of the options are
available at in the
<link xlink:href="https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions">
Docker Image Specification v1.2.0 </link>.
</para>
<para>
<emphasis>Default:</emphasis> <literal>{}</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>created</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Date and time the layers were created. Follows the same
<literal>now</literal> exception supported by
<literal>buildImage</literal>.
</para>
<para>
<emphasis>Default:</emphasis> <literal>1970-01-01T00:00:01Z</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>maxLayers</varname> <emphasis>optional</emphasis>
</term>
<listitem>
<para>
Maximum number of layers to create.
</para>
<para>
<emphasis>Default:</emphasis> <literal>24</literal>
</para>
</listitem>
</varlistentry>
</variablelist>
<section xml:id="dockerTools-buildLayeredImage-arg-contents">
<title>Behavior of <varname>contents</varname> in the final image</title>
<para>
Each path directly listed in <varname>contents</varname> will have a
symlink in the root of the image.
</para>
<para>
For example:
<programlisting><![CDATA[
pkgs.dockerTools.buildLayeredImage {
name = "hello";
contents = [ pkgs.hello ];
}
]]></programlisting>
will create symlinks for all the paths in the <literal>hello</literal>
package:
<screen><![CDATA[
/bin/hello -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/bin/hello
/share/info/hello.info -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/share/info/hello.info
/share/locale/bg/LC_MESSAGES/hello.mo -> /nix/store/h1zb1padqbbb7jicsvkmrym3r6snphxg-hello-2.10/share/locale/bg/LC_MESSAGES/hello.mo
]]></screen>
</para>
</section>
<section xml:id="dockerTools-buildLayeredImage-arg-config">
<title>Automatic inclusion of <varname>config</varname> references</title>
<para>
The closure of <varname>config</varname> is automatically included in the
closure of the final image.
</para>
<para>
This allows you to make very simple Docker images with very little code.
This container will start up and run <command>hello</command>:
<programlisting><![CDATA[
pkgs.dockerTools.buildLayeredImage {
name = "hello";
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
}
]]></programlisting>
</para>
</section>
<section xml:id="dockerTools-buildLayeredImage-arg-maxLayers">
<title>Adjusting <varname>maxLayers</varname></title>
<para>
Increasing the <varname>maxLayers</varname> increases the number of layers
which have a chance to be shared between different images.
</para>
<para>
Modern Docker installations support up to 128 layers, however older
versions support as few as 42.
</para>
<para>
If the produced image will not be extended by other Docker builds, it is
safe to set <varname>maxLayers</varname> to <literal>128</literal>. However
it will be impossible to extend the image further.
</para>
<para>
The first (<literal>maxLayers-2</literal>) most "popular" paths will have
their own individual layers, then layer #<literal>maxLayers-1</literal>
will contain all the remaining "unpopular" paths, and finally layer
#<literal>maxLayers</literal> will contain the Image configuration.
</para>
<para>
Docker's Layers are not inherently ordered, they are content-addressable
and are not explicitly layered until they are composed in to an Image.
</para>
</section>
</section>
<section xml:id="ssec-pkgs-dockerTools-fetchFromRegistry">
<title>pullImage</title>
<para>
This function is analogous to the <command>docker pull</command> command, in
that can be used to pull a Docker image from a Docker registry. By default
<link xlink:href="https://hub.docker.com/">Docker Hub</link> is used to pull
images.
</para>
<para>
Its parameters are described in the example below:
</para>
<example xml:id='ex-dockerTools-pullImage'>
<title>Docker pull</title>
<programlisting>
pullImage {
imageName = "nixos/nix"; <co xml:id='ex-dockerTools-pullImage-1' />
imageDigest = "sha256:20d9485b25ecfd89204e843a962c1bd70e9cc6858d65d7f5fadc340246e2116b"; <co xml:id='ex-dockerTools-pullImage-2' />
finalImageTag = "1.11"; <co xml:id='ex-dockerTools-pullImage-3' />
sha256 = "0mqjy3zq2v6rrhizgb9nvhczl87lcfphq9601wcprdika2jz7qh8"; <co xml:id='ex-dockerTools-pullImage-4' />
os = "linux"; <co xml:id='ex-dockerTools-pullImage-5' />
arch = "x86_64"; <co xml:id='ex-dockerTools-pullImage-6' />
}
</programlisting>
</example>
<calloutlist>
<callout arearefs='ex-dockerTools-pullImage-1'>
<para>
<varname>imageName</varname> specifies the name of the image to be
downloaded, which can also include the registry namespace (e.g.
<literal>nixos</literal>). This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-2'>
<para>
<varname>imageDigest</varname> specifies the digest of the image to be
downloaded. Skopeo can be used to get the digest of an image, with its
<varname>inspect</varname> subcommand. Since a given
<varname>imageName</varname> may transparently refer to a manifest list of
images which support multiple architectures and/or operating systems,
supply the `--override-os` and `--override-arch` arguments to specify
exactly which image you want. By default it will match the OS and
architecture of the host the command is run on.
<programlisting>
$ nix-shell --packages skopeo jq --command "skopeo --override-os linux --override-arch x86_64 inspect docker://docker.io/nixos/nix:1.11 | jq -r '.Digest'"
sha256:20d9485b25ecfd89204e843a962c1bd70e9cc6858d65d7f5fadc340246e2116b
</programlisting>
This argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-3'>
<para>
<varname>finalImageTag</varname>, if specified, this is the tag of the
image to be created. Note it is never used to fetch the image since we
prefer to rely on the immutable digest ID. By default it's
<literal>latest</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-4'>
<para>
<varname>sha256</varname> is the checksum of the whole fetched image. This
argument is required.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-5'>
<para>
<varname>os</varname>, if specified, is the operating system of the
fetched image. By default it's <literal>linux</literal>.
</para>
</callout>
<callout arearefs='ex-dockerTools-pullImage-6'>
<para>
<varname>arch</varname>, if specified, is the cpu architecture of the
fetched image. By default it's <literal>x86_64</literal>.
</para>
</callout>
</calloutlist>
</section>
<section xml:id="ssec-pkgs-dockerTools-exportImage">
<title>exportImage</title>
<para>
This function is analogous to the <command>docker export</command> command,
in that can used to flatten a Docker image that contains multiple layers. It
is in fact the result of the merge of all the layers of the image. As such,
the result is suitable for being imported in Docker with <command>docker
import</command>.
</para>
<note>
<para>
Using this function requires the <literal>kvm</literal> device to be
available.
</para>
</note>
<para>
The parameters of <varname>exportImage</varname> are the following:
</para>
<example xml:id='ex-dockerTools-exportImage'>
<title>Docker export</title>
<programlisting>
exportImage {
fromImage = someLayeredImage;
fromImageName = null;
fromImageTag = null;
name = someLayeredImage.name;
}
</programlisting>
</example>
<para>
The parameters relative to the base image have the same synopsis as
described in <xref linkend='ssec-pkgs-dockerTools-buildImage'/>, except that
<varname>fromImage</varname> is the only required argument in this case.
</para>
<para>
The <varname>name</varname> argument is the name of the derivation output,
which defaults to <varname>fromImage.name</varname>.
</para>
</section>
<section xml:id="ssec-pkgs-dockerTools-shadowSetup">
<title>shadowSetup</title>
<para>
This constant string is a helper for setting up the base files for managing
users and groups, only if such files don't exist already. It is suitable for
being used in a <varname>runAsRoot</varname>
<xref linkend='ex-dockerTools-buildImage-runAsRoot'/> script for cases like
in the example below:
</para>
<example xml:id='ex-dockerTools-shadowSetup'>
<title>Shadow base files</title>
<programlisting>
buildImage {
name = "shadow-basic";
runAsRoot = ''
#!${stdenv.shell}
${shadowSetup}
groupadd -r redis
useradd -r -g redis redis
mkdir /data
chown redis:redis /data
'';
}
</programlisting>
</example>
<para>
Creating base files like <literal>/etc/passwd</literal> or
<literal>/etc/login.defs</literal> are necessary for shadow-utils to
manipulate users and groups.
</para>
</section>
</section>

View File

@ -0,0 +1,142 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-fhs-environments">
<title>buildFHSUserEnv</title>
<para>
<function>buildFHSUserEnv</function> provides a way to build and run
FHS-compatible lightweight sandboxes. It creates an isolated root with bound
<filename>/nix/store</filename>, so its footprint in terms of disk space
needed is quite small. This allows one to run software which is hard or
unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions,
games distributed as tarballs, software with integrity checking and/or
external self-updated binaries. It uses Linux namespaces feature to create
temporary lightweight environments which are destroyed after all child
processes exit, without root user rights requirement. Accepted arguments are:
</para>
<variablelist>
<varlistentry>
<term>
<literal>name</literal>
</term>
<listitem>
<para>
Environment name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>targetPkgs</literal>
</term>
<listitem>
<para>
Packages to be installed for the main host's architecture (i.e. x86_64 on
x86_64 installations). Along with libraries binaries are also installed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>multiPkgs</literal>
</term>
<listitem>
<para>
Packages to be installed for all architectures supported by a host (i.e.
i686 and x86_64 on x86_64 installations). Only libraries are installed by
default.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraBuildCommands</literal>
</term>
<listitem>
<para>
Additional commands to be executed for finalizing the directory structure.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraBuildCommandsMulti</literal>
</term>
<listitem>
<para>
Like <literal>extraBuildCommands</literal>, but executed only on multilib
architectures.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraOutputsToInstall</literal>
</term>
<listitem>
<para>
Additional derivation outputs to be linked for both target and
multi-architecture packages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>extraInstallCommands</literal>
</term>
<listitem>
<para>
Additional commands to be executed for finalizing the derivation with
runner script.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>runScript</literal>
</term>
<listitem>
<para>
A command that would be executed inside the sandbox and passed all the
command line arguments. It defaults to <literal>bash</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
One can create a simple environment using a <literal>shell.nix</literal> like
that:
</para>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
(pkgs.buildFHSUserEnv {
name = "simple-x11-env";
targetPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]) ++ (with pkgs.xorg;
[ libX11
libXcursor
libXrandr
]);
multiPkgs = pkgs: (with pkgs;
[ udev
alsaLib
]);
runScript = "bash";
}).env
]]></programlisting>
<para>
Running <literal>nix-shell</literal> would then drop you into a shell with
these libraries and binaries available. You can use this to run closed-source
applications which expect FHS structure without hassles: simply change
<literal>runScript</literal> to the application path, e.g.
<filename>./bin/start.sh</filename> -- relative paths are supported.
</para>
</section>

View File

@ -0,0 +1,89 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-generators">
<title>Generators</title>
<para>
Generators are functions that create file formats from nix data structures,
e.g. for configuration files. There are generators available for:
<literal>INI</literal>, <literal>JSON</literal> and <literal>YAML</literal>
</para>
<para>
All generators follow a similar call interface: <code>generatorName
configFunctions data</code>, where <literal>configFunctions</literal> is an
attrset of user-defined functions that format nested parts of the content.
They each have common defaults, so often they do not need to be set manually.
An example is <code>mkSectionName ? (name: libStr.escape [ "[" "]" ]
name)</code> from the <literal>INI</literal> generator. It receives the name
of a section and sanitizes it. The default <literal>mkSectionName</literal>
escapes <literal>[</literal> and <literal>]</literal> with a backslash.
</para>
<para>
Generators can be fine-tuned to produce exactly the file format required by
your application/service. One example is an INI-file format which uses
<literal>: </literal> as separator, the strings
<literal>"yes"</literal>/<literal>"no"</literal> as boolean values and
requires all string values to be quoted:
</para>
<programlisting>
with lib;
let
customToINI = generators.toINI {
# specifies how to format a key/value pair
mkKeyValue = generators.mkKeyValueDefault {
# specifies the generated string for a subset of nix values
mkValueString = v:
if v == true then ''"yes"''
else if v == false then ''"no"''
else if isString v then ''"${v}"''
# and delegats all other values to the default generator
else generators.mkValueStringDefault {} v;
} ":";
};
# the INI file can now be given as plain old nix values
in customToINI {
main = {
pushinfo = true;
autopush = false;
host = "localhost";
port = 42;
};
mergetool = {
merge = "diff3";
};
}
</programlisting>
<para>
This will produce the following INI file as nix string:
</para>
<programlisting>
[main]
autopush:"no"
host:"localhost"
port:42
pushinfo:"yes"
str\:ange:"very::strange"
[mergetool]
merge:"diff3"
</programlisting>
<note>
<para>
Nix store paths can be converted to strings by enclosing a derivation
attribute like so: <code>"${drv}"</code>.
</para>
</note>
<para>
Detailed documentation for each generator can be found in
<literal>lib/generators.nix</literal>.
</para>
</section>

15
doc/functions/library.xml Normal file
View File

@ -0,0 +1,15 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-functions-library">
<title>Nixpkgs Library Functions</title>
<para>
Nixpkgs provides a standard library at <varname>pkgs.lib</varname>, or
through <code>import &lt;nixpkgs/lib&gt;</code>.
</para>
<xi:include href="./library/asserts.xml" />
<xi:include href="./library/attrsets.xml" />
</section>

View File

@ -0,0 +1,117 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-functions-library-asserts">
<title>Assert functions</title>
<section xml:id="function-library-lib.asserts.assertMsg">
<title><function>lib.asserts.assertMsg</function></title>
<subtitle><literal>assertMsg :: Bool -> String -> Bool</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.asserts.assertMsg" />
<para>
Print a trace message if <literal>pred</literal> is false.
</para>
<para>
Intended to be used to augment asserts with helpful error messages.
</para>
<variablelist>
<varlistentry>
<term>
<varname>pred</varname>
</term>
<listitem>
<para>
Condition under which the <varname>msg</varname> should
<emphasis>not</emphasis> be printed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>msg</varname>
</term>
<listitem>
<para>
Message to print.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.asserts.assertMsg-example-false">
<title>Printing when the predicate is false</title>
<programlisting><![CDATA[
assert lib.asserts.assertMsg ("foo" == "bar") "foo is not bar, silly"
stderr> trace: foo is not bar, silly
stderr> assert failed
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.asserts.assertOneOf">
<title><function>lib.asserts.assertOneOf</function></title>
<subtitle><literal>assertOneOf :: String -> String ->
StringList -> Bool</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.asserts.assertOneOf" />
<para>
Specialized <function>asserts.assertMsg</function> for checking if
<varname>val</varname> is one of the elements of <varname>xs</varname>.
Useful for checking enums.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the variable the user entered <varname>val</varname> into,
for inclusion in the error message.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>val</varname>
</term>
<listitem>
<para>
The value of what the user provided, to be compared against the values in
<varname>xs</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>xs</varname>
</term>
<listitem>
<para>
The list of valid values.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.asserts.assertOneOf-example">
<title>Ensuring a user provided a possible value</title>
<programlisting><![CDATA[
let sslLibrary = "bearssl";
in lib.asserts.assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ];
=> false
stderr> trace: sslLibrary must be one of "openssl", "libressl", but is: "bearssl"
]]></programlisting>
</example>
</section>
</section>

View File

@ -0,0 +1,970 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-functions-library-attrset">
<title>Attribute-Set Functions</title>
<section xml:id="function-library-lib.attrsets.attrByPath">
<title><function>lib.attrset.attrByPath</function></title>
<subtitle><literal>attrByPath :: [String] -> Any -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.attrByPath" />
<para>
Return an attribute from within nested attribute sets.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attrPath</varname>
</term>
<listitem>
<para>
A list of strings representing the path through the nested attribute set
<varname>set</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>default</varname>
</term>
<listitem>
<para>
Default value if <varname>attrPath</varname> does not resolve to an
existing value.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The nested attributeset to select values from.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrset.attrByPath-example-value-exists">
<title>Extracting a value from a nested attribute set</title>
<programlisting><![CDATA[
let set = { a = { b = 3; }; };
in lib.attrsets.attrByPath [ "a" "b" ] 0 set
=> 3
]]></programlisting>
</example>
<example xml:id="function-library-lib.attrset.attrByPath-example-default-value">
<title>No value at the path, instead using the default</title>
<programlisting><![CDATA[
lib.attrsets.attrByPath [ "a" "b" ] 0 {}
=> 0
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.hasAttrByPath">
<title><function>lib.attrsets.hasAttrByPath</function></title>
<subtitle><literal>hasAttrByPath :: [String] -> AttrSet -> Bool</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.hasAttrByPath" />
<para>
Determine if an attribute exists within a nested attribute set.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attrPath</varname>
</term>
<listitem>
<para>
A list of strings representing the path through the nested attribute set
<varname>set</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The nested attributeset to check.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.hasAttrByPath-example">
<title>A nested value does exist inside a set</title>
<programlisting><![CDATA[
lib.attrsets.hasAttrByPath
[ "a" "b" "c" "d" ]
{ a = { b = { c = { d = 123; }; }; }; }
=> true
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.setAttrByPath">
<title><function>lib.attrsets.setAttrByPath</function></title>
<subtitle><literal>setAttrByPath :: [String] -> Any -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.setAttrByPath" />
<para>
Create a new attribute set with <varname>value</varname> set at the nested
attribute location specified in <varname>attrPath</varname>.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attrPath</varname>
</term>
<listitem>
<para>
A list of strings representing the path through the nested attribute set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The value to set at the location described by
<varname>attrPath</varname>.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.setAttrByPath-example">
<title>Creating a new nested attribute set</title>
<programlisting><![CDATA[
lib.attrsets.setAttrByPath [ "a" "b" ] 3
=> { a = { b = 3; }; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.getAttrFromPath">
<title><function>lib.attrsets.getAttrFromPath</function></title>
<subtitle><literal>getAttrFromPath :: [String] -> AttrSet -> Value</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.getAttrFromPath" />
<para>
Like <xref linkend="function-library-lib.attrsets.attrByPath" /> except
without a default, and it will throw if the value doesn't exist.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attrPath</varname>
</term>
<listitem>
<para>
A list of strings representing the path through the nested attribute set
<varname>set</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The nested attribute set to find the value in.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.getAttrPath-example-success">
<title>Succesfully getting a value from an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.getAttrFromPath [ "a" "b" ] { a = { b = 3; }; }
=> 3
]]></programlisting>
</example>
<example xml:id="function-library-lib.attrsets.getAttrPath-example-throw">
<title>Throwing after failing to get a value from an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.getAttrFromPath [ "x" "y" ] { }
=> error: cannot find attribute `x.y'
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.attrVals">
<title><function>lib.attrsets.attrVals</function></title>
<subtitle><literal>attrVals :: [String] -> AttrSet -> [Any]</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.attrVals" />
<para>
Return the specified attributes from a set. All values must exist.
</para>
<variablelist>
<varlistentry>
<term>
<varname>nameList</varname>
</term>
<listitem>
<para>
The list of attributes to fetch from <varname>set</varname>. Each
attribute name must exist on the attrbitue set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The set to get attribute values from.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.attrVals-example-success">
<title>Getting several values from an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.attrVals [ "a" "b" "c" ] { a = 1; b = 2; c = 3; }
=> [ 1 2 3 ]
]]></programlisting>
</example>
<example xml:id="function-library-lib.attrsets.attrVals-failure">
<title>Getting missing values from an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.attrVals [ "d" ] { }
error: attribute 'd' missing
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.attrValues">
<title><function>lib.attrsets.attrValues</function></title>
<subtitle><literal>attrValues :: AttrSet -> [Any]</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.attrValues" />
<para>
Get all the attribute values from an attribute set.
</para>
<para>
Provides a backwards-compatible interface of
<function>builtins.attrValues</function> for Nix version older than 1.8.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attrs</varname>
</term>
<listitem>
<para>
The attribute set.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.attrValues-example">
<title></title>
<programlisting><![CDATA[
lib.attrsets.attrValues { a = 1; b = 2; c = 3; }
=> [ 1 2 3 ]
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.catAttrs">
<title><function>lib.attrsets.catAttrs</function></title>
<subtitle><literal>catAttrs :: String -> AttrSet -> [Any]</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.catAttrs" />
<para>
Collect each attribute named `attr' from the list of attribute sets,
<varname>sets</varname>. Sets that don't contain the named attribute are
ignored.
</para>
<para>
Provides a backwards-compatible interface of
<function>builtins.catAttrs</function> for Nix version older than 1.9.
</para>
<variablelist>
<varlistentry>
<term>
<varname>attr</varname>
</term>
<listitem>
<para>
Attribute name to select from each attribute set in
<varname>sets</varname>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>sets</varname>
</term>
<listitem>
<para>
The list of attribute sets to select <varname>attr</varname> from.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.catAttrs-example">
<title>Collect an attribute from a list of attribute sets.</title>
<para>
Attribute sets which don't have the attribute are ignored.
</para>
<programlisting><![CDATA[
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
=> [ 1 2 ]
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.filterAttrs">
<title><function>lib.attrsets.filterAttrs</function></title>
<subtitle><literal>filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.filterAttrs" />
<para>
Filter an attribute set by removing all attributes for which the given
predicate return false.
</para>
<variablelist>
<varlistentry>
<term>
<varname>pred</varname>
</term>
<listitem>
<para>
<literal>String -> Any -> Bool</literal>
</para>
<para>
Predicate which returns true to include an attribute, or returns false to
exclude it.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The attribute's name
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute's value
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Returns <literal>true</literal> to include the attribute,
<literal>false</literal> to exclude the attribute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The attribute set to filter
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.filterAttrs-example">
<title>Filtering an attributeset</title>
<programlisting><![CDATA[
filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
=> { foo = 1; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.filterAttrsRecursive">
<title><function>lib.attrsets.filterAttrsRecursive</function></title>
<subtitle><literal>filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.filterAttrsRecursive" />
<para>
Filter an attribute set recursively by removing all attributes for which the
given predicate return false.
</para>
<variablelist>
<varlistentry>
<term>
<varname>pred</varname>
</term>
<listitem>
<para>
<literal>String -> Any -> Bool</literal>
</para>
<para>
Predicate which returns true to include an attribute, or returns false to
exclude it.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The attribute's name
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute's value
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Returns <literal>true</literal> to include the attribute,
<literal>false</literal> to exclude the attribute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The attribute set to filter
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.filterAttrsRecursive-example">
<title>Recursively filtering an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.filterAttrsRecursive
(n: v: v != null)
{
levelA = {
example = "hi";
levelB = {
hello = "there";
this-one-is-present = {
this-is-excluded = null;
};
};
this-one-is-also-excluded = null;
};
also-excluded = null;
}
=> {
levelA = {
example = "hi";
levelB = {
hello = "there";
this-one-is-present = { };
};
};
}
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.foldAttrs">
<title><function>lib.attrsets.foldAttrs</function></title>
<subtitle><literal>foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.foldAttrs" />
<para>
Apply fold function to values grouped by key.
</para>
<variablelist>
<varlistentry>
<term>
<varname>op</varname>
</term>
<listitem>
<para>
<literal>Any -> Any -> Any</literal>
</para>
<para>
Given a value <varname>val</varname> and a collector
<varname>col</varname>, combine the two.
</para>
<variablelist>
<varlistentry>
<term>
<varname>val</varname>
</term>
<listitem>
<para>
An attribute's value
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>col</varname>
</term>
<listitem>
<!-- TODO: make this not bad, use more fold-ey terms -->
<para>
The result of previous <function>op</function> calls with other values
and <function>nul</function>.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>nul</varname>
</term>
<listitem>
<para>
The null-value, the starting value.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>list_of_attrs</varname>
</term>
<listitem>
<para>
A list of attribute sets to fold together by key.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.foldAttrs-example">
<title>Combining an attribute of lists in to one attribute set</title>
<programlisting><![CDATA[
lib.attrsets.foldAttrs
(n: a: [n] ++ a) []
[
{ a = 2; b = 7; }
{ a = 3; }
{ b = 6; }
]
=> { a = [ 2 3 ]; b = [ 7 6 ]; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.collect">
<title><function>lib.attrsets.collect</function></title>
<subtitle><literal>collect :: (Any -> Bool) -> AttrSet -> [Any]</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.collect" />
<para>
Recursively collect sets that verify a given predicate named
<varname>pred</varname> from the set <varname>attrs</varname>. The recursion
stops when <varname>pred</varname> returns <literal>true</literal>.
</para>
<variablelist>
<varlistentry>
<term>
<varname>pred</varname>
</term>
<listitem>
<para>
<literal>Any -> Bool</literal>
</para>
<para>
Given an attribute's value, determine if recursion should stop.
</para>
<variablelist>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute set value.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>attrs</varname>
</term>
<listitem>
<para>
The attribute set to recursively collect.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.collect-example-lists">
<title>Collecting all lists from an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.collect isList { a = { b = ["b"]; }; c = [1]; }
=> [["b"] [1]]
]]></programlisting>
</example>
<example xml:id="function-library-lib.attrsets.collect-example-outpath">
<title>Collecting all attribute-sets which contain the <literal>outPath</literal> attribute name.</title>
<programlisting><![CDATA[
collect (x: x ? outPath)
{ a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
=> [{ outPath = "a/"; } { outPath = "b/"; }]
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.nameValuePair">
<title><function>lib.attrsets.nameValuePair</function></title>
<subtitle><literal>nameValuePair :: String -> Any -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.nameValuePair" />
<para>
Utility function that creates a <literal>{name, value}</literal> pair as
expected by <function>builtins.listToAttrs</function>.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The attribute name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute value.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.nameValuePair-example">
<title>Creating a name value pair</title>
<programlisting><![CDATA[
nameValuePair "some" 6
=> { name = "some"; value = 6; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.mapAttrs">
<title><function>lib.attrsets.mapAttrs</function></title>
<subtitle><literal></literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.mapAttrs" />
<para>
Apply a function to each element in an attribute set, creating a new
attribute set.
</para>
<para>
Provides a backwards-compatible interface of
<function>builtins.mapAttrs</function> for Nix version older than 2.1.
</para>
<variablelist>
<varlistentry>
<term>
<varname>fn</varname>
</term>
<listitem>
<para>
<literal>String -> Any -> Any</literal>
</para>
<para>
Given an attribute's name and value, return a new value.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the attribute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute's value.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.mapAttrs-example">
<title>Modifying each value of an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.mapAttrs
(name: value: name + "-" value)
{ x = "foo"; y = "bar"; }
=> { x = "x-foo"; y = "y-bar"; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.mapAttrs-prime">
<title><function>lib.attrsets.mapAttrs&apos;</function></title>
<subtitle><literal>mapAttrs' :: (String -> Any -> { name = String; value = Any }) -> AttrSet -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.mapAttrs-prime" />
<para>
Like <function>mapAttrs</function>, but allows the name of each attribute to
be changed in addition to the value. The applied function should return both
the new name and value as a <function>nameValuePair</function>.
</para>
<variablelist>
<varlistentry>
<term>
<varname>fn</varname>
</term>
<listitem>
<para>
<literal>String -> Any -> { name = String; value = Any }</literal>
</para>
<para>
Given an attribute's name and value, return a new
<link
linkend="function-library-lib.attrsets.nameValuePair">name
value pair</link>.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the attribute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute's value.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The attribute set to map over.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.mapAttrs-prime-example">
<title>Change the name and value of each attribute of an attribute set</title>
<programlisting><![CDATA[
lib.attrsets.mapAttrs' (name: value: lib.attrsets.nameValuePair ("foo_" + name) ("bar-" + value))
{ x = "a"; y = "b"; }
=> { foo_x = "bar-a"; foo_y = "bar-b"; }
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.mapAttrsToList">
<title><function>lib.attrsets.mapAttrsToList</function></title>
<subtitle><literal>mapAttrsToList :: (String -> Any -> Any) ->
AttrSet -> Any</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.mapAttrsToList" />
<para>
Call <varname>fn</varname> for each attribute in the given
<varname>set</varname> and return the result in a list.
</para>
<variablelist>
<varlistentry>
<term>
<varname>fn</varname>
</term>
<listitem>
<para>
<literal>String -> Any -> Any</literal>
</para>
<para>
Given an attribute's name and value, return a new value.
</para>
<variablelist>
<varlistentry>
<term>
<varname>name</varname>
</term>
<listitem>
<para>
The name of the attribute.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>value</varname>
</term>
<listitem>
<para>
The attribute's value.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>set</varname>
</term>
<listitem>
<para>
The attribute set to map over.
</para>
</listitem>
</varlistentry>
</variablelist>
<example xml:id="function-library-lib.attrsets.mapAttrsToList-example">
<title>Combine attribute values and names in to a list</title>
<programlisting><![CDATA[
lib.attrsets.mapAttrsToList (name: value: "${name}=${value}")
{ x = "a"; y = "b"; }
=> [ "x=a" "y=b" ]
]]></programlisting>
</example>
</section>
<section xml:id="function-library-lib.attrsets.mapAttrsRecursive">
<title><function>lib.attrsets.mapAttrsRecursive</function></title>
<subtitle><literal>mapAttrsRecursive :: ([String] > Any -> Any) -> AttrSet -> AttrSet</literal>
</subtitle>
<xi:include href="./locations.xml" xpointer="lib.attrsets.mapAttrsRecursive" />
<para>
Like <function>mapAttrs</function>, except that it recursively applies
itself to attribute sets. Also, the first argument of the argument function
is a <emphasis>list</emphasis> of the names of the containing attributes.
</para>
</section>
</section>

203
doc/functions/overrides.xml Normal file
View File

@ -0,0 +1,203 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-overrides">
<title>Overriding</title>
<para>
Sometimes one wants to override parts of <literal>nixpkgs</literal>, e.g.
derivation attributes, the results of derivations or even the whole package
set.
</para>
<section xml:id="sec-pkg-override">
<title>&lt;pkg&gt;.override</title>
<para>
The function <varname>override</varname> is usually available for all the
derivations in the nixpkgs expression (<varname>pkgs</varname>).
</para>
<para>
It is used to override the arguments passed to a function.
</para>
<para>
Example usages:
<programlisting>pkgs.foo.override { arg1 = val1; arg2 = val2; ... }</programlisting>
<programlisting>
import pkgs.path { overlays = [ (self: super: {
foo = super.foo.override { barSupport = true ; };
})]};
</programlisting>
<programlisting>
mypkg = pkgs.callPackage ./mypkg.nix {
mydep = pkgs.mydep.override { ... };
}
</programlisting>
</para>
<para>
In the first example, <varname>pkgs.foo</varname> is the result of a
function call with some default arguments, usually a derivation. Using
<varname>pkgs.foo.override</varname> will call the same function with the
given new arguments.
</para>
</section>
<section xml:id="sec-pkg-overrideAttrs">
<title>&lt;pkg&gt;.overrideAttrs</title>
<para>
The function <varname>overrideAttrs</varname> allows overriding the
attribute set passed to a <varname>stdenv.mkDerivation</varname> call,
producing a new derivation based on the original one. This function is
available on all derivations produced by the
<varname>stdenv.mkDerivation</varname> function, which is most packages in
the nixpkgs expression <varname>pkgs</varname>.
</para>
<para>
Example usage:
<programlisting>
helloWithDebug = pkgs.hello.overrideAttrs (oldAttrs: rec {
separateDebugInfo = true;
});
</programlisting>
</para>
<para>
In the above example, the <varname>separateDebugInfo</varname> attribute is
overridden to be true, thus building debug info for
<varname>helloWithDebug</varname>, while all other attributes will be
retained from the original <varname>hello</varname> package.
</para>
<para>
The argument <varname>oldAttrs</varname> is conventionally used to refer to
the attr set originally passed to <varname>stdenv.mkDerivation</varname>.
</para>
<note>
<para>
Note that <varname>separateDebugInfo</varname> is processed only by the
<varname>stdenv.mkDerivation</varname> function, not the generated, raw Nix
derivation. Thus, using <varname>overrideDerivation</varname> will not work
in this case, as it overrides only the attributes of the final derivation.
It is for this reason that <varname>overrideAttrs</varname> should be
preferred in (almost) all cases to <varname>overrideDerivation</varname>,
i.e. to allow using <varname>sdenv.mkDerivation</varname> to process input
arguments, as well as the fact that it is easier to use (you can use the
same attribute names you see in your Nix code, instead of the ones
generated (e.g. <varname>buildInputs</varname> vs
<varname>nativeBuildInputs</varname>, and involves less typing.
</para>
</note>
</section>
<section xml:id="sec-pkg-overrideDerivation">
<title>&lt;pkg&gt;.overrideDerivation</title>
<warning>
<para>
You should prefer <varname>overrideAttrs</varname> in almost all cases, see
its documentation for the reasons why.
<varname>overrideDerivation</varname> is not deprecated and will continue
to work, but is less nice to use and does not have as many abilities as
<varname>overrideAttrs</varname>.
</para>
</warning>
<warning>
<para>
Do not use this function in Nixpkgs as it evaluates a Derivation before
modifying it, which breaks package abstraction and removes error-checking
of function arguments. In addition, this evaluation-per-function
application incurs a performance penalty, which can become a problem if
many overrides are used. It is only intended for ad-hoc customisation, such
as in <filename>~/.config/nixpkgs/config.nix</filename>.
</para>
</warning>
<para>
The function <varname>overrideDerivation</varname> creates a new derivation
based on an existing one by overriding the original's attributes with the
attribute set produced by the specified function. This function is available
on all derivations defined using the <varname>makeOverridable</varname>
function. Most standard derivation-producing functions, such as
<varname>stdenv.mkDerivation</varname>, are defined using this function,
which means most packages in the nixpkgs expression,
<varname>pkgs</varname>, have this function.
</para>
<para>
Example usage:
<programlisting>
mySed = pkgs.gnused.overrideDerivation (oldAttrs: {
name = "sed-4.2.2-pre";
src = fetchurl {
url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2;
sha256 = "11nq06d131y4wmf3drm0yk502d2xc6n5qy82cg88rb9nqd2lj41k";
};
patches = [];
});
</programlisting>
</para>
<para>
In the above example, the <varname>name</varname>, <varname>src</varname>,
and <varname>patches</varname> of the derivation will be overridden, while
all other attributes will be retained from the original derivation.
</para>
<para>
The argument <varname>oldAttrs</varname> is used to refer to the attribute
set of the original derivation.
</para>
<note>
<para>
A package's attributes are evaluated *before* being modified by the
<varname>overrideDerivation</varname> function. For example, the
<varname>name</varname> attribute reference in <varname>url =
"mirror://gnu/hello/${name}.tar.gz";</varname> is filled-in *before* the
<varname>overrideDerivation</varname> function modifies the attribute set.
This means that overriding the <varname>name</varname> attribute, in this
example, *will not* change the value of the <varname>url</varname>
attribute. Instead, we need to override both the <varname>name</varname>
*and* <varname>url</varname> attributes.
</para>
</note>
</section>
<section xml:id="sec-lib-makeOverridable">
<title>lib.makeOverridable</title>
<para>
The function <varname>lib.makeOverridable</varname> is used to make the
result of a function easily customizable. This utility only makes sense for
functions that accept an argument set and return an attribute set.
</para>
<para>
Example usage:
<programlisting>
f = { a, b }: { result = a+b; };
c = lib.makeOverridable f { a = 1; b = 2; };
</programlisting>
</para>
<para>
The variable <varname>c</varname> is the value of the <varname>f</varname>
function applied with some default arguments. Hence the value of
<varname>c.result</varname> is <literal>3</literal>, in this example.
</para>
<para>
The variable <varname>c</varname> however also has some additional
functions, like <link linkend="sec-pkg-override">c.override</link> which can
be used to override the default arguments. In this example the value of
<varname>(c.override { a = 4; }).result</varname> is 6.
</para>
</section>
</section>

26
doc/functions/shell.xml Normal file
View File

@ -0,0 +1,26 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-pkgs-mkShell">
<title>pkgs.mkShell</title>
<para>
<function>pkgs.mkShell</function> is a special kind of derivation that is
only useful when using it combined with <command>nix-shell</command>. It will
in fact fail to instantiate when invoked with <command>nix-build</command>.
</para>
<section xml:id="sec-pkgs-mkShell-usage">
<title>Usage</title>
<programlisting><![CDATA[
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar
# available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
]]></programlisting>
</section>
</section>

View File

@ -0,0 +1,85 @@
{ pkgs ? (import ./.. { }), nixpkgs ? { }}:
let
revision = pkgs.lib.trivial.revisionWithDefault (nixpkgs.revision or "master");
libDefPos = set:
builtins.map
(name: {
name = name;
location = builtins.unsafeGetAttrPos name set;
})
(builtins.attrNames set);
libset = toplib:
builtins.map
(subsetname: {
subsetname = subsetname;
functions = libDefPos toplib."${subsetname}";
})
(builtins.filter
(name: builtins.isAttrs toplib."${name}")
(builtins.attrNames toplib));
nixpkgsLib = pkgs.lib;
flattenedLibSubset = { subsetname, functions }:
builtins.map
(fn: {
name = "lib.${subsetname}.${fn.name}";
value = fn.location;
})
functions;
locatedlibsets = libs: builtins.map flattenedLibSubset (libset libs);
removeFilenamePrefix = prefix: filename:
let
prefixLen = (builtins.stringLength prefix) + 1; # +1 to remove the leading /
filenameLen = builtins.stringLength filename;
substr = builtins.substring prefixLen filenameLen filename;
in substr;
removeNixpkgs = removeFilenamePrefix (builtins.toString pkgs.path);
liblocations =
builtins.filter
(elem: elem.value != null)
(nixpkgsLib.lists.flatten
(locatedlibsets nixpkgsLib));
fnLocationRelative = { name, value }:
{
inherit name;
value = value // { file = removeNixpkgs value.file; };
};
relativeLocs = (builtins.map fnLocationRelative liblocations);
sanitizeId = builtins.replaceStrings
[ "'" ]
[ "-prime" ];
urlPrefix = "https://github.com/NixOS/nixpkgs/blob/${revision}";
xmlstrings = (nixpkgsLib.strings.concatMapStrings
({ name, value }:
''
<section><title>${name}</title>
<para xml:id="${sanitizeId name}">
Located at
<link
xlink:href="${urlPrefix}/${value.file}#L${builtins.toString value.line}">${value.file}:${builtins.toString value.line}</link>
in <literal>&lt;nixpkgs&gt;</literal>.
</para>
</section>
'')
relativeLocs);
in pkgs.writeText
"locations.xml"
''
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="5">
<title>All the locations for every lib function</title>
<para>This file is only for inclusion by other files.</para>
${xmlstrings}
</section>
''

View File

@ -668,8 +668,9 @@ overrides = self: super: rec {
plugins = with availablePlugins; [ python perl ];
}
}</programlisting>
If the <literal>configure</literal> function returns an attrset without the <literal>plugins</literal>
attribute, <literal>availablePlugins</literal> will be used automatically.
If the <literal>configure</literal> function returns an attrset without the
<literal>plugins</literal> attribute, <literal>availablePlugins</literal>
will be used automatically.
</para>
<para>
@ -703,9 +704,11 @@ overrides = self: super: rec {
}; }
</programlisting>
</para>
<para>
WeeChat allows to set defaults on startup using the <literal>--run-command</literal>.
The <literal>configure</literal> method can be used to pass commands to the program:
WeeChat allows to set defaults on startup using the
<literal>--run-command</literal>. The <literal>configure</literal> method
can be used to pass commands to the program:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
init = ''
@ -714,12 +717,14 @@ overrides = self: super: rec {
'';
};
}</programlisting>
Further values can be added to the list of commands when running
<literal>weechat --run-command "your-commands"</literal>.
Further values can be added to the list of commands when running
<literal>weechat --run-command "your-commands"</literal>.
</para>
<para>
Additionally it's possible to specify scripts to be loaded when starting <literal>weechat</literal>.
These will be loaded before the commands from <literal>init</literal>:
Additionally it's possible to specify scripts to be loaded when starting
<literal>weechat</literal>. These will be loaded before the commands from
<literal>init</literal>:
<programlisting>weechat.override {
configure = { availablePlugins, ... }: {
scripts = with pkgs.weechatScripts; [
@ -731,11 +736,13 @@ overrides = self: super: rec {
};
}</programlisting>
</para>
<para>
In <literal>nixpkgs</literal> there's a subpackage which contains derivations for
WeeChat scripts. Such derivations expect a <literal>passthru.scripts</literal> attribute
which contains a list of all scripts inside the store path. Furthermore all scripts
have to live in <literal>$out/share</literal>. An exemplary derivation looks like this:
In <literal>nixpkgs</literal> there's a subpackage which contains
derivations for WeeChat scripts. Such derivations expect a
<literal>passthru.scripts</literal> attribute which contains a list of all
scripts inside the store path. Furthermore all scripts have to live in
<literal>$out/share</literal>. An exemplary derivation looks like this:
<programlisting>{ stdenv, fetchurl }:
stdenv.mkDerivation {
@ -814,20 +821,26 @@ citrix_receiver.override {
<section xml:id="sec-ibus-typing-booster">
<title>ibus-engines.typing-booster</title>
<para>This package is an ibus-based completion method to speed up typing.</para>
<para>
This package is an ibus-based completion method to speed up typing.
</para>
<section xml:id="sec-ibus-typing-booster-activate">
<title>Activating the engine</title>
<para>
IBus needs to be configured accordingly to activate <literal>typing-booster</literal>. The configuration
depends on the desktop manager in use. For detailed instructions, please refer to the
<link xlink:href="https://mike-fabian.github.io/ibus-typing-booster/documentation.html">upstream docs</link>.
IBus needs to be configured accordingly to activate
<literal>typing-booster</literal>. The configuration depends on the desktop
manager in use. For detailed instructions, please refer to the
<link xlink:href="https://mike-fabian.github.io/ibus-typing-booster/documentation.html">upstream
docs</link>.
</para>
<para>
On NixOS you need to explicitly enable <literal>ibus</literal> with given engines
before customizing your desktop to use <literal>typing-booster</literal>. This can be achieved
using the <literal>ibus</literal> module:
On NixOS you need to explicitly enable <literal>ibus</literal> with given
engines before customizing your desktop to use
<literal>typing-booster</literal>. This can be achieved using the
<literal>ibus</literal> module:
<programlisting>{ pkgs, ... }: {
i18n.inputMethod = {
enabled = "ibus";
@ -841,17 +854,20 @@ citrix_receiver.override {
<title>Using custom hunspell dictionaries</title>
<para>
The IBus engine is based on <literal>hunspell</literal> to support completion in many languages.
By default the dictionaries <literal>de-de</literal>, <literal>en-us</literal>, <literal>es-es</literal>,
<literal>it-it</literal>, <literal>sv-se</literal> and <literal>sv-fi</literal>
are in use. To add another dictionary, the package can be overridden like this:
The IBus engine is based on <literal>hunspell</literal> to support
completion in many languages. By default the dictionaries
<literal>de-de</literal>, <literal>en-us</literal>,
<literal>es-es</literal>, <literal>it-it</literal>,
<literal>sv-se</literal> and <literal>sv-fi</literal> are in use. To add
another dictionary, the package can be overridden like this:
<programlisting>ibus-engines.typing-booster.override {
langs = [ "de-at" "en-gb" ];
}</programlisting>
</para>
<para>
<emphasis>Note: each language passed to <literal>langs</literal> must be an attribute name in
<literal>pkgs.hunspellDicts</literal>.</emphasis>
<emphasis>Note: each language passed to <literal>langs</literal> must be an
attribute name in <literal>pkgs.hunspellDicts</literal>.</emphasis>
</para>
</section>
@ -859,10 +875,12 @@ citrix_receiver.override {
<title>Built-in emoji picker</title>
<para>
The <literal>ibus-engines.typing-booster</literal> package contains a program
named <literal>emoji-picker</literal>. To display all emojis correctly,
a special font such as <literal>noto-fonts-emoji</literal> is needed:
The <literal>ibus-engines.typing-booster</literal> package contains a
program named <literal>emoji-picker</literal>. To display all emojis
correctly, a special font such as <literal>noto-fonts-emoji</literal> is
needed:
</para>
<para>
On NixOS it can be installed using the following expression:
<programlisting>{ pkgs, ... }: {

View File

@ -1,5 +1,5 @@
{ pkgs ? import ../. {} }:
(import ./default.nix).overrideAttrs (x: {
(import ./default.nix {}).overrideAttrs (x: {
buildInputs = x.buildInputs ++ [ pkgs.xmloscopy pkgs.ruby ];
})

View File

@ -1,22 +0,0 @@
---
title: pkgs.mkShell
author: zimbatm
date: 2017-10-30
---
# mkShell
pkgs.mkShell is a special kind of derivation that is only useful when using
it combined with nix-shell. It will in fact fail to instantiate when invoked
with nix-build.
## Usage
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
```

View File

@ -8,7 +8,31 @@ with lib.strings;
rec {
# Returns true when the given argument is an option
#
# Examples:
# isOption 1 // => false
# isOption (mkOption {}) // => true
isOption = lib.isType "option";
# Creates an Option attribute set. mkOption accepts an attribute set with the following keys:
#
# default: Default value used when no definition is given in the configuration.
# defaultText: Textual representation of the default, for in the manual.
# example: Example value used in the manual.
# description: String describing the option.
# type: Option type, providing type-checking and value merging.
# apply: Function that converts the option value to something else.
# internal: Whether the option is for NixOS developers only.
# visible: Whether the option shows up in the manual.
# readOnly: Whether the option can be set only once
# options: Obsolete, used by types.optionSet.
#
# All keys default to `null` when not given.
#
# Examples:
# mkOption { } // => { _type = "option"; }
# mkOption { defaultText = "foo"; } // => { _type = "option"; defaultText = "foo"; }
mkOption =
{ default ? null # Default value used when no definition is given in the configuration.
, defaultText ? null # Textual representation of the default, for in the manual.
@ -24,6 +48,10 @@ rec {
} @ attrs:
attrs // { _type = "option"; };
# Creates a Option attribute set for a boolean value option i.e an option to be toggled on or off:
#
# Examples:
# mkEnableOption "foo" // => { _type = "option"; default = false; description = "Whether to enable foo."; example = true; type = { ... }; }
mkEnableOption = name: mkOption {
default = false;
example = true;
@ -74,7 +102,18 @@ rec {
else
val) (head defs).value defs;
# Extracts values of all "value" keys of the given list
#
# Examples:
# getValues [ { value = 1; } { value = 2; } ] // => [ 1 2 ]
# getValues [ ] // => [ ]
getValues = map (x: x.value);
# Extracts values of all "file" keys of the given list
#
# Examples:
# getFiles [ { file = "file1"; } { file = "file2"; } ] // => [ "file1" "file2" ]
# getFiles [ ] // => [ ]
getFiles = map (x: x.file);
# Generate documentation template from the list of option declaration like

View File

@ -26,6 +26,10 @@ rec {
(type == "symlink" && lib.hasPrefix "result" baseName)
);
# Filters a source tree removing version control files and directories using cleanSourceWith
#
# Example:
# cleanSource ./.
cleanSource = src: cleanSourceWith { filter = cleanSourceFilter; inherit src; };
# Like `builtins.filterSource`, except it will compose with itself,

View File

@ -105,6 +105,16 @@ rec {
then lib.strings.fileContents suffixFile
else "pre-git";
# Attempt to get the revision nixpkgs is from
revisionWithDefault = default:
let
revisionFile = "${toString ./..}/.git-revision";
gitRepo = "${toString ./..}/.git";
in if lib.pathIsDirectory gitRepo
then lib.commitIdFromGitRepo gitRepo
else if lib.pathExists revisionFile then lib.fileContents revisionFile
else default;
nixpkgsVersion = builtins.trace "`lib.nixpkgsVersion` is deprecated, use `lib.version` instead!" version;
# Whether we're being called by nix-shell.

View File

@ -1135,6 +1135,11 @@
github = "dtzWill";
name = "Will Dietz";
};
dysinger = {
email = "tim@dysinger.net";
github = "dysinger";
name = "Tim Dysinger";
};
dywedir = {
email = "dywedir@protonmail.ch";
github = "dywedir";
@ -2199,6 +2204,11 @@
github = "krav";
name = "Kristoffer Thømt Ravneberg";
};
kroell = {
email = "nixosmainter@makroell.de";
github = "rokk4";
name = "Matthias Axel Kröll";
};
kristoff3r = {
email = "k.soeholm@gmail.com";
github = "kristoff3r";
@ -2442,6 +2452,11 @@
github = "ma27";
name = "Maximilian Bosch";
};
ma9e = {
email = "sean@lfo.team";
github = "ma9e";
name = "Sean Haugh";
};
madjar = {
email = "georges.dubus@compiletoi.net";
github = "madjar";
@ -3042,7 +3057,7 @@
name = "Oliver Dunkl";
};
offline = {
email = "jakahudoklin@gmail.com";
email = "jaka@x-truder.net";
github = "offlinehacker";
name = "Jaka Hudoklin";
};
@ -3105,6 +3120,11 @@
github = "oyren";
name = "Moritz Scheuren";
};
pacien = {
email = "b4gx3q.nixpkgs@pacien.net";
github = "pacien";
name = "Pacien Tran-Girard";
};
paholg = {
email = "paho@paholg.com";
github = "paholg";
@ -3314,6 +3334,11 @@
github = "proglodyte";
name = "Proglodyte";
};
prusnak = {
email = "stick@gk2.sk";
github = "prusnak";
name = "Pavol Rusnak";
};
pshendry = {
email = "paul@pshendry.com";
github = "pshendry";
@ -4312,6 +4337,11 @@
github = "uri-canva";
name = "Uri Baghin";
};
uskudnik = {
email = "urban.skudnik@gmail.com";
github = "uskudnik";
name = "Urban Skudnik";
};
utdemir = {
email = "me@utdemir.com";
github = "utdemir";
@ -4648,6 +4678,11 @@
github = "maggesi";
name = "Marco Maggesi";
};
zachcoyle = {
email = "zach.coyle@gmail.com";
github = "zachcoyle";
name = "Zach Coyle";
};
zagy = {
email = "cz@flyingcircus.io";
github = "zagy";

View File

@ -4,7 +4,7 @@ all: manual-combined.xml format
.PHONY: debug
debug: generated manual-combined.xml
manual-combined.xml: generated *.xml
manual-combined.xml: generated *.xml **/*.xml
rm -f ./manual-combined.xml
nix-shell --packages xmloscopy \
--run "xmloscopy --docbook5 ./manual.xml ./manual-combined.xml"

View File

@ -52,4 +52,7 @@ $ ping -c1 10.233.4.2
networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
</programlisting>
</para>
<para>
You may need to restart your system for the changes to take effect.
</para>
</section>

View File

@ -73,7 +73,8 @@ Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
</para>
<para>
To change the configuration of the container, you can edit
There are several ways to change the configuration of the container. First,
on the host, you can edit
<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
and run
<screen>
@ -86,7 +87,8 @@ Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
<xref linkend="opt-services.httpd.enable"/> = true;
<xref linkend="opt-services.httpd.adminAddr"/> = "foo@example.org";
<xref linkend="opt-networking.firewall.allowedTCPPorts"/> = [ 80 ];
'
'
# curl http://$(nixos-container show-ip foo)/
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
</screen>
@ -95,13 +97,11 @@ Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
</para>
<para>
Note that in previous versions of NixOS (17.09 and earlier) one could also
use all nix-related commands (like <command>nixos-rebuild switch</command>)
from inside the container. However, since the release of Nix 2.0 this is not
supported anymore. Supporting Nix commands inside the container might be
possible again in future versions. See
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/40355">the github
issue</link> for tracking progress on this issue.
Alternatively, you can change the configuration from within the container
itself by running <command>nixos-rebuild switch</command> inside the
container. Note that the container by default does not have a copy of the
NixOS channel, so you should run <command>nix-channel --update</command>
first.
</para>
<para>

View File

@ -9,13 +9,12 @@
For systems without CD drive, the NixOS live CD can be booted from a USB
stick. You can use the <command>dd</command> utility to write the image:
<command>dd if=<replaceable>path-to-image</replaceable>
of=<replaceable>/dev/sdb</replaceable></command>. Be careful about specifying
of=<replaceable>/dev/sdX</replaceable></command>. Be careful about specifying
the correct drive; you can use the <command>lsblk</command> command to get a
list of block devices.
</para>
<para>
On macOS:
<note>
<title>On macOS</title>
<para>
<programlisting>
$ diskutil list
[..]
@ -26,43 +25,16 @@ $ diskutil unmountDisk diskN
Unmount of all volumes on diskN was successful
$ sudo dd bs=1m if=nix.iso of=/dev/rdiskN
</programlisting>
Using the 'raw' <command>rdiskN</command> device instead of
<command>diskN</command> completes in minutes instead of hours. After
<command>dd</command> completes, a GUI dialog "The disk you inserted was not
readable by this computer" will pop up, which can be ignored.
Using the 'raw' <command>rdiskN</command> device instead of
<command>diskN</command> completes in minutes instead of hours. After
<command>dd</command> completes, a GUI dialog "The disk you inserted was
not readable by this computer" will pop up, which can be ignored.
</para>
</note>
</para>
<para>
The <command>dd</command> utility will write the image verbatim to the drive,
making it the recommended option for both UEFI and non-UEFI installations.
For non-UEFI installations, you can alternatively use
<link xlink:href="http://unetbootin.sourceforge.net/">unetbootin</link>. If
you cannot use <command>dd</command> for a UEFI installation, you can also
mount the ISO, copy its contents verbatim to your drive, then either:
<itemizedlist>
<listitem>
<para>
Change the label of the disk partition to the label of the ISO (visible
with the blkid command), or
</para>
</listitem>
<listitem>
<para>
Edit <filename>loader/entries/nixos-livecd.conf</filename> on the drive
and change the <literal>root=</literal> field in the
<literal>options</literal> line to point to your drive (see the
documentation on <literal>root=</literal> in
<link xlink:href="https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt">
the kernel documentation</link> for more details).
</para>
</listitem>
<listitem>
<para>
If you want to load the contents of the ISO to ram after bootin (So you
can remove the stick after bootup) you can append the parameter
<literal>copytoram</literal> to the <literal>options</literal> field.
</para>
</listitem>
</itemizedlist>
</para>
</section>

View File

@ -4,60 +4,46 @@
version="5.0"
xml:id="sec-installation">
<title>Installing NixOS</title>
<para>
NixOS can be installed on BIOS or UEFI systems. The procedure for a UEFI
installation is by and large the same as a BIOS installation. The differences
are mentioned in the steps that follow.
</para>
<orderedlist>
<listitem>
<para>
Boot from the CD.
</para>
<variablelist>
<varlistentry>
<term>
UEFI systems
</term>
<listitem>
<para>
You should boot the live CD in UEFI mode (consult your specific
hardware's documentation for instructions). You may find the
<link xlink:href="http://www.rodsbooks.com/refind">rEFInd boot
manager</link> useful.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
<listitem>
<para>
The CD contains a basic NixOS installation. (It also contains Memtest86+,
useful if you want to test new hardware). When its finished booting, it
should have detected most of your hardware.
</para>
</listitem>
<listitem>
<para>
The NixOS manual is available on virtual console 8 (press Alt+F8 to access)
or by running <command>nixos-help</command>.
</para>
</listitem>
<listitem>
<para>
You get logged in as <literal>root</literal> (with empty password).
</para>
</listitem>
<listitem>
<para>
If you downloaded the graphical ISO image, you can run <command>systemctl
start display-manager</command> to start KDE. If you want to continue on
the terminal, you can use <command>loadkeys</command> to switch to your
preferred keyboard layout. (We even provide neo2 via <command>loadkeys de
neo</command>!)
</para>
</listitem>
<listitem>
<section xml:id="sec-installation-booting">
<title>Booting the system</title>
<para>
NixOS can be installed on BIOS or UEFI systems. The procedure for a UEFI
installation is by and large the same as a BIOS installation. The
differences are mentioned in the steps that follow.
</para>
<para>
The installation media can be burned to a CD, or now more commonly, "burned"
to a USB drive (see <xref linkend="sec-booting-from-usb"/>).
</para>
<para>
The installation media contains a basic NixOS installation. When its
finished booting, it should have detected most of your hardware.
</para>
<para>
The NixOS manual is available on virtual console 8 (press Alt+F8 to access)
or by running <command>nixos-help</command>.
</para>
<para>
You are logged-in automatically as <literal>root</literal>. (The
<literal>root</literal> user account has an empty password.)
</para>
<para>
If you downloaded the graphical ISO image, you can run <command>systemctl
start display-manager</command> to start KDE. If you want to continue on the
terminal, you can use <command>loadkeys</command> to switch to your
preferred keyboard layout. (We even provide neo2 via <command>loadkeys de
neo</command>!)
</para>
<section xml:id="sec-installation-booting-networking">
<title>Networking in the installer</title>
<para>
The boot process should have brought up networking (check <command>ip
a</command>). Networking is necessary for the installer, since it will
@ -65,58 +51,165 @@
binaries). Its best if you have a DHCP server on your network. Otherwise
configure networking manually using <command>ifconfig</command>.
</para>
<para>
To manually configure the network on the graphical installer, first disable
network-manager with <command>systemctl stop network-manager</command>.
</para>
<para>
To manually configure the wifi on the minimal installer, run
<command>wpa_supplicant -B -i interface -c &lt;(wpa_passphrase 'SSID'
'key')</command>.
</para>
</listitem>
<listitem>
<para>
If you would like to continue the installation from a different machine you
need to activate the SSH daemon via <literal>systemctl start
sshd</literal>. In order to be able to login you also need to set a
password for <literal>root</literal> using <literal>passwd</literal>.
</para>
</listitem>
<listitem>
</section>
</section>
<section xml:id="sec-installation-partitioning">
<title>Partitioning and formatting</title>
<para>
The NixOS installer doesnt do any partitioning or formatting, so you need
to do that yourself.
</para>
<para>
The NixOS installer ships with multiple partitioning tools. The examples
below use <command>parted</command>, but also provides
<command>fdisk</command>, <command>gdisk</command>,
<command>cfdisk</command>, and <command>cgdisk</command>.
</para>
<para>
The recommended partition scheme differs depending if the computer uses
<emphasis>Legacy Boot</emphasis> or <emphasis>UEFI</emphasis>.
</para>
<section xml:id="sec-installation-partitioning-UEFI">
<title>UEFI (GPT)</title>
<para>
The NixOS installer doesnt do any partitioning or formatting yet, so you
need to do that yourself. Use the following commands:
<itemizedlist>
Here's an example partition scheme for UEFI, using
<filename>/dev/sda</filename> as the device.
<note>
<para>
You can safely ignore <command>parted</command>'s informational message
about needing to update /etc/fstab.
</para>
</note>
</para>
<para>
<orderedlist>
<listitem>
<para>
For partitioning: <command>fdisk</command>.
<screen>
# fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
-- for UEFI systems only
> n # <lineannotation>(create a new partition for /boot)</lineannotation>
> 3 # <lineannotation>(make it a partition number 3)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> +512M # <lineannotation>(the size of the UEFI boot partition)</lineannotation>
> t # <lineannotation>(change the partition type ...)</lineannotation>
> 3 # <lineannotation>(... of the boot partition ...)</lineannotation>
> 1 # <lineannotation>(... to 'UEFI System')</lineannotation>
-- for BIOS or UEFI systems
> n # <lineannotation>(create a new partition for /swap)</lineannotation>
> 2 # <lineannotation>(make it a partition number 2)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> +8G # <lineannotation>(the size of the swap partition, set to whatever you like)</lineannotation>
> n # <lineannotation>(create a new partition for /)</lineannotation>
> 1 # <lineannotation>(make it a partition number 1)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation>
> a # <lineannotation>(make the partition bootable)</lineannotation>
> x # <lineannotation>(enter expert mode)</lineannotation>
> f # <lineannotation>(fix up the partition ordering)</lineannotation>
> r # <lineannotation>(exit expert mode)</lineannotation>
> w # <lineannotation>(write the partition table to disk and exit)</lineannotation></screen>
Create a <emphasis>GPT</emphasis> partition table.
<screen language="commands"># parted /dev/sda -- mklabel gpt</screen>
</para>
</listitem>
<listitem>
<para>
Add a <emphasis>swap</emphasis> partition. The size required will vary
according to needs, here a 8GiB one is created. The space left in front
(512MiB) will be used by the boot partition.
<screen language="commands"># parted /dev/sda -- mkpart primary linux-swap 512MiB 8.5GiB</screen>
<note>
<para>
The swap partition size rules are no different than for other Linux
distributions.
</para>
</note>
</para>
</listitem>
<listitem>
<para>
Next, add the <emphasis>root</emphasis> partition. This will fill the
remainder ending part of the disk.
<screen language="commands"># parted /dev/sda -- mkpart primary 8.5GiB -1MiB</screen>
</para>
</listitem>
<listitem>
<para>
Finally, the <emphasis>boot</emphasis> partition. NixOS by default uses
the ESP (EFI system partition) as its <emphasis>/boot</emphasis>
partition. It uses the initially reserved 512MiB at the start of the
disk.
<screen language="commands"># parted /dev/sda -- mkpart ESP fat32 1M 512MiB
# parted /dev/sda -- set 3 boot on</screen>
</para>
</listitem>
</orderedlist>
</para>
<para>
Once complete, you can follow with
<xref linkend="sec-installation-partitioning-formatting"/>.
</para>
</section>
<section xml:id="sec-installation-partitioning-MBR">
<title>Legacy Boot (MBR)</title>
<para>
Here's an example partition scheme for Legacy Boot, using
<filename>/dev/sda</filename> as the device.
<note>
<para>
You can safely ignore <command>parted</command>'s informational message
about needing to update /etc/fstab.
</para>
</note>
</para>
<para>
<orderedlist>
<listitem>
<para>
Create a <emphasis>MBR</emphasis> partition table.
<screen language="commands"># parted /dev/sda -- mklabel msdos</screen>
</para>
</listitem>
<listitem>
<para>
Add a <emphasis>swap</emphasis> partition. The size required will vary
according to needs, here a 8GiB one is created.
<screen language="commands"># parted /dev/sda -- mkpart primary linux-swap 1M 8GiB</screen>
<note>
<para>
The swap partition size rules are no different than for other Linux
distributions.
</para>
</note>
</para>
</listitem>
<listitem>
<para>
Finally, add the <emphasis>root</emphasis> partition. This will fill the
remainder of the disk.
<screen language="commands"># parted /dev/sda -- mkpart primary 8GiB -1s</screen>
</para>
</listitem>
</orderedlist>
</para>
<para>
Once complete, you can follow with
<xref linkend="sec-installation-partitioning-formatting"/>.
</para>
</section>
<section xml:id="sec-installation-partitioning-formatting">
<title>Formatting</title>
<para>
Use the following commands:
<itemizedlist>
<listitem>
<para>
For initialising Ext4 partitions: <command>mkfs.ext4</command>. It is
@ -169,242 +262,249 @@
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>
Mount the target file system on which NixOS should be installed on
<filename>/mnt</filename>, e.g.
</section>
</section>
<section xml:id="sec-installation-installing">
<title>Installing</title>
<orderedlist>
<listitem>
<para>
Mount the target file system on which NixOS should be installed on
<filename>/mnt</filename>, e.g.
<screen>
# mount /dev/disk/by-label/nixos /mnt
</screen>
</para>
</listitem>
<listitem>
<variablelist>
<varlistentry>
<term>
UEFI systems
</term>
<listitem>
<para>
Mount the boot file system on <filename>/mnt/boot</filename>, e.g.
</para>
</listitem>
<listitem>
<variablelist>
<varlistentry>
<term>
UEFI systems
</term>
<listitem>
<para>
Mount the boot file system on <filename>/mnt/boot</filename>, e.g.
<screen>
# mkdir -p /mnt/boot
# mount /dev/disk/by-label/boot /mnt/boot
</screen>
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
<listitem>
<para>
If your machine has a limited amount of memory, you may want to activate
swap devices now (<command>swapon
<replaceable>device</replaceable></command>). The installer (or rather, the
build actions that it may spawn) may need quite a bit of RAM, depending on
your configuration.
</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
<listitem>
<para>
If your machine has a limited amount of memory, you may want to activate
swap devices now (<command>swapon
<replaceable>device</replaceable></command>). The installer (or rather,
the build actions that it may spawn) may need quite a bit of RAM,
depending on your configuration.
<screen>
# swapon /dev/sda2</screen>
</para>
</listitem>
<listitem>
<para>
You now need to create a file
<filename>/mnt/etc/nixos/configuration.nix</filename> that specifies the
intended configuration of the system. This is because NixOS has a
<emphasis>declarative</emphasis> configuration model: you create or edit a
description of the desired configuration of your system, and then NixOS
takes care of making it happen. The syntax of the NixOS configuration file
is described in <xref linkend="sec-configuration-syntax"/>, while a list of
available configuration options appears in
<xref
</para>
</listitem>
<listitem>
<para>
You now need to create a file
<filename>/mnt/etc/nixos/configuration.nix</filename> that specifies the
intended configuration of the system. This is because NixOS has a
<emphasis>declarative</emphasis> configuration model: you create or edit a
description of the desired configuration of your system, and then NixOS
takes care of making it happen. The syntax of the NixOS configuration file
is described in <xref linkend="sec-configuration-syntax"/>, while a list
of available configuration options appears in
<xref
linkend="ch-options"/>. A minimal example is shown in
<xref
<xref
linkend="ex-config"/>.
</para>
<para>
The command <command>nixos-generate-config</command> can generate an
initial configuration file for you:
</para>
<para>
The command <command>nixos-generate-config</command> can generate an
initial configuration file for you:
<screen>
# nixos-generate-config --root /mnt</screen>
You should then edit <filename>/mnt/etc/nixos/configuration.nix</filename>
to suit your needs:
You should then edit <filename>/mnt/etc/nixos/configuration.nix</filename>
to suit your needs:
<screen>
# nano /mnt/etc/nixos/configuration.nix
</screen>
If youre using the graphical ISO image, other editors may be available
(such as <command>vim</command>). If you have network access, you can also
install other editors — for instance, you can install Emacs by running
<literal>nix-env -i emacs</literal>.
</para>
<variablelist>
<varlistentry>
<term>
BIOS systems
</term>
<listitem>
<para>
You <emphasis>must</emphasis> set the option
<xref linkend="opt-boot.loader.grub.device"/> to specify on which disk
the GRUB boot loader is to be installed. Without it, NixOS cannot boot.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
UEFI systems
</term>
<listitem>
<para>
You <emphasis>must</emphasis> set the option
<xref linkend="opt-boot.loader.systemd-boot.enable"/> to
<literal>true</literal>. <command>nixos-generate-config</command> should
do this automatically for new configurations when booted in UEFI mode.
</para>
<para>
You may want to look at the options starting with
<option><link linkend="opt-boot.loader.efi.canTouchEfiVariables">boot.loader.efi</link></option>
and
<option><link linkend="opt-boot.loader.systemd-boot.enable">boot.loader.systemd</link></option>
as well.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
If there are other operating systems running on the machine before
installing NixOS, the <xref linkend="opt-boot.loader.grub.useOSProber"/>
option can be set to <literal>true</literal> to automatically add them to
the grub menu.
</para>
<para>
Another critical option is <option>fileSystems</option>, specifying the
file systems that need to be mounted by NixOS. However, you typically
dont need to set it yourself, because
<command>nixos-generate-config</command> sets it automatically in
<filename>/mnt/etc/nixos/hardware-configuration.nix</filename> from your
currently mounted file systems. (The configuration file
<filename>hardware-configuration.nix</filename> is included from
<filename>configuration.nix</filename> and will be overwritten by future
invocations of <command>nixos-generate-config</command>; thus, you
generally should not modify it.)
</para>
<note>
<para>
Depending on your hardware configuration or type of file system, you may
need to set the option <option>boot.initrd.kernelModules</option> to
include the kernel modules that are necessary for mounting the root file
system, otherwise the installed system will not be able to boot. (If this
happens, boot from the CD again, mount the target file system on
<filename>/mnt</filename>, fix
<filename>/mnt/etc/nixos/configuration.nix</filename> and rerun
<filename>nixos-install</filename>.) In most cases,
<command>nixos-generate-config</command> will figure out the required
modules.
If youre using the graphical ISO image, other editors may be available
(such as <command>vim</command>). If you have network access, you can also
install other editors — for instance, you can install Emacs by running
<literal>nix-env -i emacs</literal>.
</para>
</note>
</listitem>
<listitem>
<para>
Do the installation:
<variablelist>
<varlistentry>
<term>
BIOS systems
</term>
<listitem>
<para>
You <emphasis>must</emphasis> set the option
<xref linkend="opt-boot.loader.grub.device"/> to specify on which disk
the GRUB boot loader is to be installed. Without it, NixOS cannot boot.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
UEFI systems
</term>
<listitem>
<para>
You <emphasis>must</emphasis> set the option
<xref linkend="opt-boot.loader.systemd-boot.enable"/> to
<literal>true</literal>. <command>nixos-generate-config</command>
should do this automatically for new configurations when booted in UEFI
mode.
</para>
<para>
You may want to look at the options starting with
<option><link linkend="opt-boot.loader.efi.canTouchEfiVariables">boot.loader.efi</link></option>
and
<option><link linkend="opt-boot.loader.systemd-boot.enable">boot.loader.systemd</link></option>
as well.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
If there are other operating systems running on the machine before
installing NixOS, the <xref linkend="opt-boot.loader.grub.useOSProber"/>
option can be set to <literal>true</literal> to automatically add them to
the grub menu.
</para>
<para>
Another critical option is <option>fileSystems</option>, specifying the
file systems that need to be mounted by NixOS. However, you typically
dont need to set it yourself, because
<command>nixos-generate-config</command> sets it automatically in
<filename>/mnt/etc/nixos/hardware-configuration.nix</filename> from your
currently mounted file systems. (The configuration file
<filename>hardware-configuration.nix</filename> is included from
<filename>configuration.nix</filename> and will be overwritten by future
invocations of <command>nixos-generate-config</command>; thus, you
generally should not modify it.)
</para>
<note>
<para>
Depending on your hardware configuration or type of file system, you may
need to set the option <option>boot.initrd.kernelModules</option> to
include the kernel modules that are necessary for mounting the root file
system, otherwise the installed system will not be able to boot. (If this
happens, boot from the installation media again, mount the target file
system on <filename>/mnt</filename>, fix
<filename>/mnt/etc/nixos/configuration.nix</filename> and rerun
<filename>nixos-install</filename>.) In most cases,
<command>nixos-generate-config</command> will figure out the required
modules.
</para>
</note>
</listitem>
<listitem>
<para>
Do the installation:
<screen>
# nixos-install</screen>
Cross fingers. If this fails due to a temporary problem (such as a network
issue while downloading binaries from the NixOS binary cache), you can just
re-run <command>nixos-install</command>. Otherwise, fix your
<filename>configuration.nix</filename> and then re-run
<command>nixos-install</command>.
</para>
<para>
As the last step, <command>nixos-install</command> will ask you to set the
password for the <literal>root</literal> user, e.g.
Cross fingers. If this fails due to a temporary problem (such as a network
issue while downloading binaries from the NixOS binary cache), you can
just re-run <command>nixos-install</command>. Otherwise, fix your
<filename>configuration.nix</filename> and then re-run
<command>nixos-install</command>.
</para>
<para>
As the last step, <command>nixos-install</command> will ask you to set the
password for the <literal>root</literal> user, e.g.
<screen>
setting root password...
Enter new UNIX password: ***
Retype new UNIX password: ***
</screen>
<note>
<para>
For unattended installations, it is possible to use
<command>nixos-install --no-root-passwd</command> in order to disable the
password prompt entirely.
</para>
</note>
</para>
</listitem>
<listitem>
<para>
If everything went well:
Retype new UNIX password: ***</screen>
<note>
<para>
For unattended installations, it is possible to use
<command>nixos-install --no-root-passwd</command> in order to disable
the password prompt entirely.
</para>
</note>
</para>
</listitem>
<listitem>
<para>
If everything went well:
<screen>
# reboot</screen>
</para>
</listitem>
<listitem>
<para>
You should now be able to boot into the installed NixOS. The GRUB boot menu
shows a list of <emphasis>available configurations</emphasis> (initially
just one). Every time you change the NixOS configuration (see
<link
# reboot</screen>
</para>
</listitem>
<listitem>
<para>
You should now be able to boot into the installed NixOS. The GRUB boot
menu shows a list of <emphasis>available configurations</emphasis>
(initially just one). Every time you change the NixOS configuration (see
<link
linkend="sec-changing-config">Changing Configuration</link>
), a new item is added to the menu. This allows you to easily roll back to
a previous configuration if something goes wrong.
</para>
<para>
You should log in and change the <literal>root</literal> password with
<command>passwd</command>.
</para>
<para>
Youll probably want to create some user accounts as well, which can be
done with <command>useradd</command>:
), a new item is added to the menu. This allows you to easily roll back to
a previous configuration if something goes wrong.
</para>
<para>
You should log in and change the <literal>root</literal> password with
<command>passwd</command>.
</para>
<para>
Youll probably want to create some user accounts as well, which can be
done with <command>useradd</command>:
<screen>
$ useradd -c 'Eelco Dolstra' -m eelco
$ passwd eelco</screen>
</para>
<para>
You may also want to install some software. For instance,
</para>
<para>
You may also want to install some software. For instance,
<screen>
$ nix-env -qa \*</screen>
shows what packages are available, and
shows what packages are available, and
<screen>
$ nix-env -i w3m</screen>
install the <literal>w3m</literal> browser.
</para>
</listitem>
</orderedlist>
<para>
To summarise, <xref linkend="ex-install-sequence" /> shows a typical sequence
of commands for installing NixOS on an empty hard drive (here
<filename>/dev/sda</filename>). <xref linkend="ex-config"
install the <literal>w3m</literal> browser.
</para>
</listitem>
</orderedlist>
</section>
<section xml:id="sec-installation-summary">
<title>Installation summary</title>
<para>
To summarise, <xref linkend="ex-install-sequence" /> shows a typical
sequence of commands for installing NixOS on an empty hard drive (here
<filename>/dev/sda</filename>). <xref linkend="ex-config"
/> shows a
corresponding configuration Nix expression.
</para>
<example xml:id='ex-install-sequence'>
<title>Commands for Installing NixOS on <filename>/dev/sda</filename></title>
<screen>
# fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
-- for UEFI systems only
> n # <lineannotation>(create a new partition for /boot)</lineannotation>
> 3 # <lineannotation>(make it a partition number 3)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> +512M # <lineannotation>(the size of the UEFI boot partition)</lineannotation>
> t # <lineannotation>(change the partition type ...)</lineannotation>
> 3 # <lineannotation>(... of the boot partition ...)</lineannotation>
> 1 # <lineannotation>(... to 'UEFI System')</lineannotation>
-- for BIOS or UEFI systems
> n # <lineannotation>(create a new partition for /swap)</lineannotation>
> 2 # <lineannotation>(make it a partition number 2)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> +8G # <lineannotation>(the size of the swap partition)</lineannotation>
> n # <lineannotation>(create a new partition for /)</lineannotation>
> 1 # <lineannotation>(make it a partition number 1)</lineannotation>
> # <lineannotation>(press enter to accept the default)</lineannotation>
> # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation>
> a # <lineannotation>(make the partition bootable)</lineannotation>
> x # <lineannotation>(enter expert mode)</lineannotation>
> f # <lineannotation>(fix up the partition ordering)</lineannotation>
> r # <lineannotation>(exit expert mode)</lineannotation>
> w # <lineannotation>(write the partition table to disk and exit)</lineannotation>
corresponding configuration Nix expression.
</para>
<example xml:id="ex-partition-scheme-MBR">
<title>Example partition schemes for NixOS on <filename>/dev/sda</filename> (MBR)</title>
<screen language="commands">
# parted /dev/sda -- mklabel msdos
# parted /dev/sda -- mkpart primary linux-swap 1M 8GiB
# parted /dev/sda -- mkpart primary 8GiB -1s</screen>
</example>
<example xml:id="ex-partition-scheme-UEFI">
<title>Example partition schemes for NixOS on <filename>/dev/sda</filename> (UEFI)</title>
<screen language="commands">
# parted /dev/sda -- mklabel gpt
# parted /dev/sda -- mkpart primary linux-swap 512MiB 8.5GiB
# parted /dev/sda -- mkpart primary 8.5GiB -1MiB
# parted /dev/sda -- mkpart ESP fat32 1M 512MiB
# parted /dev/sda -- set 3 boot on</screen>
</example>
<example xml:id="ex-install-sequence">
<title>Commands for Installing NixOS on <filename>/dev/sda</filename></title>
<para>
With a partitioned disk.
<screen language="commands">
# mkfs.ext4 -L nixos /dev/sda1
# mkswap -L swap /dev/sda2
# swapon /dev/sda2
@ -416,9 +516,11 @@ $ nix-env -i w3m</screen>
# nano /mnt/etc/nixos/configuration.nix
# nixos-install
# reboot</screen>
</example>
<example xml:id='ex-config'>
<title>NixOS Configuration</title>
</para>
</example>
<example xml:id='ex-config'>
<title>NixOS Configuration</title>
<screen>
{ config, pkgs, ... }: {
imports = [
@ -438,10 +540,19 @@ $ nix-env -i w3m</screen>
services.sshd.enable = true;
}
</screen>
</example>
<xi:include href="installing-usb.xml" />
<xi:include href="installing-pxe.xml" />
<xi:include href="installing-virtualbox-guest.xml" />
<xi:include href="installing-from-other-distro.xml" />
<xi:include href="installing-behind-a-proxy.xml" />
</example>
</section>
<section xml:id="sec-installation-additional-notes">
<title>Additional installation notes</title>
<xi:include href="installing-usb.xml" />
<xi:include href="installing-pxe.xml" />
<xi:include href="installing-virtualbox-guest.xml" />
<xi:include href="installing-from-other-distro.xml" />
<xi:include href="installing-behind-a-proxy.xml" />
</section>
</chapter>

View File

@ -3,7 +3,7 @@
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-18.09">
<title>Release 18.09 (“Jellyfish”, 2018/09/??)</title>
<title>Release 18.09 (“Jellyfish”, 2018/10/05)</title>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
@ -14,7 +14,45 @@
<para>
In addition to numerous new and upgraded packages, this release has the
following highlights:
following notable updates:
</para>
<itemizedlist>
<listitem>
<para>
End of support is planned for end of April 2019, handing over to 19.03.
</para>
</listitem>
<listitem>
<para>
Platform support: x86_64-linux and x86_64-darwin as always. Support for
aarch64-linux is as with the previous releases, not equivalent to the
x86-64-linux release, but with efforts to reach parity.
</para>
</listitem>
<listitem>
<para>
Nix has been updated to 2.1; see its
<link xlink:href="https://nixos.org/nix/manual/#ssec-relnotes-2.1">release
notes</link>.
</para>
</listitem>
<listitem>
<para>
Core versions: linux: 4.14 LTS (unchanged), glibc: 2.26 → 2.27, gcc: 7
(unchanged), systemd: 237 → 239.
</para>
</listitem>
<listitem>
<para>
Desktop version changes: gnome: 3.26 → 3.28, (KDE) plasma-desktop: 5.12
→ 5.13.
</para>
</listitem>
</itemizedlist>
<para>
Notable changes and additions for 18.09 include:
</para>
<itemizedlist>
@ -70,7 +108,7 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
<title>New Services</title>
<para>
The following new services were added since the last release:
A curated selection of new services that were added since the last release:
</para>
<itemizedlist>
@ -125,6 +163,303 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
</para>
</listitem>
</itemizedlist>
<para>
Every new services:
</para>
<itemizedlist>
<listitem>
<para>
<literal>./config/xdg/autostart.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./config/xdg/icons.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./config/xdg/menus.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./config/xdg/mime.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./hardware/brightnessctl.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./hardware/onlykey.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./hardware/video/uvcvideo/default.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./misc/documentation.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/firejail.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/iftop.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/sedutil.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/singularity.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/xss-lock.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./programs/zsh/zsh-autosuggestions.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/admin/oxidized.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/backup/duplicati.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/backup/restic.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/backup/restic-rest-server.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/cluster/hadoop/default.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/databases/aerospike.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/databases/monetdb.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/desktops/bamf.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/desktops/flatpak.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/desktops/zeitgeist.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/development/bloop.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/development/jupyter/default.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/hardware/lcd.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/hardware/undervolt.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/clipmenu.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/gitweb.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/serviio.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/safeeyes.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/sysprof.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/misc/weechat.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/monitoring/datadog-agent.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/monitoring/incron.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/dnsdist.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/freeradius.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/hans.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/morty.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/ndppd.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/ocserv.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/owamp.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/quagga.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/shadowsocks.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/stubby.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/networking/zeronet.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/security/certmgr.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/security/cfssl.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/security/oauth2_proxy_nginx.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-apps/virtlyst.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-apps/youtrack.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-servers/hitch/default.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-servers/hydron.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-servers/meguca.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./services/web-servers/nginx/gitweb.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./virtualisation/kvmgt.nix</literal>
</para>
</listitem>
<listitem>
<para>
<literal>./virtualisation/qemu-guest-agent.nix</literal>
</para>
</listitem>
</itemizedlist>
</section>
<section xmlns="http://docbook.org/ns/docbook"

View File

@ -105,6 +105,14 @@
<varname>rabbitmq-server</varname>.
</para>
</listitem>
<listitem>
<para>
The <literal>light</literal> module no longer uses setuid binaries, but
udev rules. As a consequence users of that module have to belong to the
<literal>video</literal> group in order to use the executable
(i.e. <literal>users.users.yourusername.extraGroups = ["video"];</literal>).
</para>
</listitem>
</itemizedlist>
</section>

View File

@ -129,17 +129,17 @@ in
message = "Option driSupport32Bit only makes sense on a 64-bit system.";
};
system.activationScripts.setup-opengl =
''
ln -sfn ${package} /run/opengl-driver
${if pkgs.stdenv.isi686 then ''
ln -sfn opengl-driver /run/opengl-driver-32
'' else if cfg.driSupport32Bit then ''
ln -sfn ${package32} /run/opengl-driver-32
'' else ''
rm -f /run/opengl-driver-32
''}
'';
systemd.tmpfiles.rules = [
"L+ /run/opengl-driver - - - - ${package}"
(
if pkgs.stdenv.isi686 then
"L+ /run/opengl-driver-32 - - - - opengl-driver"
else if cfg.driSupport32Bit then
"L+ /run/opengl-driver-32 - - - - ${package32}"
else
"r /run/opengl-driver-32"
)
];
environment.sessionVariables.LD_LIBRARY_PATH =
[ "/run/opengl-driver/lib" ] ++ optional cfg.driSupport32Bit "/run/opengl-driver-32/lib";

View File

@ -26,9 +26,73 @@ let
nvidia_libs32 = (nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; };
enabled = nvidia_x11 != null;
cfg = config.hardware.nvidia;
optimusCfg = cfg.optimus_prime;
in
{
options = {
hardware.nvidia.modesetting.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable kernel modesetting when using the NVIDIA proprietary driver.
Enabling this fixes screen tearing when using Optimus via PRIME (see
<option>hardware.nvidia.optimus_prime.enable</option>. This is not enabled
by default because it is not officially supported by NVIDIA and would not
work with SLI.
'';
};
hardware.nvidia.optimus_prime.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
If enabled, the NVIDIA GPU will be always on and used for all rendering,
while enabling output to displays attached only to the integrated Intel GPU
without a multiplexer.
Note that this option only has any effect if the "nvidia" driver is specified
in <option>services.xserver.videoDrivers</option>, and it should preferably
be the only driver there.
If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
specified (<option>hardware.nvidia.optimus_prime.nvidiaBusId</option> and
<option>hardware.nvidia.optimus_prime.intelBusId</option>).
If you enable this, you may want to also enable kernel modesetting for the
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
to prevent tearing.
Note that this configuration will only be successful when a display manager
for which the <option>services.xserver.displayManager.setupCommands</option>
option is supported is used; notably, SLiM is not supported.
'';
};
hardware.nvidia.optimus_prime.nvidiaBusId = lib.mkOption {
type = lib.types.string;
default = "";
example = "PCI:1:0:0";
description = ''
Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
'';
};
hardware.nvidia.optimus_prime.intelBusId = lib.mkOption {
type = lib.types.string;
default = "";
example = "PCI:0:2:0";
description = ''
Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
'';
};
};
config = mkIf enabled {
assertions = [
@ -36,15 +100,61 @@ in
assertion = config.services.xserver.displayManager.gdm.wayland;
message = "NVidia drivers don't support wayland";
}
{
assertion = !optimusCfg.enable ||
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
message = ''
When NVIDIA Optimus via PRIME is enabled, the GPU bus IDs must configured.
'';
}
];
services.xserver.drivers = singleton
{ name = "nvidia"; modules = [ nvidia_x11.bin ]; libPath = [ nvidia_x11 ]; };
# If Optimus/PRIME is enabled, we:
# - Specify the configured NVIDIA GPU bus ID in the Device section for the
# "nvidia" driver.
# - Add the AllowEmptyInitialConfiguration option to the Screen section for the
# "nvidia" driver, in order to allow the X server to start without any outputs.
# - Add a separate Device section for the Intel GPU, using the "modesetting"
# driver and with the configured BusID.
# - Reference that Device section from the ServerLayout section as an inactive
# device.
# - Configure the display manager to run specific `xrandr` commands which will
# configure/enable displays connected to the Intel GPU.
services.xserver.screenSection =
services.xserver.drivers = singleton {
name = "nvidia";
modules = [ nvidia_x11.bin ];
libPath = [ nvidia_x11 ];
deviceSection = optionalString optimusCfg.enable
''
BusID "${optimusCfg.nvidiaBusId}"
'';
screenSection =
''
Option "RandRRotation" "on"
${optionalString optimusCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
'';
};
services.xserver.extraConfig = optionalString optimusCfg.enable
''
Option "RandRRotation" "on"
Section "Device"
Identifier "nvidia-optimus-intel"
Driver "modesetting"
BusID "${optimusCfg.intelBusId}"
Option "AccelMethod" "none"
EndSection
'';
services.xserver.serverLayoutSection = optionalString optimusCfg.enable
''
Inactive "nvidia-optimus-intel"
'';
services.xserver.displayManager.setupCommands = optionalString optimusCfg.enable ''
# Added by nvidia configuration module for Optimus/PRIME.
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0
${pkgs.xorg.xrandr}/bin/xrandr --auto
'';
environment.etc."nvidia/nvidia-application-profiles-rc" = mkIf nvidia_x11.useProfiles {
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
@ -62,6 +172,8 @@ in
boot.kernelModules = [ "nvidia-uvm" ] ++
lib.optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
# If requested enable modesetting via kernel parameter.
boot.kernelParams = optional cfg.modesetting.enable "nvidia-drm.modeset=1";
# Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
services.udev.extraRules =

View File

@ -277,8 +277,7 @@ if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") {
# Also for Hyper-V.
if ($virt eq "microsoft") {
push @initrdAvailableKernelModules, "hv_storvsc";
$videoDriver = "fbdev";
push @attrs, "virtualisation.hypervGuest.enable = true;"
}

View File

@ -82,7 +82,7 @@ evalNix(){
set -e
if test $exit_code -eq 0; then
cat <<EOF
sed '/^warning: Nix search path/d' <<EOF
$result
EOF
return 0;
@ -90,7 +90,7 @@ EOF
sed -n '
/^error/ { s/, at (string):[0-9]*:[0-9]*//; p; };
/^warning: Nix search path/ { p; };
' <<EOF
' >&2 <<EOF
$result
EOF
exit_code=1

View File

@ -5,7 +5,6 @@ with lib;
let
cfg = config.system.nixos;
revisionFile = "${toString pkgs.path}/.git-revision";
gitRepo = "${toString pkgs.path}/.git";
gitCommitId = lib.substring 0 7 (commitIdFromGitRepo gitRepo);
in
@ -37,9 +36,7 @@ in
nixos.revision = mkOption {
internal = true;
type = types.str;
default = if pathIsDirectory gitRepo then commitIdFromGitRepo gitRepo
else if pathExists revisionFile then fileContents revisionFile
else "master";
default = lib.trivial.revisionWithDefault "master";
description = "The Git revision from which this NixOS configuration was built.";
};

View File

@ -284,6 +284,7 @@
./services/hardware/tlp.nix
./services/hardware/thinkfan.nix
./services/hardware/trezord.nix
./services/hardware/triggerhappy.nix
./services/hardware/u2f.nix
./services/hardware/udev.nix
./services/hardware/udisks2.nix
@ -690,6 +691,7 @@
./services/web-apps/codimd.nix
./services/web-apps/frab.nix
./services/web-apps/mattermost.nix
./services/web-apps/nextcloud.nix
./services/web-apps/nexus.nix
./services/web-apps/pgpkeyserver-lite.nix
./services/web-apps/matomo.nix

View File

@ -33,7 +33,7 @@ let
'';
bashAliases = concatStringsSep "\n" (
mapAttrsFlatten (k: v: "alias ${k}='${v}'") cfg.shellAliases
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}") cfg.shellAliases
);
in

View File

@ -13,7 +13,8 @@ in
default = false;
type = types.bool;
description = ''
Whether to install Light backlight control with setuid wrapper.
Whether to install Light backlight control command
and udev rules granting access to members of the "video" group.
'';
};
};
@ -21,6 +22,6 @@ in
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.light ];
security.wrappers.light.source = "${pkgs.light.out}/bin/light";
services.udev.packages = [ pkgs.light ];
};
}

View File

@ -548,6 +548,13 @@ in
environment.etc =
mapAttrsToList (n: v: makePAMService v) config.security.pam.services;
systemd.tmpfiles.rules = optionals
(any (s: s.updateWtmp) (attrValues config.security.pam.services))
[
"f /var/log/wtmp"
"f /var/log/lastlog"
];
security.pam.services =
{ other.text =
''

View File

@ -88,11 +88,11 @@ in
"polkit-agent-helper-1".source = "${pkgs.polkit.out}/lib/polkit-1/polkit-agent-helper-1";
};
system.activationScripts.polkit =
''
# Probably no more needed, clean up
rm -rf /var/lib/{polkit-1,PolicyKit}
'';
systemd.tmpfiles.rules = [
# Probably no more needed, clean up
"R /var/lib/polkit-1"
"R /var/lib/PolicyKit"
];
users.users.polkituser = {
description = "PolKit daemon";

View File

@ -4,22 +4,7 @@ with lib;
let
cfg = config.services.psd;
configFile = ''
${optionalString (cfg.users != [ ]) ''
USERS="${concatStringsSep " " cfg.users}"
''}
${optionalString (cfg.browsers != [ ]) ''
BROWSERS="${concatStringsSep " " cfg.browsers}"
''}
${optionalString (cfg.volatile != "") "VOLATILE=${cfg.volatile}"}
${optionalString (cfg.daemonFile != "") "DAEMON_FILE=${cfg.daemonFile}"}
'';
in {
options.services.psd = with types; {
enable = mkOption {
type = bool;
@ -28,32 +13,6 @@ in {
Whether to enable the Profile Sync daemon.
'';
};
users = mkOption {
type = listOf str;
default = [ ];
example = [ "demo" ];
description = ''
A list of users whose browser profiles should be sync'd to tmpfs.
'';
};
browsers = mkOption {
type = listOf str;
default = [ ];
example = [ "chromium" "firefox" ];
description = ''
A list of browsers to sync. Available choices are:
chromium chromium-dev conkeror.mozdev.org epiphany firefox
firefox-trunk google-chrome google-chrome-beta google-chrome-unstable
heftig-aurora icecat luakit midori opera opera-developer opera-beta
qupzilla palemoon rekonq seamonkey
An empty list will enable all browsers.
'';
};
resyncTimer = mkOption {
type = str;
default = "1h";
@ -66,80 +25,53 @@ in {
omitted.
'';
};
volatile = mkOption {
type = str;
default = "/run/psd-profiles";
description = ''
The directory where browser profiles should reside(this should be
mounted as a tmpfs). Do not include a trailing backslash.
'';
};
daemonFile = mkOption {
type = str;
default = "/run/psd";
description = ''
Where the pid and backup configuration files will be stored.
'';
};
};
config = mkIf cfg.enable {
assertions = [
{ assertion = cfg.users != [];
message = "services.psd.users must contain at least one user";
}
];
systemd = {
services = {
psd = {
description = "Profile Sync daemon";
wants = [ "psd-resync.service" "local-fs.target" ];
wantedBy = [ "multi-user.target" ];
preStart = "mkdir -p ${cfg.volatile}";
path = with pkgs; [ glibc rsync gawk ];
unitConfig = {
RequiresMountsFor = [ "/home/" ];
user = {
services = {
psd = {
enable = true;
description = "Profile Sync daemon";
wants = [ "psd-resync.service" "local-fs.target" ];
wantedBy = [ "default.target" ];
path = with pkgs; [ rsync kmod gawk nettools profile-sync-daemon ];
unitConfig = {
RequiresMountsFor = [ "/home/" ];
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon sync";
ExecStop = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon unsync";
};
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = "yes";
ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon sync";
ExecStop = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon unsync";
psd-resync = {
enable = true;
description = "Timed profile resync";
after = [ "psd.service" ];
wants = [ "psd-resync.timer" ];
partOf = [ "psd.service" ];
wantedBy = [ "default.target" ];
path = with pkgs; [ rsync kmod gawk nettools profile-sync-daemon ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon resync";
};
};
};
psd-resync = {
description = "Timed profile resync";
after = [ "psd.service" ];
wants = [ "psd-resync.timer" ];
partOf = [ "psd.service" ];
timers.psd-resync = {
description = "Timer for profile sync daemon - ${cfg.resyncTimer}";
partOf = [ "psd-resync.service" "psd.service" ];
path = with pkgs; [ glibc rsync gawk ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon resync";
timerConfig = {
OnUnitActiveSec = "${cfg.resyncTimer}";
};
};
};
timers.psd-resync = {
description = "Timer for profile sync daemon - ${cfg.resyncTimer}";
partOf = [ "psd-resync.service" "psd.service" ];
timerConfig = {
OnUnitActiveSec = "${cfg.resyncTimer}";
};
};
};
environment.etc."psd.conf".text = configFile;
};
}

View File

@ -0,0 +1,114 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.triggerhappy;
socket = "/run/thd.socket";
configFile = pkgs.writeText "triggerhappy.conf" ''
${concatMapStringsSep "\n"
({ keys, event, cmd, ... }:
''${concatMapStringsSep "+" (x: "KEY_" + x) keys} ${toString { press = 1; hold = 2; release = 0; }.${event}} ${cmd}''
)
cfg.bindings}
${cfg.extraConfig}
'';
bindingCfg = { config, ... }: {
options = {
keys = mkOption {
type = types.listOf types.str;
description = "List of keys to match. Key names as defined in linux/input-event-codes.h";
};
event = mkOption {
type = types.enum ["press" "hold" "release"];
default = "press";
description = "Event to match.";
};
cmd = mkOption {
type = types.str;
description = "What to run.";
};
};
};
in
{
###### interface
options = {
services.triggerhappy = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable the <command>triggerhappy</command> hotkey daemon.
'';
};
bindings = mkOption {
type = types.listOf (types.submodule bindingCfg);
default = [];
example = lib.literalExample ''
[ { keys = ["PLAYPAUSE"]; cmd = "''${pkgs.mpc_cli}/bin/mpc -q toggle"; } ]
'';
description = ''
Key bindings for <command>triggerhappy</command>.
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Literal contents to append to the end of <command>triggerhappy</command> configuration file.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
systemd.sockets.triggerhappy = {
description = "Triggerhappy Socket";
wantedBy = [ "sockets.target" ];
socketConfig.ListenDatagram = socket;
};
systemd.services.triggerhappy = {
wantedBy = [ "multi-user.target" ];
after = [ "local-fs.target" ];
description = "Global hotkey daemon";
serviceConfig = {
ExecStart = "${pkgs.triggerhappy}/bin/thd --user nobody --socket ${socket} --triggers ${configFile} --deviceglob /dev/input/event*";
};
};
services.udev.packages = lib.singleton (pkgs.writeTextFile {
name = "triggerhappy-udev-rules";
destination = "/etc/udev/rules.d/61-triggerhappy.rules";
text = ''
ACTION=="add", SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{name}!="triggerhappy", \
RUN+="${pkgs.triggerhappy}/bin/th-cmd --socket ${socket} --passfd --udev"
'';
});
};
}

View File

@ -55,7 +55,7 @@ in
User = cfg.user;
Group = cfg.group;
PermissionsStartOnly = "true";
ExecStart = "${pkgs.emby}/bin/MediaBrowser.Server.Mono";
ExecStart = "${pkgs.emby}/bin/emby -programdata ${cfg.dataDir}";
Restart = "on-failure";
};
};

View File

@ -9,6 +9,15 @@ let
if cfg.configText != null then
pkgs.writeText "alertmanager.yml" cfg.configText
else mkConfigFile;
cmdlineArgs = cfg.extraFlags ++ [
"--config.file ${alertmanagerYml}"
"--web.listen-address ${cfg.listenAddress}:${toString cfg.port}"
"--log.level ${cfg.logLevel}"
] ++ (optional (cfg.webExternalUrl != null)
"--web.external-url ${cfg.webExternalUrl}"
) ++ (optional (cfg.logFormat != null)
"--log.format ${cfg.logFormat}"
);
in {
options = {
services.prometheus.alertmanager = {
@ -99,6 +108,14 @@ in {
Open port in firewall for incoming connections.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching the Alertmanager.
'';
};
};
};
@ -111,11 +128,7 @@ in {
after = [ "network.target" ];
script = ''
${pkgs.prometheus-alertmanager.bin}/bin/alertmanager \
--config.file ${alertmanagerYml} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--log.level ${cfg.logLevel} \
${optionalString (cfg.webExternalUrl != null) ''--web.external-url ${cfg.webExternalUrl} \''}
${optionalString (cfg.logFormat != null) "--log.format ${cfg.logFormat}"}
${concatStringsSep " \\\n " cmdlineArgs}
'';
serviceConfig = {

View File

@ -60,10 +60,10 @@ in
DynamicUser = true;
ExecStart = ''
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
-config.file ${configFile} \
-log.format ${cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--config.file=${configFile} \
--log.format=${cfg.logFormat} \
--log.level=${cfg.logLevel} \
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};

View File

@ -7,9 +7,10 @@ let
cfg = config.services.bitlbee;
bitlbeeUid = config.ids.uids.bitlbee;
bitlbeePkg = if cfg.libpurple_plugins == []
then pkgs.bitlbee
else pkgs.bitlbee.override { enableLibPurple = true; };
bitlbeePkg = pkgs.bitlbee.override {
enableLibPurple = cfg.libpurple_plugins != [];
enablePam = cfg.authBackend == "pam";
};
bitlbeeConfig = pkgs.writeText "bitlbee.conf"
''
@ -20,6 +21,7 @@ let
DaemonInterface = ${cfg.interface}
DaemonPort = ${toString cfg.portNumber}
AuthMode = ${cfg.authMode}
AuthBackend = ${cfg.authBackend}
Plugindir = ${pkgs.bitlbee-plugins cfg.plugins}/lib/bitlbee
${lib.optionalString (cfg.hostName != "") "HostName = ${cfg.hostName}"}
${lib.optionalString (cfg.protocols != "") "Protocols = ${cfg.protocols}"}
@ -70,6 +72,16 @@ in
'';
};
authBackend = mkOption {
default = "storage";
type = types.enum [ "storage" "pam" ];
description = ''
How users are authenticated
storage -- save passwords internally
pam -- Linux PAM authentication
'';
};
authMode = mkOption {
default = "Open";
type = types.enum [ "Open" "Closed" "Registered" ];
@ -147,23 +159,22 @@ in
###### implementation
config = mkIf config.services.bitlbee.enable {
users.users = singleton
{ name = "bitlbee";
config = mkMerge [
(mkIf config.services.bitlbee.enable {
users.users = singleton {
name = "bitlbee";
uid = bitlbeeUid;
description = "BitlBee user";
home = "/var/lib/bitlbee";
createHome = true;
};
users.groups = singleton
{ name = "bitlbee";
users.groups = singleton {
name = "bitlbee";
gid = config.ids.gids.bitlbee;
};
systemd.services.bitlbee =
{
systemd.services.bitlbee = {
environment.PURPLE_PLUGIN_PATH = purple_plugin_path;
description = "BitlBee IRC to other chat networks gateway";
after = [ "network.target" ];
@ -172,8 +183,12 @@ in
serviceConfig.ExecStart = "${bitlbeePkg}/sbin/bitlbee -F -n -c ${bitlbeeConfig}";
};
environment.systemPackages = [ bitlbeePkg ];
environment.systemPackages = [ bitlbeePkg ];
};
})
(mkIf (config.services.bitlbee.authBackend == "pam") {
security.pam.services.bitlbee = {};
})
];
}

View File

@ -90,7 +90,7 @@ in
BANDB_DBPATH = "${cfg.statedir}/ban.db";
};
serviceConfig = {
ExecStart = "${charybdis}/bin/charybdis-ircd -foreground -logfile /dev/stdout -configfile ${configFile}";
ExecStart = "${charybdis}/bin/charybdis -foreground -logfile /dev/stdout -configfile ${configFile}";
Group = cfg.group;
User = cfg.user;
PermissionsStartOnly = true; # preStart needs to run with root permissions

View File

@ -57,32 +57,12 @@ in
};
config = mkIf cfg.enable {
# from miniupnpd/netfilter/iptables_init.sh
networking.firewall.extraCommands = ''
iptables -t nat -N MINIUPNPD
iptables -t nat -A PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
iptables -t mangle -N MINIUPNPD
iptables -t mangle -A PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
iptables -t filter -N MINIUPNPD
iptables -t filter -A FORWARD -i ${cfg.externalInterface} ! -o ${cfg.externalInterface} -j MINIUPNPD
iptables -t nat -N MINIUPNPD-PCP-PEER
iptables -t nat -A POSTROUTING -o ${cfg.externalInterface} -j MINIUPNPD-PCP-PEER
${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_init.sh -i ${cfg.externalInterface}
'';
# from miniupnpd/netfilter/iptables_removeall.sh
networking.firewall.extraStopCommands = ''
iptables -t nat -F MINIUPNPD
iptables -t nat -D PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
iptables -t nat -X MINIUPNPD
iptables -t mangle -F MINIUPNPD
iptables -t mangle -D PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
iptables -t mangle -X MINIUPNPD
iptables -t filter -F MINIUPNPD
iptables -t filter -D FORWARD -i ${cfg.externalInterface} ! -o ${cfg.externalInterface} -j MINIUPNPD
iptables -t filter -X MINIUPNPD
iptables -t nat -F MINIUPNPD-PCP-PEER
iptables -t nat -D POSTROUTING -o ${cfg.externalInterface} -j MINIUPNPD-PCP-PEER
iptables -t nat -X MINIUPNPD-PCP-PEER
${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_removeall.sh -i ${cfg.externalInterface}
'';
systemd.services.miniupnpd = {

View File

@ -50,7 +50,7 @@ in
enable = mkOption {
type = types.bool;
default = false;
description = "If enabled, start the Murmur Service.";
description = "If enabled, start the Murmur Mumble server.";
};
autobanAttempts = mkOption {

View File

@ -0,0 +1,463 @@
{ config, lib, pkgs, ... }@args:
with lib;
let
cfg = config.services.nextcloud;
toKeyValue = generators.toKeyValue {
mkKeyValue = generators.mkKeyValueDefault {} " = ";
};
phpOptionsExtensions = ''
${optionalString cfg.caching.apcu "extension=${cfg.phpPackages.apcu}/lib/php/extensions/apcu.so"}
${optionalString cfg.caching.redis "extension=${cfg.phpPackages.redis}/lib/php/extensions/redis.so"}
${optionalString cfg.caching.memcached "extension=${cfg.phpPackages.memcached}/lib/php/extensions/memcached.so"}
zend_extension = opcache.so
opcache.enable = 1
'';
phpOptions = {
upload_max_filesize = cfg.maxUploadSize;
post_max_size = cfg.maxUploadSize;
memory_limit = cfg.maxUploadSize;
} // cfg.phpOptions;
phpOptionsStr = phpOptionsExtensions + (toKeyValue phpOptions);
occ = pkgs.writeScriptBin "nextcloud-occ" ''
#! ${pkgs.stdenv.shell}
cd ${pkgs.nextcloud}
exec /run/wrappers/bin/sudo -u nextcloud \
NEXTCLOUD_CONFIG_DIR="${cfg.home}/config" \
${config.services.phpfpm.phpPackage}/bin/php \
-c ${pkgs.writeText "php.ini" phpOptionsStr}\
occ $*
'';
in {
options.services.nextcloud = {
enable = mkEnableOption "nextcloud";
hostName = mkOption {
type = types.str;
description = "FQDN for the nextcloud instance.";
};
home = mkOption {
type = types.str;
default = "/var/lib/nextcloud";
description = "Storage path of nextcloud.";
};
https = mkOption {
type = types.bool;
default = false;
description = "Enable if there is a TLS terminating proxy in front of nextcloud.";
};
maxUploadSize = mkOption {
default = "512M";
type = types.str;
description = ''
Defines the upload limit for files. This changes the relevant options
in php.ini and nginx if enabled.
'';
};
skeletonDirectory = mkOption {
default = "";
type = types.str;
description = ''
The directory where the skeleton files are located. These files will be
copied to the data directory of new users. Leave empty to not copy any
skeleton files.
'';
};
nginx.enable = mkEnableOption "nginx vhost management";
webfinger = mkOption {
type = types.bool;
default = false;
description = ''
Enable this option if you plan on using the webfinger plugin.
The appropriate nginx rewrite rules will be added to your configuration.
'';
};
phpPackages = mkOption {
type = types.attrs;
default = pkgs.php71Packages;
defaultText = "pkgs.php71Packages";
description = ''
Overridable attribute of the PHP packages set to use. If any caching
module is enabled, it will be taken from here. Therefore it should
match the version of PHP given to
<literal>services.phpfpm.phpPackage</literal>.
'';
};
phpOptions = mkOption {
type = types.attrsOf types.str;
default = {
"short_open_tag" = "Off";
"expose_php" = "Off";
"error_reporting" = "E_ALL & ~E_DEPRECATED & ~E_STRICT";
"display_errors" = "stderr";
"opcache.enable_cli" = "1";
"opcache.interned_strings_buffer" = "8";
"opcache.max_accelerated_files" = "10000";
"opcache.memory_consumption" = "128";
"opcache.revalidate_freq" = "1";
"opcache.fast_shutdown" = "1";
"openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt";
"catch_workers_output" = "yes";
};
description = ''
Options for PHP's php.ini file for nextcloud.
'';
};
config = {
dbtype = mkOption {
type = types.enum [ "sqlite" "pgsql" "mysql" ];
default = "sqlite";
description = "Database type.";
};
dbname = mkOption {
type = types.nullOr types.str;
default = "nextcloud";
description = "Database name.";
};
dbuser = mkOption {
type = types.nullOr types.str;
default = "nextcloud";
description = "Database user.";
};
dbpass = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Database password. Use <literal>dbpassFile</literal> to avoid this
being world-readable in the <literal>/nix/store</literal>.
'';
};
dbpassFile = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The full path to a file that contains the database password.
'';
};
dbhost = mkOption {
type = types.nullOr types.str;
default = "localhost";
description = "Database host.";
};
dbport = mkOption {
type = with types; nullOr (either int str);
default = null;
description = "Database port.";
};
dbtableprefix = mkOption {
type = types.nullOr types.str;
default = null;
description = "Table prefix in Nextcloud database.";
};
adminuser = mkOption {
type = types.str;
default = "root";
description = "Admin username.";
};
adminpass = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Database password. Use <literal>adminpassFile</literal> to avoid this
being world-readable in the <literal>/nix/store</literal>.
'';
};
adminpassFile = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The full path to a file that contains the admin's password.
'';
};
extraTrustedDomains = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Trusted domains, from which the nextcloud installation will be
acessible. You don't need to add
<literal>services.nextcloud.hostname</literal> here.
'';
};
};
caching = {
apcu = mkOption {
type = types.bool;
default = true;
description = ''
Whether to load the APCu module into PHP.
'';
};
redis = mkOption {
type = types.bool;
default = false;
description = ''
Whether to load the Redis module into PHP.
You still need to enable Redis in your config.php.
See https://docs.nextcloud.com/server/14/admin_manual/configuration_server/caching_configuration.html
'';
};
memcached = mkOption {
type = types.bool;
default = false;
description = ''
Whether to load the Memcached module into PHP.
You still need to enable Memcached in your config.php.
See https://docs.nextcloud.com/server/14/admin_manual/configuration_server/caching_configuration.html
'';
};
};
};
config = mkIf cfg.enable (mkMerge [
{ assertions = let acfg = cfg.config; in [
{ assertion = !(acfg.dbpass != null && acfg.dbpassFile != null);
message = "Please specify no more than one of dbpass or dbpassFile";
}
{ assertion = ((acfg.adminpass != null || acfg.adminpassFile != null)
&& !(acfg.adminpass != null && acfg.adminpassFile != null));
message = "Please specify exactly one of adminpass or adminpassFile";
}
];
}
{ systemd.timers."nextcloud-cron" = {
wantedBy = [ "timers.target" ];
timerConfig.OnBootSec = "5m";
timerConfig.OnUnitActiveSec = "15m";
timerConfig.Unit = "nextcloud-cron.service";
};
systemd.services = {
"nextcloud-setup" = let
overrideConfig = pkgs.writeText "nextcloud-config.php" ''
<?php
$CONFIG = [
'apps_paths' => [
[ 'path' => '${cfg.home}/apps', 'url' => '/apps', 'writable' => false ],
[ 'path' => '${cfg.home}/store-apps', 'url' => '/store-apps', 'writable' => true ],
],
'datadirectory' => '${cfg.home}/data',
'skeletondirectory' => '${cfg.skeletonDirectory}',
${optionalString cfg.caching.apcu "'memcache.local' => '\\OC\\Memcache\\APCu',"}
'log_type' => 'syslog',
];
'';
occInstallCmd = let
c = cfg.config;
adminpass = if c.adminpassFile != null
then ''"$(<"${toString c.adminpassFile}")"''
else ''"${toString c.adminpass}"'';
dbpass = if c.dbpassFile != null
then ''"$(<"${toString c.dbpassFile}")"''
else if c.dbpass != null
then ''"${toString c.dbpass}"''
else null;
installFlags = concatStringsSep " \\\n "
(mapAttrsToList (k: v: "${k} ${toString v}") {
"--database" = ''"${c.dbtype}"'';
# The following attributes are optional depending on the type of
# database. Those that evaluate to null on the left hand side
# will be omitted.
${if c.dbname != null then "--database-name" else null} = ''"${c.dbname}"'';
${if c.dbhost != null then "--database-host" else null} = ''"${c.dbhost}"'';
${if c.dbport != null then "--database-port" else null} = ''"${toString c.dbport}"'';
${if c.dbuser != null then "--database-user" else null} = ''"${c.dbuser}"'';
${if (any (x: x != null) [c.dbpass c.dbpassFile])
then "--database-pass" else null} = dbpass;
${if c.dbtableprefix != null
then "--database-table-prefix" else null} = ''"${toString c.dbtableprefix}"'';
"--admin-user" = ''"${c.adminuser}"'';
"--admin-pass" = adminpass;
"--data-dir" = ''"${cfg.home}/data"'';
});
in ''
${occ}/bin/nextcloud-occ maintenance:install \
${installFlags}
'';
occSetTrustedDomainsCmd = concatStringsSep "\n" (imap0
(i: v: ''
${occ}/bin/nextcloud-occ config:system:set trusted_domains \
${toString i} --value="${toString v}"
'') ([ cfg.hostName ] ++ cfg.config.extraTrustedDomains));
in {
wantedBy = [ "multi-user.target" ];
before = [ "phpfpm-nextcloud.service" ];
script = ''
chmod og+x ${cfg.home}
ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
mkdir -p ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
chown -R nextcloud:nginx ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
# Do not install if already installed
if [[ ! -e ${cfg.home}/config/config.php ]]; then
${occInstallCmd}
fi
${occ}/bin/nextcloud-occ upgrade
${occ}/bin/nextcloud-occ config:system:delete trusted_domains
${occSetTrustedDomainsCmd}
'';
serviceConfig.Type = "oneshot";
};
"nextcloud-cron" = {
environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
serviceConfig.Type = "oneshot";
serviceConfig.User = "nextcloud";
serviceConfig.ExecStart = "${pkgs.php}/bin/php -f ${pkgs.nextcloud}/cron.php";
};
};
services.phpfpm = {
phpOptions = phpOptionsExtensions;
phpPackage = pkgs.php71;
pools.nextcloud = let
phpAdminValues = (toKeyValue
(foldr (a: b: a // b) {}
(mapAttrsToList (k: v: { "php_admin_value[${k}]" = v; })
phpOptions)));
in {
listen = "/run/phpfpm/nextcloud";
extraConfig = ''
listen.owner = nginx
listen.group = nginx
user = nextcloud
group = nginx
pm = dynamic
pm.max_children = 32
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
env[NEXTCLOUD_CONFIG_DIR] = ${cfg.home}/config
env[PATH] = /run/wrappers/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/usr/bin:/bin
${phpAdminValues}
'';
};
};
users.extraUsers.nextcloud = {
home = "${cfg.home}";
group = "nginx";
createHome = true;
};
environment.systemPackages = [ occ ];
}
(mkIf cfg.nginx.enable {
services.nginx = {
enable = true;
virtualHosts = {
"${cfg.hostName}" = {
root = pkgs.nextcloud;
locations = {
"= /robots.txt" = {
priority = 100;
extraConfig = ''
allow all;
log_not_found off;
access_log off;
'';
};
"/" = {
priority = 200;
extraConfig = "rewrite ^ /index.php$uri;";
};
"~ ^/store-apps" = {
priority = 201;
extraConfig = "root ${cfg.home};";
};
"= /.well-known/carddav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"= /.well-known/caldav" = {
priority = 210;
extraConfig = "return 301 $scheme://$host/remote.php/dav;";
};
"~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^/(?:\\.|autotest|occ|issue|indie|db_|console)" = {
priority = 300;
extraConfig = "deny all;";
};
"~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\\.php(?:$|/)" = {
priority = 500;
extraConfig = ''
include ${pkgs.nginxMainline}/conf/fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS ${if cfg.https then "on" else "off"};
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass unix:/run/phpfpm/nextcloud;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_read_timeout 120s;
'';
};
"~ ^/(?:updater|ocs-provider)(?:$|/)".extraConfig = ''
try_files $uri/ =404;
index index.php;
'';
"~ \\.(?:css|js|woff|svg|gif)$".extraConfig = ''
try_files $uri /index.php$uri$is_args$args;
add_header Cache-Control "public, max-age=15778463";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
access_log off;
'';
"~ \\.(?:png|html|ttf|ico|jpg|jpeg)$".extraConfig = ''
try_files $uri /index.php$uri$is_args$args;
access_log off;
'';
};
extraConfig = ''
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
error_page 403 /core/templates/403.php;
error_page 404 /core/templates/404.php;
client_max_body_size ${cfg.maxUploadSize};
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
${optionalString cfg.webfinger ''
rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
''}
'';
};
};
};
})
]);
}

View File

@ -624,7 +624,11 @@ let
};
users = optionalAttrs (cfg.user == "tt_rss") {
users.tt_rss.group = "tt_rss";
users.tt_rss = {
description = "tt-rss service user";
isSystemUser = true;
group = "tt_rss";
};
groups.tt_rss = {};
};
};

View File

@ -245,8 +245,8 @@ let
}
''
) virtualHosts);
mkLocations = locations: concatStringsSep "\n" (mapAttrsToList (location: config: ''
location ${location} {
mkLocations = locations: concatStringsSep "\n" (map (config: ''
location ${config.location} {
${optionalString (config.proxyPass != null && !cfg.proxyResolveWhileRunning)
"proxy_pass ${config.proxyPass};"
}
@ -266,7 +266,18 @@ let
${config.extraConfig}
${optionalString (config.proxyPass != null && cfg.recommendedProxySettings) "include ${recommendedProxyConfig};"}
}
'') locations);
'') (sortProperties (mapAttrsToList (k: v: v // { location = k; }) locations)));
mkBasicAuth = vhostName: authDef: let
htpasswdFile = pkgs.writeText "${vhostName}.htpasswd" (
concatStringsSep "\n" (mapAttrsToList (user: password: ''
${user}:{PLAIN}${password}
'') authDef)
);
in ''
auth_basic secured;
auth_basic_user_file ${htpasswdFile};
'';
mkHtpasswd = vhostName: authDef: pkgs.writeText "${vhostName}.htpasswd" (
concatStringsSep "\n" (mapAttrsToList (user: password: ''
${user}:{PLAIN}${password}

View File

@ -71,6 +71,16 @@ with lib;
These lines go to the end of the location verbatim.
'';
};
priority = mkOption {
type = types.int;
default = 1000;
description = ''
Order of this location block in relation to the others in the vhost.
The semantics are the same as with `lib.mkOrder`. Smaller values have
a greater priority.
'';
};
};
}

View File

@ -64,7 +64,7 @@ in
};
security.wrappers = {
kcheckpass.source = "${lib.getBin plasma5.plasma-workspace}/lib/libexec/kcheckpass";
kcheckpass.source = "${lib.getBin plasma5.kscreenlocker}/lib/libexec/kcheckpass";
"start_kdeinit".source = "${lib.getBin pkgs.kinit}/lib/libexec/kf5/start_kdeinit";
kwin_wayland = {
source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
@ -225,11 +225,8 @@ in
security.pam.services.sddm.enableKwallet = true;
security.pam.services.slim.enableKwallet = true;
# Update the start menu for each user that has `isNormalUser` set.
system.activationScripts.plasmaSetup = stringAfter [ "users" "groups" ]
(concatStringsSep "\n"
(mapAttrsToList (name: value: "${pkgs.su}/bin/su ${name} -c ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5")
(filterAttrs (n: v: v.isNormalUser) config.users.users)));
# Update the start menu for each user that is currently logged in
system.userActivationScripts.plasmaSetup = "${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5";
})
];

View File

@ -222,6 +222,17 @@ in
description = "List of arguments for the X server.";
};
setupCommands = mkOption {
type = types.lines;
default = "";
description = ''
Shell commands executed just after the X server has started.
This option is only effective for display managers for which this feature
is supported; currently these are LightDM, GDM and SDDM.
'';
};
sessionCommands = mkOption {
type = types.lines;
default = "";

View File

@ -7,6 +7,13 @@ let
cfg = config.services.xserver.displayManager;
gdm = pkgs.gnome3.gdm;
xSessionWrapper = if (cfg.setupCommands == "") then null else
pkgs.writeScript "gdm-x-session-wrapper" ''
#!${pkgs.bash}/bin/bash
${cfg.setupCommands}
exec "$@"
'';
in
{
@ -112,6 +119,11 @@ in
GDM_SESSIONS_DIR = "${cfg.session.desktops}/share/xsessions";
# Find the mouse
XCURSOR_PATH = "~/.icons:${pkgs.gnome3.adwaita-icon-theme}/share/icons";
} // optionalAttrs (xSessionWrapper != null) {
# Make GDM use this wrapper before running the session, which runs the
# configured setupCommands. This relies on a patched GDM which supports
# this environment variable.
GDM_X_SESSION_WRAPPER = "${xSessionWrapper}";
};
execCmd = "exec ${gdm}/bin/gdm";
};

View File

@ -0,0 +1,159 @@
{ config, lib, pkgs, ... }:
with lib;
let
dmcfg = config.services.xserver.displayManager;
ldmcfg = dmcfg.lightdm;
cfg = ldmcfg.greeters.enso;
theme = cfg.theme.package;
icons = cfg.iconTheme.package;
cursors = cfg.cursorTheme.package;
# We need a few things in the environment for the greeter to run with
# fonts/icons.
wrappedEnsoGreeter = pkgs.runCommand "lightdm-enso-os-greeter"
{ buildInputs = [ pkgs.makeWrapper ]; }
''
# This wrapper ensures that we actually get themes
makeWrapper ${pkgs.lightdm-enso-os-greeter}/bin/pantheon-greeter \
$out/greeter \
--prefix PATH : "${pkgs.glibc.bin}/bin" \
--set GDK_PIXBUF_MODULE_FILE "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" \
--set GTK_PATH "${theme}:${pkgs.gtk3.out}" \
--set GTK_EXE_PREFIX "${theme}" \
--set GTK_DATA_PREFIX "${theme}" \
--set XDG_DATA_DIRS "${theme}/share:${icons}/share:${cursors}/share" \
--set XDG_CONFIG_HOME "${theme}/share"
cat - > $out/lightdm-enso-os-greeter.desktop << EOF
[Desktop Entry]
Name=LightDM Greeter
Comment=This runs the LightDM Greeter
Exec=$out/greeter
Type=Application
EOF
'';
ensoGreeterConf = pkgs.writeText "lightdm-enso-os-greeter.conf" ''
[greeter]
default-wallpaper=${ldmcfg.background}
gtk-theme=${cfg.theme.name}
icon-theme=${cfg.iconTheme.name}
cursor-theme=${cfg.cursorTheme.name}
blur=${toString cfg.blur}
brightness=${toString cfg.brightness}
${cfg.extraConfig}
'';
in {
options = {
services.xserver.displayManager.lightdm.greeters.enso = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable enso-os-greeter as the lightdm greeter
'';
};
theme = {
package = mkOption {
type = types.package;
default = pkgs.gnome3.gnome-themes-extra;
defaultText = "pkgs.gnome3.gnome-themes-extra";
description = ''
The package path that contains the theme given in the name option.
'';
};
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the theme to use for the lightdm-enso-os-greeter
'';
};
};
iconTheme = {
package = mkOption {
type = types.package;
default = pkgs.papirus-icon-theme;
defaultText = "pkgs.papirus-icon-theme";
description = ''
The package path that contains the icon theme given in the name option.
'';
};
name = mkOption {
type = types.str;
default = "ePapirus";
description = ''
Name of the icon theme to use for the lightdm-enso-os-greeter
'';
};
};
cursorTheme = {
package = mkOption {
type = types.package;
default = pkgs.capitaine-cursors;
defaultText = "pkgs.capitaine-cursors";
description = ''
The package path that contains the cursor theme given in the name option.
'';
};
name = mkOption {
type = types.str;
default = "capitane-cursors";
description = ''
Name of the cursor theme to use for the lightdm-enso-os-greeter
'';
};
};
blur = mkOption {
type = types.bool;
default = false;
description = ''
Whether or not to enable blur
'';
};
brightness = mkOption {
type = types.int;
default = 7;
description = ''
Brightness
'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration that should be put in the greeter.conf
configuration file
'';
};
};
};
config = mkIf (ldmcfg.enable && cfg.enable) {
environment.etc."lightdm/greeter.conf".source = ensoGreeterConf;
services.xserver.displayManager.lightdm = {
greeter = mkDefault {
package = wrappedEnsoGreeter;
name = "lightdm-enso-os-greeter";
};
greeters = {
gtk = {
enable = mkDefault false;
};
};
};
};
}

View File

@ -62,6 +62,12 @@ let
${optionalString hasDefaultUserSession ''
user-session=${defaultSessionName}
''}
${optionalString (dmcfg.setupCommands != "") ''
display-setup-script=${pkgs.writeScript "lightdm-display-setup" ''
#!${pkgs.bash}/bin/bash
${dmcfg.setupCommands}
''}
''}
${cfg.extraSeatDefaults}
'';
@ -74,6 +80,7 @@ in
imports = [
./lightdm-greeters/gtk.nix
./lightdm-greeters/mini.nix
./lightdm-greeters/enso-os.nix
];
options = {

View File

@ -20,6 +20,7 @@ let
Xsetup = pkgs.writeScript "Xsetup" ''
#!/bin/sh
${cfg.setupScript}
${dmcfg.setupCommands}
'';
Xstop = pkgs.writeScript "Xstop" ''
@ -137,7 +138,8 @@ in
xrandr --auto
'';
description = ''
A script to execute when starting the display server.
A script to execute when starting the display server. DEPRECATED, please
use <option>services.xserver.displayManager.setupCommands</option>.
'';
};

View File

@ -374,6 +374,12 @@ in
description = "Contents of the first Monitor section of the X server configuration file.";
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = "Additional contents (sections) included in the X server configuration file";
};
xrandrHeads = mkOption {
default = [];
example = [
@ -754,6 +760,7 @@ in
Driver "${driver.driverName or driver.name}"
${if cfg.useGlamor then ''Option "AccelMethod" "glamor"'' else ""}
${cfg.deviceSection}
${driver.deviceSection or ""}
${xrandrDeviceSection}
EndSection
@ -765,6 +772,7 @@ in
''}
${cfg.screenSection}
${driver.screenSection or ""}
${optionalString (cfg.defaultDepth != 0) ''
DefaultDepth ${toString cfg.defaultDepth}
@ -794,6 +802,8 @@ in
'')}
${xrandrMonitorSections}
${cfg.extraConfig}
'';
fonts.enableDefaultFonts = mkDefault true;

View File

@ -100,6 +100,52 @@ in
exit $_status
'';
};
};
system.userActivationScripts = mkOption {
default = {};
example = literalExample ''
{ plasmaSetup = {
text = '''
${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5"
''';
deps = [];
};
}
'';
description = ''
A set of shell script fragments that are executed by a systemd user
service when a NixOS system configuration is activated. Examples are
rebuilding the .desktop file cache for showing applications in the menu.
Since these are executed every time you run
<command>nixos-rebuild</command>, it's important that they are
idempotent and fast.
'';
type = types.attrsOf types.unspecified;
apply = set: {
script = ''
unset PATH
for i in ${toString path}; do
PATH=$PATH:$i/bin:$i/sbin
done
_status=0
trap "_status=1 _localstatus=\$?" ERR
${
let
set' = mapAttrs (n: v: if isString v then noDepEntry v else v) set;
withHeadlines = addAttributeName set';
in textClosureMap id (withHeadlines) (attrNames withHeadlines)
}
exit $_status
'';
};
};
@ -128,14 +174,6 @@ in
''
# Various log/runtime directories.
mkdir -m 0755 -p /run/nix/current-load # for distributed builds
mkdir -m 0700 -p /run/nix/remote-stores
mkdir -m 0755 -p /var/log
touch /var/log/wtmp /var/log/lastlog # must exist
chmod 644 /var/log/wtmp /var/log/lastlog
mkdir -m 1777 -p /var/tmp
# Empty, immutable home directory of many system accounts.
@ -177,6 +215,14 @@ in
source ${config.system.build.earlyMountScript}
'';
systemd.user = {
services.nixos-activation = {
description = "Run user specific NixOS activation";
script = config.system.userActivationScripts.script;
unitConfig.ConditionUser = "!@system";
serviceConfig.Type = "oneshot";
};
};
};
}

View File

@ -419,7 +419,8 @@ while (my $f = <$listActiveUsers>) {
my ($uid, $name) = ($+{uid}, $+{user});
print STDERR "reloading user units for $name...\n";
system("su", "-s", "@shell@", "-l", $name, "-c", "XDG_RUNTIME_DIR=/run/user/$uid @systemd@/bin/systemctl --user daemon-reload");
system("@su@", "-s", "@shell@", "-l", $name, "-c", "XDG_RUNTIME_DIR=/run/user/$uid @systemd@/bin/systemctl --user daemon-reload");
system("@su@", "-s", "@shell@", "-l", $name, "-c", "XDG_RUNTIME_DIR=/run/user/$uid @systemd@/bin/systemctl --user start nixos-activation.service");
}
close $listActiveUsers;

View File

@ -109,6 +109,7 @@ let
inherit (pkgs) utillinux coreutils;
systemd = config.systemd.package;
shell = "${pkgs.bash}/bin/sh";
su = "${pkgs.shadow.su}/bin/su";
inherit children;
kernelParams = config.boot.kernelParams;

View File

@ -6,11 +6,22 @@ let
cfg = config.boot.initrd.network;
dhcpinterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
udhcpcScript = pkgs.writeScript "udhcp-script"
''
#! /bin/sh
if [ "$1" = bound ]; then
ip address add "$ip/$mask" dev "$interface"
if [ -n "$mtu" ]; then
ip link set mtu "$mtu" dev "$interface"
fi
if [ -n "$staticroutes" ]; then
echo "$staticroutes" \
| sed -r "s@(\S+) (\S+)@ ip route add \"\1\" via \"\2\" dev \"$interface\" ; @g" \
| sed -r "s@ via \"0\.0\.0\.0\"@@g" \
| /bin/sh
fi
if [ -n "$router" ]; then
ip route add "$router" dev "$interface" # just in case if "$router" is not within "$ip/$mask" (e.g. Hetzner Cloud)
ip route add default via "$router" dev "$interface"
@ -93,18 +104,24 @@ in
''
# Otherwise, use DHCP.
+ optionalString config.networking.useDHCP ''
+ optionalString (config.networking.useDHCP || dhcpinterfaces != []) ''
if [ -z "$hasNetwork" ]; then
# Bring up all interfaces.
for iface in $(cd /sys/class/net && ls); do
for iface in $(ls /sys/class/net/); do
echo "bringing up network interface $iface..."
ip link set "$iface" up
done
# Acquire a DHCP lease.
echo "acquiring IP address via DHCP..."
udhcpc --quit --now --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
# Acquire DHCP leases.
for iface in ${ if config.networking.useDHCP then
"$(ls /sys/class/net/ | grep -v ^lo$)"
else
lib.concatMapStringsSep " " lib.escapeShellArg dhcpinterfaces
}; do
echo "acquiring IP address via DHCP on $iface..."
udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
done
fi
''

View File

@ -152,6 +152,14 @@ ln -sfn /run/booted-system /nix/var/nix/gcroots/booted-system
@shell@ @postBootCommands@
# Ensure systemd doesn't try to populate /etc, by forcing its first-boot
# heuristic off. It doesn't matter what's in /etc/machine-id for this purpose,
# and systemd will immediately fill in the file when it starts, so just
# creating it is enough. This `: >>` pattern avoids forking and avoids changing
# the mtime if the file already exists.
: >> /etc/machine-id
# Reset the logging file descriptors.
exec 1>&$logOutFd 2>&$logErrFd
exec {logOutFd}>&- {logErrFd}>&-

View File

@ -63,7 +63,7 @@ in rec {
assertValueOneOf = name: values: group: attr:
optional (attr ? ${name} && !elem attr.${name} values)
"Systemd ${group} field `${name}' cannot have value `${attr.${name}}'.";
"Systemd ${group} field `${name}' cannot have value `${toString attr.${name}}'.";
assertHasField = name: group: attr:
optional (!(attr ? ${name}))

View File

@ -394,7 +394,7 @@ in rec {
Each attribute in this set specifies an option in the
<literal>[Timer]</literal> section of the unit. See
<citerefentry><refentrytitle>systemd.timer</refentrytitle>
<manvolnum>7</manvolnum></citerefentry> and
<manvolnum>5</manvolnum></citerefentry> and
<citerefentry><refentrytitle>systemd.time</refentrytitle>
<manvolnum>7</manvolnum></citerefentry> for details.
'';

View File

@ -747,6 +747,7 @@ in
"systemd/journald.conf".text = ''
[Journal]
Storage=persistent
RateLimitInterval=${config.services.journald.rateLimitInterval}
RateLimitBurst=${toString config.services.journald.rateLimitBurst}
${optionalString (config.services.journald.console != "") ''
@ -783,19 +784,6 @@ in
services.dbus.enable = true;
system.activationScripts.systemd = stringAfter [ "groups" ]
''
mkdir -m 0755 -p /var/lib/udev
if ! [ -e /etc/machine-id ]; then
${systemd}/bin/systemd-machine-id-setup
fi
# Keep a persistent journal. Note that systemd-tmpfiles will
# set proper ownership/permissions.
mkdir -m 0700 -p /var/log/journal
'';
users.users.systemd-network.uid = config.ids.uids.systemd-network;
users.groups.systemd-network.gid = config.ids.gids.systemd-network;
users.users.systemd-resolve.uid = config.ids.uids.systemd-resolve;

View File

@ -22,6 +22,13 @@ with lib;
# Not supported in systemd-nspawn containers.
security.audit.enable = false;
# Make sure that root user in container will talk to host nix-daemon
environment.etc."profile".text = ''
export NIX_REMOTE=daemon
'';
};
}

View File

@ -9,20 +9,47 @@ in {
options = {
virtualisation.hypervGuest = {
enable = mkEnableOption "Hyper-V Guest Support";
videoMode = mkOption {
type = types.str;
default = "1152x864";
example = "1024x768";
description = ''
Resolution at which to initialize the video adapter.
Supports screen resolution up to Full HD 1920x1080 with 32 bit color
on Windows Server 2012, and 1600x1200 with 16 bit color on Windows
Server 2008 R2 or earlier.
'';
};
};
};
config = mkIf cfg.enable {
boot = {
initrd.kernelModules = [
"hv_balloon" "hv_netvsc" "hv_storvsc" "hv_utils" "hv_vmbus"
];
kernelParams = [
"video=hyperv_fb:${cfg.videoMode}"
];
};
environment.systemPackages = [ config.boot.kernelPackages.hyperv-daemons.bin ];
security.rngd.enable = false;
# enable hotadding memory
# enable hotadding cpu/memory
services.udev.packages = lib.singleton (pkgs.writeTextFile {
name = "hyperv-memory-hotadd-udev-rules";
destination = "/etc/udev/rules.d/99-hyperv-memory-hotadd.rules";
name = "hyperv-cpu-and-memory-hotadd-udev-rules";
destination = "/etc/udev/rules.d/99-hyperv-cpu-and-memory-hotadd.rules";
text = ''
ACTION="add", SUBSYSTEM=="memory", ATTR{state}="online"
# Memory hotadd
SUBSYSTEM=="memory", ACTION=="add", DEVPATH=="/devices/system/memory/memory[0-9]*", TEST=="state", ATTR{state}="online"
# CPU hotadd
SUBSYSTEM=="cpu", ACTION=="add", DEVPATH=="/devices/system/cpu/cpu[0-9]*", TEST=="online", ATTR{online}="1"
'';
});

View File

@ -12,7 +12,7 @@ in {
virtualbox = {
baseImageSize = mkOption {
type = types.int;
default = 10 * 1024;
default = 100 * 1024;
description = ''
The size of the VirtualBox base image in MiB.
'';

View File

@ -250,6 +250,7 @@ in rec {
tests.acme = callTest tests/acme.nix {};
tests.avahi = callTest tests/avahi.nix {};
tests.beegfs = callTest tests/beegfs.nix {};
tests.upnp = callTest tests/upnp.nix {};
tests.bittorrent = callTest tests/bittorrent.nix {};
tests.bind = callTest tests/bind.nix {};
#tests.blivet = callTest tests/blivet.nix {}; # broken since 2017-07024
@ -362,6 +363,7 @@ in rec {
tests.netdata = callTest tests/netdata.nix { };
tests.networking.networkd = callSubTests tests/networking.nix { networkd = true; };
tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; };
tests.nextcloud = callSubTests tests/nextcloud { };
# TODO: put in networking.nix after the test becomes more complete
tests.networkingProxy = callTest tests/networking-proxy.nix {};
tests.nexus = callTest tests/nexus.nix { };

View File

@ -13,57 +13,95 @@ let
# Some random file to serve.
file = pkgs.hello.src;
miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf"
''
ext_ifname=eth1
listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address}/24
allow 1024-65535 192.168.2.0/24 1024-65535
'';
internalRouterAddress = "192.168.3.1";
internalClient1Address = "192.168.3.2";
externalRouterAddress = "80.100.100.1";
externalClient2Address = "80.100.100.2";
externalTrackerAddress = "80.100.100.3";
in
{
name = "bittorrent";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ domenkozar eelco chaoflow rob wkennington ];
maintainers = [ domenkozar eelco chaoflow rob wkennington bobvanderlinden ];
};
nodes =
{ tracker =
{ pkgs, ... }:
{ environment.systemPackages = [ pkgs.transmission pkgs.opentracker ];
{ environment.systemPackages = [ pkgs.transmission ];
virtualisation.vlans = [ 1 ];
networking.interfaces.eth1.ipv4.addresses = [
{ address = externalTrackerAddress; prefixLength = 24; }
];
# We need Apache on the tracker to serve the torrents.
services.httpd.enable = true;
services.httpd.adminAddr = "foo@example.org";
services.httpd.documentRoot = "/tmp";
networking.firewall.enable = false; # FIXME: figure out what ports we actually need
networking.firewall.enable = false;
services.opentracker.enable = true;
services.transmission.enable = true;
services.transmission.settings.dht-enabled = false;
services.transmission.settings.port-forwaring-enabled = false;
};
router =
{ pkgs, ... }:
{ environment.systemPackages = [ pkgs.miniupnpd ];
virtualisation.vlans = [ 1 2 ];
{ pkgs, nodes, ... }:
{ virtualisation.vlans = [ 1 2 ];
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "eth2" ];
networking.nat.externalInterface = "eth1";
networking.firewall.enable = false;
networking.firewall.enable = true;
networking.firewall.trustedInterfaces = [ "eth2" ];
networking.interfaces.eth0.ipv4.addresses = [];
networking.interfaces.eth1.ipv4.addresses = [
{ address = externalRouterAddress; prefixLength = 24; }
];
networking.interfaces.eth2.ipv4.addresses = [
{ address = internalRouterAddress; prefixLength = 24; }
];
services.miniupnpd = {
enable = true;
externalInterface = "eth1";
internalIPs = [ "eth2" ];
appendConfig = ''
ext_ip=${externalRouterAddress}
'';
};
};
client1 =
{ pkgs, nodes, ... }:
{ environment.systemPackages = [ pkgs.transmission ];
{ environment.systemPackages = [ pkgs.transmission pkgs.miniupnpc ];
virtualisation.vlans = [ 2 ];
networking.defaultGateway =
(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address;
networking.interfaces.eth0.ipv4.addresses = [];
networking.interfaces.eth1.ipv4.addresses = [
{ address = internalClient1Address; prefixLength = 24; }
];
networking.defaultGateway = internalRouterAddress;
networking.firewall.enable = false;
services.transmission.enable = true;
services.transmission.settings.dht-enabled = false;
services.transmission.settings.message-level = 3;
};
client2 =
{ pkgs, ... }:
{ environment.systemPackages = [ pkgs.transmission ];
virtualisation.vlans = [ 1 ];
networking.interfaces.eth0.ipv4.addresses = [];
networking.interfaces.eth1.ipv4.addresses = [
{ address = externalClient2Address; prefixLength = 24; }
];
networking.firewall.enable = false;
services.transmission.enable = true;
services.transmission.settings.dht-enabled = false;
services.transmission.settings.port-forwaring-enabled = false;
};
};
@ -72,43 +110,38 @@ in
''
startAll;
# Enable NAT on the router and start miniupnpd.
$router->waitForUnit("nat");
$router->succeed(
"iptables -w -t nat -N MINIUPNPD",
"iptables -w -t nat -A PREROUTING -i eth1 -j MINIUPNPD",
"echo 1 > /proc/sys/net/ipv4/ip_forward",
"miniupnpd -f ${miniupnpdConf nodes}"
);
# Wait for network and miniupnpd.
$router->waitForUnit("network-online.target");
$router->waitForUnit("miniupnpd");
# Create the torrent.
$tracker->succeed("mkdir /tmp/data");
$tracker->succeed("cp ${file} /tmp/data/test.tar.bz2");
$tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ipv4.addresses).address}:6969/announce -o /tmp/test.torrent");
$tracker->succeed("transmission-create /tmp/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent");
$tracker->succeed("chmod 644 /tmp/test.torrent");
# Start the tracker. !!! use a less crappy tracker
$tracker->waitForUnit("network.target");
$tracker->succeed("opentracker -p 6969 >&2 &");
$tracker->waitForUnit("network-online.target");
$tracker->waitForUnit("opentracker.service");
$tracker->waitForOpenPort(6969);
# Start the initial seeder.
my $pid = $tracker->succeed("transmission-cli /tmp/test.torrent -M -w /tmp/data >&2 & echo \$!");
$tracker->succeed("transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir /tmp/data");
# Now we should be able to download from the client behind the NAT.
$tracker->waitForUnit("httpd");
$client1->waitForUnit("network.target");
$client1->succeed("transmission-cli http://tracker/test.torrent -w /tmp >&2 &");
$client1->waitForUnit("network-online.target");
$client1->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --download-dir /tmp >&2 &");
$client1->waitForFile("/tmp/test.tar.bz2");
$client1->succeed("cmp /tmp/test.tar.bz2 ${file}");
# Bring down the initial seeder.
$tracker->succeed("kill -9 $pid");
# $tracker->stopJob("transmission");
# Now download from the second client. This can only succeed if
# the first client created a NAT hole in the router.
$client2->waitForUnit("network.target");
$client2->succeed("transmission-cli http://tracker/test.torrent -M -w /tmp >&2 &");
$client2->waitForUnit("network-online.target");
$client2->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht --download-dir /tmp >&2 &");
$client2->waitForFile("/tmp/test.tar.bz2");
$client2->succeed("cmp /tmp/test.tar.bz2 ${file}");
'';

View File

@ -86,6 +86,9 @@ import ./make-test.nix ({ pkgs, ...} : {
# Execute commands via the root shell.
$machine->succeed("nixos-container run $id1 -- uname") =~ /Linux/ or die;
# Execute a nix command via the root shell. (regression test for #40355)
$machine->succeed("nixos-container run $id1 -- nix-instantiate -E 'derivation { name = \"empty\"; builder = \"false\"; system = \"false\"; }'");
# Stop and start (regression test for #4989)
$machine->succeed("nixos-container stop $id1");
$machine->succeed("nixos-container start $id1");

View File

@ -78,6 +78,8 @@ import ./make-test.nix ({ pkgs, ...} : rec {
# Test whether we have a reboot record in wtmp.
subtest "reboot-wtmp", sub {
$machine->shutdown;
$machine->waitForUnit('multi-user.target');
$machine->succeed("last | grep reboot >&2");
};

View File

@ -0,0 +1,56 @@
import ../make-test.nix ({ pkgs, ...}: let
adminpass = "notproduction";
adminuser = "root";
in {
name = "nextcloud-basic";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ globin eqyiel ];
};
nodes = {
# The only thing the client needs to do is download a file.
client = { ... }: {};
nextcloud = { config, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 80 ];
services.nextcloud = {
enable = true;
nginx.enable = true;
hostName = "nextcloud";
config = {
# Don't inherit adminuser since "root" is supposed to be the default
inherit adminpass;
};
};
};
};
testScript = let
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
#!${pkgs.stdenv.shell}
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
"''${@}"
'';
copySharedFile = pkgs.writeScript "copy-shared-file" ''
#!${pkgs.stdenv.shell}
echo 'hi' | ${withRcloneEnv} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
'';
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
#!${pkgs.stdenv.shell}
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
'';
in ''
startAll();
$nextcloud->waitForUnit("multi-user.target");
$nextcloud->succeed("curl -sSf http://nextcloud/login");
$nextcloud->succeed("${withRcloneEnv} ${copySharedFile}");
$client->waitForUnit("multi-user.target");
$client->succeed("${withRcloneEnv} ${diffSharedFile}");
'';
})

View File

@ -0,0 +1,6 @@
{ system ? builtins.currentSystem }:
{
basic = import ./basic.nix { inherit system; };
with-postgresql-and-redis = import ./with-postgresql-and-redis.nix { inherit system; };
with-mysql-and-memcached = import ./with-mysql-and-memcached.nix { inherit system; };
}

View File

@ -0,0 +1,97 @@
import ../make-test.nix ({ pkgs, ...}: let
adminpass = "hunter2";
adminuser = "root";
in {
name = "nextcloud-with-mysql-and-memcached";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eqyiel ];
};
nodes = {
# The only thing the client needs to do is download a file.
client = { ... }: {};
nextcloud = { config, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 80 ];
services.nextcloud = {
enable = true;
hostName = "nextcloud";
nginx.enable = true;
https = true;
caching = {
apcu = true;
redis = false;
memcached = true;
};
config = {
dbtype = "mysql";
dbname = "nextcloud";
dbuser = "nextcloud";
dbhost = "127.0.0.1";
dbport = 3306;
dbpass = "hunter2";
# Don't inherit adminuser since "root" is supposed to be the default
inherit adminpass;
};
};
services.mysql = {
enable = true;
bind = "127.0.0.1";
package = pkgs.mariadb;
initialScript = pkgs.writeText "mysql-init" ''
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'hunter2';
CREATE DATABASE IF NOT EXISTS nextcloud;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
CREATE TEMPORARY TABLES ON nextcloud.* TO 'nextcloud'@'localhost'
IDENTIFIED BY 'hunter2';
FLUSH privileges;
'';
};
systemd.services."nextcloud-setup"= {
requires = ["mysql.service"];
after = ["mysql.service"];
};
services.memcached.enable = true;
};
};
testScript = let
configureMemcached = pkgs.writeScript "configure-memcached" ''
#!${pkgs.stdenv.shell}
nextcloud-occ config:system:set memcached_servers 0 0 --value 127.0.0.1 --type string
nextcloud-occ config:system:set memcached_servers 0 1 --value 11211 --type integer
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\APCu' --type string
nextcloud-occ config:system:set memcache.distributed --value '\OC\Memcache\Memcached' --type string
'';
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
#!${pkgs.stdenv.shell}
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
'';
copySharedFile = pkgs.writeScript "copy-shared-file" ''
#!${pkgs.stdenv.shell}
echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
'';
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
#!${pkgs.stdenv.shell}
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
'';
in ''
startAll();
$nextcloud->waitForUnit("multi-user.target");
$nextcloud->succeed("${configureMemcached}");
$nextcloud->succeed("curl -sSf http://nextcloud/login");
$nextcloud->succeed("${withRcloneEnv} ${copySharedFile}");
$client->waitForUnit("multi-user.target");
$client->succeed("${withRcloneEnv} ${diffSharedFile}");
'';
})

View File

@ -0,0 +1,130 @@
import ../make-test.nix ({ pkgs, ...}: let
adminpass = "hunter2";
adminuser = "custom-admin-username";
in {
name = "nextcloud-with-postgresql-and-redis";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eqyiel ];
};
nodes = {
# The only thing the client needs to do is download a file.
client = { ... }: {};
nextcloud = { config, pkgs, ... }: {
networking.firewall.allowedTCPPorts = [ 80 ];
services.nextcloud = {
enable = true;
hostName = "nextcloud";
nginx.enable = true;
caching = {
apcu = false;
redis = true;
memcached = false;
};
config = {
dbtype = "pgsql";
dbname = "nextcloud";
dbuser = "nextcloud";
dbhost = "localhost";
dbpassFile = toString (pkgs.writeText "db-pass-file" ''
hunter2
'');
inherit adminuser;
adminpassFile = toString (pkgs.writeText "admin-pass-file" ''
${adminpass}
'');
};
};
services.redis = {
unixSocket = "/var/run/redis/redis.sock";
enable = true;
extraConfig = ''
unixsocketperm 770
'';
};
systemd.services.redis = {
preStart = ''
mkdir -p /var/run/redis
chown ${config.services.redis.user}:${config.services.nginx.group} /var/run/redis
'';
serviceConfig.PermissionsStartOnly = true;
};
systemd.services."nextcloud-setup"= {
requires = ["postgresql.service"];
after = [
"postgresql.service"
"chown-redis-socket.service"
];
};
# At the time of writing, redis creates its socket with the "nobody"
# group. I figure this is slightly less bad than making the socket world
# readable.
systemd.services."chown-redis-socket" = {
enable = true;
script = ''
until ${pkgs.redis}/bin/redis-cli ping; do
echo "waiting for redis..."
sleep 1
done
chown ${config.services.redis.user}:${config.services.nginx.group} /var/run/redis/redis.sock
'';
after = [ "redis.service" ];
requires = [ "redis.service" ];
wantedBy = [ "redis.service" ];
serviceConfig = {
Type = "oneshot";
};
};
services.postgresql = {
enable = true;
initialScript = pkgs.writeText "psql-init" ''
create role nextcloud with login password 'hunter2';
create database nextcloud with owner nextcloud;
'';
};
};
};
testScript = let
configureRedis = pkgs.writeScript "configure-redis" ''
#!${pkgs.stdenv.shell}
nextcloud-occ config:system:set redis 'host' --value '/var/run/redis/redis.sock' --type string
nextcloud-occ config:system:set redis 'port' --value 0 --type integer
nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\Redis' --type string
nextcloud-occ config:system:set memcache.locking --value '\OC\Memcache\Redis' --type string
'';
withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
#!${pkgs.stdenv.shell}
export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}"
export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
"''${@}"
'';
copySharedFile = pkgs.writeScript "copy-shared-file" ''
#!${pkgs.stdenv.shell}
echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
'';
diffSharedFile = pkgs.writeScript "diff-shared-file" ''
#!${pkgs.stdenv.shell}
diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
'';
in ''
startAll();
$nextcloud->waitForUnit("multi-user.target");
$nextcloud->succeed("${configureRedis}");
$nextcloud->succeed("curl -sSf http://nextcloud/login");
$nextcloud->succeed("${withRcloneEnv} ${copySharedFile}");
$client->waitForUnit("multi-user.target");
$client->succeed("${withRcloneEnv} ${diffSharedFile}");
'';
})

94
nixos/tests/upnp.nix Normal file
View File

@ -0,0 +1,94 @@
# This tests whether UPnP port mappings can be created using Miniupnpd
# and Miniupnpc.
# It runs a Miniupnpd service on one machine, and verifies
# a client can indeed create a port mapping using Miniupnpc. If
# this succeeds an external client will try to connect to the port
# mapping.
import ./make-test.nix ({ pkgs, ... }:
let
internalRouterAddress = "192.168.3.1";
internalClient1Address = "192.168.3.2";
externalRouterAddress = "80.100.100.1";
externalClient2Address = "80.100.100.2";
in
{
name = "upnp";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ bobvanderlinden ];
};
nodes =
{
router =
{ pkgs, nodes, ... }:
{ virtualisation.vlans = [ 1 2 ];
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "eth2" ];
networking.nat.externalInterface = "eth1";
networking.firewall.enable = true;
networking.firewall.trustedInterfaces = [ "eth2" ];
networking.interfaces.eth1.ipv4.addresses = [
{ address = externalRouterAddress; prefixLength = 24; }
];
networking.interfaces.eth2.ipv4.addresses = [
{ address = internalRouterAddress; prefixLength = 24; }
];
services.miniupnpd = {
enable = true;
externalInterface = "eth1";
internalIPs = [ "eth2" ];
appendConfig = ''
ext_ip=${externalRouterAddress}
'';
};
};
client1 =
{ pkgs, nodes, ... }:
{ environment.systemPackages = [ pkgs.miniupnpc pkgs.netcat ];
virtualisation.vlans = [ 2 ];
networking.defaultGateway = internalRouterAddress;
networking.interfaces.eth1.ipv4.addresses = [
{ address = internalClient1Address; prefixLength = 24; }
];
networking.firewall.enable = false;
services.httpd.enable = true;
services.httpd.listen = [{ ip = "*"; port = 9000; }];
services.httpd.adminAddr = "foo@example.org";
services.httpd.documentRoot = "/tmp";
};
client2 =
{ pkgs, ... }:
{ environment.systemPackages = [ pkgs.miniupnpc ];
virtualisation.vlans = [ 1 ];
networking.interfaces.eth1.ipv4.addresses = [
{ address = externalClient2Address; prefixLength = 24; }
];
networking.firewall.enable = false;
};
};
testScript =
{ nodes, ... }:
''
startAll;
# Wait for network and miniupnpd.
$router->waitForUnit("network-online.target");
# $router->waitForUnit("nat");
$router->waitForUnit("firewall.service");
$router->waitForUnit("miniupnpd");
$client1->waitForUnit("network-online.target");
$client1->succeed("upnpc -a ${internalClient1Address} 9000 9000 TCP");
$client1->waitForUnit("httpd");
$client2->waitUntilSucceeds("curl http://${externalRouterAddress}:9000/");
'';
})

View File

@ -1,20 +1,21 @@
{ stdenv, fetchurl, pkgconfig, autoreconfHook, openssl, db48, boost, zeromq
, zlib, miniupnpc, qtbase ? null, qttools ? null, utillinux, protobuf, qrencode, libevent
, zlib, miniupnpc, qtbase ? null, qttools ? null, utillinux, protobuf, python3, qrencode, libevent
, withGui }:
with stdenv.lib;
stdenv.mkDerivation rec{
name = "bitcoin" + (toString (optional (!withGui) "d")) + "-" + version;
version = "0.16.3";
version = "0.17.0";
src = fetchurl {
urls = [ "https://bitcoincore.org/bin/bitcoin-core-${version}/bitcoin-${version}.tar.gz"
"https://bitcoin.org/bin/bitcoin-core-${version}/bitcoin-${version}.tar.gz"
];
sha256 = "060223dzzk2izfzhxwlzzd0fhbgglvbgps2nyc4zz767vybysvl3";
sha256 = "0pkq28d2dj22qrxyyg9kh0whmhj7ghyabnhyqldbljv4a7l3kvwq";
};
nativeBuildInputs = [ pkgconfig autoreconfHook ];
nativeBuildInputs = [ pkgconfig autoreconfHook ]
++ optionals doCheck [ python3 ];
buildInputs = [ openssl db48 boost zlib zeromq
miniupnpc protobuf libevent]
++ optionals stdenv.isLinux [ utillinux ]
@ -30,9 +31,11 @@ stdenv.mkDerivation rec{
"--with-qt-bindir=${qtbase.dev}/bin:${qttools.dev}/bin"
];
# Fails with "This application failed to start because it could not
# find or load the Qt platform plugin "minimal""
doCheck = false;
doCheck = true;
# QT_PLUGIN_PATH needs to be set when executing QT, which is needed when testing Bitcoin's GUI.
# See also https://github.com/NixOS/nixpkgs/issues/24256
checkFlags = optionals withGui [ "QT_PLUGIN_PATH=${qtbase}/lib/qt-5.${versions.minor qtbase.version}/plugins" ];
enableParallelBuilding = true;

View File

@ -11,13 +11,13 @@ with stdenv.lib;
stdenv.mkDerivation rec {
name = "litecoin" + (toString (optional (!withGui) "d")) + "-" + version;
version = "0.16.0";
version = "0.16.2";
src = fetchFromGitHub {
owner = "litecoin-project";
repo = "litecoin";
rev = "v${version}";
sha256 = "1g79sbplkn2bnb17i2kyh1d64bjl3ihbx83n0xssvjaajn56hbzw";
sha256 = "0xfwh7cxxz6w8kgr4kl48w3zm81n1hv8fxb5l9zx3460im1ffgy6";
};
nativeBuildInputs = [ pkgconfig autoreconfHook ];

View File

@ -3,13 +3,13 @@
stdenv.mkDerivation rec {
name = "nano-wallet-${version}";
version = "16.0";
version = "16.1";
src = fetchFromGitHub {
owner = "nanocurrency";
repo = "raiblocks";
rev = "V${version}";
sha256 = "0fk8jlas3khdh3nlv40krsjdifxp9agblvzap6k93wmm9y34h41c";
sha256 = "0sk9g4fv494a5w75vs5a3s5c139lxzz1svz0cn1hkhxqlmz8w081";
fetchSubmodules = true;
};

View File

@ -6,11 +6,11 @@ uiEnv = pkgs.callPackage ./env.nix { };
in stdenv.mkDerivation rec {
name = "parity-ui-${version}";
version = "0.2.8";
version = "0.3.4";
src = fetchurl {
url = "https://github.com/parity-js/shell/releases/download/v${version}/parity-ui_${version}_amd64.deb";
sha256 = "1nyarq73jdknhax68cq2i868sznghzj70kvk4ixypxnjb1q6a53a";
sha256 = "1xbd00r9ph8w2d6d2c5xg4b5l74ljzs50rpc6kahfznypmh4kr73";
name = "${name}.deb";
};

View File

@ -0,0 +1,37 @@
{ stdenv, fetchurl, ladspaH
}:
stdenv.mkDerivation rec {
name = "FIL-plugins-${version}";
version = "0.3.0";
src = fetchurl {
url = "http://kokkinizita.linuxaudio.org/linuxaudio/downloads/${name}.tar.bz2";
sha256 = "1scfv9j7jrp50r565haa4rvxn1vk2ss86xssl5qgcr8r45qz42qw";
};
buildInputs = [ ladspaH ];
patchPhase = ''
sed -i 's@/usr/bin/install@install@g' Makefile
sed -i 's@/bin/rm@rm@g' Makefile
sed -i 's@/usr/lib/ladspa@$(out)/lib/ladspa@g' Makefile
'';
preInstall="mkdir -p $out/lib/ladspa";
meta = {
description = ''a four-band parametric equaliser, which has the nice property of being stable even while parameters are being changed'';
longDescription = ''
Each section has an active/bypass switch, frequency, bandwidth and gain controls.
There is also a global bypass switch and gain control.
The 2nd order resonant filters are implemented using a Mitra-Regalia style lattice filter.
All switches and controls are internally smoothed, so they can be used 'live' whithout any clicks or zipper noises.
This should make this plugin a good candidate for use in systems that allow automation of plugin control ports, such as Ardour, or for stage use.
'';
version = "${version}";
homepage = http://kokkinizita.linuxaudio.org/linuxaudio/ladspa/index.html;
license = stdenv.lib.licenses.gpl2Plus;
maintainers = [ stdenv.lib.maintainers.magnetophon ];
platforms = stdenv.lib.platforms.linux;
};
}

View File

@ -1,30 +0,0 @@
Two changes:
* Add an alias for `which', so abcde can find things in store
* Choose the right CDROM reader syntax for `cd-paranoia'
--- abcde-2.5.4/abcde~ 2012-09-18 06:09:31.000000000 -0700
+++ abcde-2.5.4/abcde 2012-10-27 00:08:48.000862364 -0700
@@ -17,6 +17,11 @@
VERSION='2.5.4'
+which ()
+{
+ type -P $1
+}
+
usage ()
{
echo "This is abcde v$VERSION."
@@ -3497,6 +3502,10 @@
for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
if new_checkexec $DEFAULT_CDROMREADER; then
CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
+ case "$DEFAULT_CDROMREADER" in
+ cd-paranoia) CDROMREADERSYNTAX=cdparanoia;;
+ *) CDROMREADERSYNTAX=$DEFAULT_CDROMREADER;;
+ esac
break
fi
done

View File

@ -3,60 +3,58 @@
, perl, MusicBrainz, MusicBrainzDiscID
, makeWrapper }:
let version = "2.8.1";
let version = "2.9.2";
in
stdenv.mkDerivation {
name = "abcde-${version}";
src = fetchurl {
url = "https://abcde.einval.com/download/abcde-${version}.tar.gz";
sha256 = "0f9bjs0phk23vry7gvh0cll9vl6kmc1y4fwwh762scfdvpbp3774";
sha256 = "13c5yvp87ckqgha160ym5rdr1a4divgvyqbjh0yb6ffclip6qd9l";
};
# FIXME: This package does not support `distmp3', `eject', etc.
patches = [ ./abcde.patch ];
configurePhase = ''
sed -i "s|^[[:blank:]]*prefix *=.*$|prefix = $out|g ;
s|^[[:blank:]]*etcdir *=.*$|etcdir = $out/etc|g ;
s|^[[:blank:]]*INSTALL *=.*$|INSTALL = install -c|g" \
"Makefile";
# We use `cd-paranoia' from GNU libcdio, which contains a hyphen
# in its name, unlike Xiph's cdparanoia.
sed -i "s|^[[:blank:]]*CDPARANOIA=.*$|CDPARANOIA=cd-paranoia|g ;
s|^[[:blank:]]*DEFAULT_CDROMREADERS=.*$|DEFAULT_CDROMREADERS=\"cd-paranoia cdda2wav\"|g" \
"abcde"
echo 'CDPARANOIA=${libcdio-paranoia}/bin/cd-paranoia' >>abcde.conf
echo CDROMREADERSYNTAX=cdparanoia >>abcde.conf
substituteInPlace "abcde" \
--replace "/etc/abcde.conf" "$out/etc/abcde.conf"
'';
buildInputs = [ makeWrapper ];
nativeBuildInputs = [ makeWrapper ];
propagatedBuildInputs = [ perl MusicBrainz MusicBrainzDiscID ];
buildInputs = [ perl MusicBrainz MusicBrainzDiscID ];
installFlags = [ "sysconfdir=$(out)/etc" ];
postFixup = ''
for cmd in abcde cddb-tool abcde-musicbrainz-tool; do
wrapProgram "$out/bin/$cmd" --prefix PATH ":" \
${stdenv.lib.makeBinPath [ "$out" which libcdio-paranoia cddiscid wget vorbis-tools id3v2 eyeD3 lame flac glyr ]}
wrapProgram "$out/bin/$cmd" \
--prefix PERL5LIB : "$PERL5LIB" \
--prefix PATH ":" ${stdenv.lib.makeBinPath [
"$out" which libcdio-paranoia cddiscid wget
vorbis-tools id3v2 eyeD3 lame flac glyr
]}
done
'';
meta = {
meta = with stdenv.lib; {
homepage = http://abcde.einval.com/wiki/;
license = stdenv.lib.licenses.gpl2Plus;
license = licenses.gpl2Plus;
maintainers = with maintainers; [ gebner ];
description = "Command-line audio CD ripper";
longDescription = ''
abcde is a front-end command-line utility (actually, a shell
script) that grabs tracks off a CD, encodes them to
Ogg/Vorbis, MP3, FLAC, Ogg/Speex and/or MPP/MP+ (Musepack)
format, and tags them, all in one go.
'';
platforms = stdenv.lib.platforms.linux;
platforms = platforms.linux;
};
}

View File

@ -10,7 +10,7 @@ in stdenv.mkDerivation rec {
name = "${pname}-${version}";
src = fetchurl {
url = "mirror://gnome/sources/${pname}/${gnome3.versionBranch version}/${name}.tar.xz";
url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
sha256 = "1mbxnqrw1fwcgraa1bgik25vdzvf97vma5pzknbwbqq5ly9fwlgw";
};

View File

@ -7,13 +7,13 @@
mkDerivation rec {
name = "elisa-${version}";
version = "0.2.80";
version = "0.3.0";
src = fetchFromGitHub {
owner = "KDE";
repo = "elisa";
rev = "v${version}";
sha256 = "0wc2kkp28gp1rfgg14a769lalwd44yz7jxkrzanh91v5j2kkln07";
sha256 = "0bpkr5rp9nfa2wzm6w3xkhsfgf5dbgxbmhckjh9wkxal3mncpkg4";
};
nativeBuildInputs = [ extra-cmake-modules kdoctools wrapGAppsHook ];

View File

@ -0,0 +1,24 @@
{ stdenv, fetchFromGitHub, cmake, pkgconfig, libuv, lv2 }:
stdenv.mkDerivation rec {
pname = "eteroj.lv2";
version = "0.4.0";
name = "${pname}-${version}";
src = fetchFromGitHub {
owner = "OpenMusicKontrollers";
repo = pname;
rev = version;
sha256 = "0lzdk7hlz3vqgshrfpj0izjad1fmsnzk2vxqrry70xgz8xglvnmn";
};
buildInputs = [ libuv lv2 ];
nativeBuildInputs = [ cmake pkgconfig ];
meta = with stdenv.lib; {
description = "OSC injection/ejection from/to UDP/TCP/Serial for LV2";
homepage = https://open-music-kontrollers.ch/lv2/eteroj;
license = licenses.artistic2;
maintainers = with maintainers; [ magnetophon ];
};
}

View File

@ -0,0 +1,160 @@
{ stdenv, fetchFromGitHub, pkgconfig, makeWrapper
, libsndfile, jack2Full
, libGLU, libGL, lv2, cairo
, ladspaH, php, expat }:
stdenv.mkDerivation rec {
pname = "lsp-plugins";
version = "1.1.4";
name = "${pname}-${version}";
src = fetchFromGitHub {
owner = "sadko4u";
repo = "${pname}";
rev = "${name}";
sha256 = "0vb8ax0w4d2a153wxrhkpi21fxsv7c24k57vhfgmm1lqwv6pbl69";
};
nativeBuildInputs = [ pkgconfig php expat ];
buildInputs = [ jack2Full libsndfile libGLU libGL lv2 cairo ladspaH makeWrapper ];
makeFlags = [
"BIN_PATH=$(out)/bin"
"LIB_PATH=$(out)/lib"
"DOC_PATH=$(out)/share/doc"
];
NIX_CFLAGS_COMPILE = [ "-DLSP_NO_EXPERIMENTAL" ];
patchPhase = ''
runHook prePatch
substituteInPlace Makefile --replace "/usr/lib" "$out/lib"
substituteInPlace ./include/container/jack/main.h --replace "/usr/lib" "$out/lib"
substituteInPlace ./include/container/vst/main.h --replace "/usr/lib" "$out/lib"
# for https://github.com/sadko4u/lsp-plugins/issues/7#issuecomment-426561549 :
sed -i '/X11__NET_WM_WINDOW_TYPE_DOCK;/d' ./src/ui/ws/x11/X11Window.cpp
runHook postPatch
'';
doCheck = true;
checkPhase = ''
runHook preCheck
TEST_PATH=$(pwd)".build-test"
make OBJDIR=$TEST_PATH test
$TEST_PATH/lsp-plugins-test utest
runHook postCheck
'';
buildFlags = "release";
meta = with stdenv.lib;
{ description = "Collection of open-source audio plugins";
longDescription = ''
Compatible with follwing formats:
- LADSPA - set of plugins for Linux Audio Developer's Simple Plugin API
- LV2 - set of plugins and UIs for Linux Audio Developer's Simple Plugin API (LADSPA) version 2
- LinuxVST - set of plugins and UIs for Steinberg's VST 2.4 format ported on GNU/Linux Platform
- JACK - Standalone versions for JACK Audio connection Kit with UI
Contains the following plugins:
- Limiter Mono - Begrenzer Mono
- Limiter Stereo - Begrenzer Stereo
- Dynamic Processor LeftRight - Dynamikprozessor LeftRight
- Dynamic Processor MidSide - Dynamikprozessor MidSide
- Dynamic Processor Mono - Dynamikprozessor Mono
- Dynamic Processor Stereo - Dynamikprozessor Stereo
- Expander LeftRight - Expander LeftRight
- Expander MidSide - Expander MidSide
- Expander Mono - Expander Mono
- Expander Stereo - Expander Stereo
- Gate LeftRight - Gate LeftRight
- Gate MidSide - Gate MidSide
- Gate Mono - Gate Mono
- Gate Stereo - Gate Stereo
- Graphic Equalizer x16 LeftRight - Grafischer Entzerrer x16 LeftRight
- Graphic Equalizer x16 MidSide - Grafischer Entzerrer x16 MidSide
- Graphic Equalizer x16 Mono - Grafischer Entzerrer x16 Mono
- Graphic Equalizer x16 Stereo - Grafischer Entzerrer x16 Stereo
- Graphic Equalizer x32 LeftRight - Grafischer Entzerrer x32 LeftRight
- Graphic Equalizer x32 MidSide - Grafischer Entzerrer x32 MidSide
- Graphic Equalizer x32 Mono - Grafischer Entzerrer x32 Mono
- Graphic Equalizer x32 Stereo - Grafischer Entzerrer x32 Stereo
- Impulse Responses Mono - Impulsantworten Mono
- Impulse Responses Stereo - Impulsantworten Stereo
- Impulse Reverb Mono - Impulsnachhall Mono
- Impulse Reverb Stereo - Impulsnachhall Stereo
- Sampler Mono - Klangerzeuger Mono
- Sampler Stereo - Klangerzeuger Stereo
- Compressor LeftRight - Kompressor LeftRight
- Compressor MidSide - Kompressor MidSide
- Compressor Mono - Kompressor Mono
- Compressor Stereo - Kompressor Stereo
- Latency Meter - Latenzmessgerät
- Multiband Compressor LeftRight x8 - Multi-band Kompressor LeftRight x8
- Multiband Compressor MidSide x8 - Multi-band Kompressor MidSide x8
- Multiband Compressor Mono x8 - Multi-band Kompressor Mono x8
- Multiband Compressor Stereo x8 - Multi-band Kompressor Stereo x8
- Oscillator Mono - Oszillator Mono
- Parametric Equalizer x16 LeftRight - Parametrischer Entzerrer x16 LeftRight
- Parametric Equalizer x16 MidSide - Parametrischer Entzerrer x16 MidSide
- Parametric Equalizer x16 Mono - Parametrischer Entzerrer x16 Mono
- Parametric Equalizer x16 Stereo - Parametrischer Entzerrer x16 Stereo
- Parametric Equalizer x32 LeftRight - Parametrischer Entzerrer x32 LeftRight
- Parametric Equalizer x32 MidSide - Parametrischer Entzerrer x32 MidSide
- Parametric Equalizer x32 Mono - Parametrischer Entzerrer x32 Mono
- Parametric Equalizer x32 Stereo - Parametrischer Entzerrer x32 Stereo
- Phase Detector - Phasendetektor
- Profiler Mono - Profiler Mono
- Multi-Sampler x12 DirectOut - Schlagzeug x12 Direktausgabe
- Multi-Sampler x12 Stereo - Schlagzeug x12 Stereo
- Multi-Sampler x24 DirectOut - Schlagzeug x24 Direktausgabe
- Multi-Sampler x24 Stereo - Schlagzeug x24 Stereo
- Multi-Sampler x48 DirectOut - Schlagzeug x48 Direktausgabe
- Multi-Sampler x48 Stereo - Schlagzeug x48 Stereo
- Sidechain Multiband Compressor LeftRight x8 - Sidechain Multi-band Kompressor LeftRight x8
- Sidechain Multiband Compressor MidSide x8 - Sidechain Multi-band Kompressor MidSide x8
- Sidechain Multiband Compressor Mono x8 - Sidechain Multi-band Kompressor Mono x8
- Sidechain Multiband Compressor Stereo x8 - Sidechain Multi-band Kompressor Stereo x8
- Sidechain Limiter Mono - Sidechain-Begrenzer Mono
- Sidechain Limiter Stereo - Sidechain-Begrenzer Stereo
- Sidechain Dynamic Processor LeftRight - Sidechain-Dynamikprozessor LeftRight
- Sidechain Dynamic Processor MidSide - Sidechain-Dynamikprozessor MidSide
- Sidechain Dynamic Processor Mono - Sidechain-Dynamikprozessor Mono
- Sidechain Dynamic Processor Stereo - Sidechain-Dynamikprozessor Stereo
- Sidechain Expander LeftRight - Sidechain-Expander LeftRight
- Sidechain Expander MidSide - Sidechain-Expander MidSide
- Sidechain Expander Mono - Sidechain-Expander Mono
- Sidechain Expander Stereo - Sidechain-Expander Stereo
- Sidechain Gate LeftRight - Sidechain-Gate LeftRight
- Sidechain Gate MidSide - Sidechain-Gate MidSide
- Sidechain Gate Mono - Sidechain-Gate Mono
- Sidechain Gate Stereo - Sidechain-Gate Stereo
- Sidechain Compressor LeftRight - Sidechain-Kompressor LeftRight
- Sidechain Compressor MidSide - Sidechain-Kompressor MidSide
- Sidechain Compressor Mono - Sidechain-Kompressor Mono
- Sidechain Compressor Stereo - Sidechain-Kompressor Stereo
- Slapback Delay Mono - Slapback-Delay Mono
- Slapback Delay Stereo - Slapback-Delay Stereo
- Spectrum Analyzer x1 - Spektrumanalysator x1
- Spectrum Analyzer x12 - Spektrumanalysator x12
- Spectrum Analyzer x16 - Spektrumanalysator x16
- Spectrum Analyzer x2 - Spektrumanalysator x2
- Spectrum Analyzer x4 - Spektrumanalysator x4
- Spectrum Analyzer x8 - Spektrumanalysator x8
- Trigger MIDI Mono - Triggersensor MIDI Mono
- Trigger MIDI Stereo - Triggersensor MIDI Stereo
- Trigger Mono - Triggersensor Mono
- Trigger Stereo - Triggersensor Stereo
- Delay Compensator Mono - Verzögerungsausgleicher Mono
- Delay Compensator Stereo - Verzögerungsausgleicher Stereo
- Delay Compensator x2 Stereo - Verzögerungsausgleicher x2 Stereo
'';
homepage = http://lsp-plug.in;
maintainers = with maintainers; [ magnetophon ];
license = licenses.gpl2;
platforms = platforms.linux;
};
}

View File

@ -1,23 +1,24 @@
{ stdenv, fetchurl, makeWrapper, SDL, alsaLib, autoreconfHook, gtk2, libjack2, ladspaH
{ stdenv, fetchFromGitHub, makeWrapper, SDL, alsaLib, autoreconfHook, gtk2, libjack2, ladspaH
, ladspaPlugins, libsamplerate, libsndfile, pkgconfig, libpulseaudio, lame
, vorbis-tools }:
stdenv.mkDerivation rec {
stdenv.mkDerivation rec {
name = "mhwaveedit-${version}";
version = "1.4.23";
version = "1.4.24";
src = fetchurl {
url = "https://github.com/magnush/mhwaveedit/archive/v${version}.tar.gz";
sha256 = "1lvd54d8kpxwl4gihhznx1b5skhibz4vfxi9k2kwqg808jfgz37l";
src = fetchFromGitHub {
owner = "magnush";
repo = "mhwaveedit";
rev = "v${version}";
sha256 = "037pbq23kh8hsih994x2sv483imglwcrqrx6m8visq9c46fi0j1y";
};
nativeBuildInputs = [ autoreconfHook ];
nativeBuildInputs = [ autoreconfHook makeWrapper pkgconfig ];
preAutoreconf = "(cd docgen && sh gendocs.sh)";
buildInputs = [
SDL alsaLib gtk2 libjack2 ladspaH libsamplerate libsndfile
pkgconfig libpulseaudio makeWrapper
SDL alsaLib gtk2 libjack2 ladspaH libsamplerate libsndfile libpulseaudio
];
configureFlags = [ "--with-default-ladspa-path=${ladspaPlugins}/lib/ladspa" ];
@ -30,7 +31,7 @@ stdenv.mkDerivation rec {
meta = with stdenv.lib; {
description = "Graphical program for editing, playing and recording sound files";
homepage = https://gna.org/projects/mhwaveedit;
homepage = https://github.com/magnush/mhwaveedit;
license = licenses.gpl2Plus;
platforms = platforms.linux;
maintainers = [ maintainers.goibhniu ];

View File

@ -0,0 +1,60 @@
{ stdenv, fetchurl
, mono, dotnetPackages, makeWrapper
, gtk2, cups, timidity }:
let
version = "2.6";
in stdenv.mkDerivation {
name = "midisheetmusic";
src = fetchurl {
url = "mirror://sourceforge/midisheetmusic/MidiSheetMusic-${version}-linux-src.tar.gz";
sha256 = "05c6zskj50g29f51lx8fvgzsi3f31z01zj6ssjjrgr7jfs7ak70p";
};
checkInputs = (with dotnetPackages; [ NUnitConsole ]);
nativeBuildInputs = [ mono makeWrapper ];
buildPhase = ''
for i in Classes/MidiPlayer.cs Classes/MidiSheetMusic.cs
do
substituteInPlace $i --replace "/usr/bin/timidity" "${timidity}/bin/timidity"
done
./build.sh
'';
# include missing file with unit tests for building
# switch from mono nunit dll to standalone dll otherwise mono compiler barks
# run via nunit3 console, because mono nunit console wants access $HOME
checkPhase = ''
substituteInPlace UnitTestDLL.csproj \
--replace "</Compile>" '</Compile><Compile Include="Classes\UnitTest.cs"/>' \
--replace nunit.framework.dll "${dotnetPackages.NUnit}/lib/dotnet/NUnit/nunit.framework.dll"
./build_unit_test.sh
nunit3-console bin/Debug/UnitTest.dll
'';
# 2 tests of 47 are still failing
doCheck = false;
installPhase = ''
mkdir -p $out/share/applications $out/share/pixmaps $out/bin
cp deb/midisheetmusic.desktop $out/share/applications
cp NotePair.png $out/share/pixmaps/midisheetmusic.png
cp bin/Debug/MidiSheetMusic.exe $out/bin/.MidiSheetMusic.exe
makeWrapper ${mono}/bin/mono $out/bin/midisheetmusic.mono.exe \
--prefix LD_LIBRARY_PATH : ${stdenv.lib.makeLibraryPath [ gtk2 cups ]} \
--add-flags $out/bin/.MidiSheetMusic.exe
'';
meta = with stdenv.lib; {
description = "Convert MIDI Files to Piano Sheet Music for two hands";
homepage = http://midisheetmusic.com;
license = licenses.gpl2;
maintainers = [ maintainers.gnidorah ];
platforms = platforms.linux;
};
}

View File

@ -44,13 +44,13 @@ let
];
in stdenv.mkDerivation rec {
name = "pulseeffects-${version}";
version = "4.3.5";
version = "4.3.7";
src = fetchFromGitHub {
owner = "wwmm";
repo = "pulseeffects";
rev = "v${version}";
sha256 = "01jxkz4s3m8cqsn6wcbrw7bzr7sr7hqsp9950018riilpni7k4bd";
sha256 = "1x1jnbpbc9snya9k2xq39gssf0k4lnd1hr4cjrnwscg5rqybxqsk";
};
nativeBuildInputs = [

View File

@ -20,7 +20,7 @@ in stdenv.mkDerivation rec {
name = "${pname}-${version}";
src = fetchurl {
url = "mirror://gnome/sources/${pname}/${gnome3.versionBranch version}/${name}.tar.xz";
url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
sha256 = "0hzcns8gf5yb0rm4ss8jd8qzarcaplp5cylk6plwilsqfvxj4xn2";
};

View File

@ -9,7 +9,7 @@ in stdenv.mkDerivation rec{
name = "${pname}-${version}";
src = fetchurl {
url = "mirror://gnome/sources/${pname}/${gnome3.versionBranch version}/${name}.tar.xz";
url = "mirror://gnome/sources/${pname}/${stdenv.lib.versions.majorMinor version}/${name}.tar.xz";
sha256 = "0mx6n901vb97hsv0cwaafjffj75s1kcp8jsqay90dy3099849dyz";
};

View File

@ -0,0 +1,34 @@
{ stdenv, fetchFromGitHub, faust2jaqt, faust2lv2 }:
stdenv.mkDerivation rec {
pname = "Tambura";
name = "${pname}-${version}";
version = "1.0";
src = fetchFromGitHub {
owner = "olilarkin";
repo = "${pname}";
rev = "v${version}";
sha256 = "1w80cmiyzca1wirf5gypg3hcix1ky777id8wnd3k92mn1jf4a24y";
};
buildInputs = [ faust2jaqt faust2lv2 ];
buildPhase = ''
faust2jaqt -vec -time -t 99999 ${pname}.dsp
faust2lv2 -vec -time -gui -t 99999 ${pname}.dsp
'';
installPhase = ''
mkdir -p $out/bin
cp ${pname} $out/bin/
mkdir -p $out/lib/lv2
cp -r ${pname}.lv2/ $out/lib/lv2
'';
meta = with stdenv.lib; {
description = "A FAUST patch inspired by the Indian Tambura/Tanpura - a four string drone instrument, known for its unique rich harmonic timbre";
homepage = https://github.com/olilarkin/Tambura;
license = licenses.gpl2;
maintainers = [ maintainers.magnetophon ];
};
}

View File

@ -14,7 +14,7 @@ python2.pkgs.buildPythonApplication rec {
pythonPath = with python2.pkgs; [
pygobject2 musicbrainzngs urllib3 chardet
pycdio setuptools mutagen
pycdio setuptools mutagen CDDB
requests
];

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