diff options
Diffstat (limited to 'nixos')
96 files changed, 1662 insertions, 720 deletions
diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml index 592bf20e545d..bf86926f9bf5 100644 --- a/nixos/doc/manual/configuration/ipv6-config.xml +++ b/nixos/doc/manual/configuration/ipv6-config.xml @@ -12,8 +12,15 @@ can disable IPv6 support globally by setting: <programlisting> networking.enableIPv6 = false; -</programlisting> +</programlisting></para> + +<para>You can disable IPv6 on a single interface using a normal sysctl (in this +example, we use interface <varname>eth0</varname>): +<programlisting> +boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true; +</programlisting> </para> + </section> diff --git a/nixos/doc/manual/configuration/network-manager.xml b/nixos/doc/manual/configuration/network-manager.xml index b7e47b8729f3..dafbcfcb1e5b 100644 --- a/nixos/doc/manual/configuration/network-manager.xml +++ b/nixos/doc/manual/configuration/network-manager.xml @@ -16,12 +16,22 @@ networking.networkmanager.enable = true; some desktop managers (e.g., GNOME) enable NetworkManager automatically for you.</para> -<para>All users that should have permission to change network settings -must belong to the <code>networkmanager</code> group.</para> +<para>All users that should have permission to change network settings must +belong to the <code>networkmanager</code> group: + +<programlisting> +users.extraUsers.youruser.extraGroups = [ "networkmanager" ]; +</programlisting> +</para> + +<para>NetworkManager is controlled using either <command>nmcli</command> or +<command>nmtui</command> (curses-based terminal user interface). See their +manual pages for details on their usage. Some desktop environments (GNOME, KDE) +have their own configuration tools for NetworkManager.</para> <note><para><code>networking.networkmanager</code> and -<code>networking.wireless</code> can not be enabled at the same time: -you can still connect to the wireless networks using +<code>networking.wireless</code> (WPA Supplicant) cannot be enabled at the same +time: you can still connect to the wireless networks using NetworkManager.</para></note> </section> diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml index b0689aa1d97f..7be5e9d51d46 100644 --- a/nixos/doc/manual/development/option-declarations.xml +++ b/nixos/doc/manual/development/option-declarations.xml @@ -31,9 +31,9 @@ options = { <varlistentry> <term><varname>type</varname></term> <listitem> - <para>The type of the option (see below). It may be omitted, - but that’s not advisable since it may lead to errors that are - hard to diagnose.</para> + <para>The type of the option (see <xref linkend='sec-option-types' />). + It may be omitted, but that’s not advisable since it may lead to errors + that are hard to diagnose.</para> </listitem> </varlistentry> @@ -65,86 +65,4 @@ options = { </para> -<para>Here is a non-exhaustive list of option types: - -<variablelist> - - <varlistentry> - <term><varname>types.bool</varname></term> - <listitem> - <para>A Boolean.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.int</varname></term> - <listitem> - <para>An integer.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.str</varname></term> - <listitem> - <para>A string.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.lines</varname></term> - <listitem> - <para>A string. If there are multiple definitions, they are - concatenated, with newline characters in between.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.path</varname></term> - <listitem> - <para>A path, defined as anything that, when coerced to a - string, starts with a slash. This includes derivations.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.package</varname></term> - <listitem> - <para>A derivation (such as <literal>pkgs.hello</literal>) or a - store path (such as - <filename>/nix/store/1ifi1cfbfs5iajmvwgrbmrnrw3a147h9-hello-2.10</filename>).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.listOf</varname> <replaceable>t</replaceable></term> - <listitem> - <para>A list of elements of type <replaceable>t</replaceable> - (e.g., <literal>types.listOf types.str</literal> is a list of - strings). Multiple definitions are concatenated together.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term> - <listitem> - <para>A set of elements of type <replaceable>t</replaceable> - (e.g., <literal>types.attrsOf types.int</literal> is a set of - name/value pairs, the values being integers).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term> - <listitem> - <para>Either the value <literal>null</literal> or something of - type <replaceable>t</replaceable>.</para> - </listitem> - </varlistentry> - -</variablelist> - -You can also create new types using the function -<varname>mkOptionType</varname>. See -<filename>lib/types.nix</filename> in Nixpkgs for details.</para> - </section> diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml new file mode 100644 index 000000000000..8871b02cebf1 --- /dev/null +++ b/nixos/doc/manual/development/option-types.xml @@ -0,0 +1,394 @@ +<section xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="sec-option-types"> + +<title>Options Types</title> + + <para>Option types are a way to put constraints on the values a module option + can take. + Types are also responsible of how values are merged in case of multiple + value definitions.</para> + <section><title>Basic Types</title> + + <para>Basic types are the simplest available types in the module system. + Basic types include multiple string types that mainly differ in how + definition merging is handled.</para> + +<variablelist> + <varlistentry> + <term><varname>types.bool</varname></term> + <listitem><para>A boolean, its values can be <literal>true</literal> or + <literal>false</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.int</varname></term> + <listitem><para>An integer.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.path</varname></term> + <listitem><para>A filesystem path, defined as anything that when coerced to + a string starts with a slash. Even if derivations can be considered as + path, the more specific <literal>types.package</literal> should be + preferred.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.package</varname></term> + <listitem><para>A derivation or a store path.</para></listitem> + </varlistentry> +</variablelist> + +<para>String related types:</para> + +<variablelist> + <varlistentry> + <term><varname>types.str</varname></term> + <listitem><para>A string. Multiple definitions cannot be + merged.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.lines</varname></term> + <listitem><para>A string. Multiple definitions are concatenated with a new + line <literal>"\n"</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.commas</varname></term> + <listitem><para>A string. Multiple definitions are concatenated with a comma + <literal>","</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.envVar</varname></term> + <listitem><para>A string. Multiple definitions are concatenated with a + collon <literal>":"</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.separatedString</varname> + <replaceable>sep</replaceable></term> + <listitem><para>A string with a custom separator + <replaceable>sep</replaceable>, e.g. <literal>types.separatedString + "|"</literal>.</para></listitem> + </varlistentry> +</variablelist> + + </section> + + <section><title>Composed Types</title> + + <para>Composed types allow to create complex types by taking another type(s) + or value(s) as parameter(s). + It is possible to compose types multiple times, e.g. <literal>with types; + nullOr (enum [ "left" "right" ])</literal>.</para> + +<variablelist> + <varlistentry> + <term><varname>types.listOf</varname> <replaceable>t</replaceable></term> + <listitem><para>A list of <replaceable>t</replaceable> type, e.g. + <literal>types.listOf int</literal>. Multiple definitions are merged + with list concatenation.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term> + <listitem><para>An attribute set of where all the values are of + <replaceable>t</replaceable> type. Multiple definitions result in the + joined attribute set.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.loaOf</varname> <replaceable>t</replaceable></term> + <listitem><para>An attribute set or a list of <replaceable>t</replaceable> + type. Multiple definitions are merged according to the + value.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.loeOf</varname> <replaceable>t</replaceable></term> + <listitem><para>A list or an element of <replaceable>t</replaceable> type. + Multiple definitions are merged according to the + values.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term> + <listitem><para><literal>null</literal> or type + <replaceable>t</replaceable>. Multiple definitions are merged according + to type <replaceable>t</replaceable>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.uniq</varname> <replaceable>t</replaceable></term> + <listitem><para>Ensures that type <replaceable>t</replaceable> cannot be + merged. It is used to ensure option definitions are declared only + once.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.enum</varname> <replaceable>l</replaceable></term> + <listitem><para>One element of the list <replaceable>l</replaceable>, e.g. + <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions + cannot be merged</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.either</varname> <replaceable>t1</replaceable> + <replaceable>t2</replaceable></term> + <listitem><para>Type <replaceable>t1</replaceable> or type + <replaceable>t2</replaceable>, e.g. <literal>with types; either int + str</literal>. Multiple definitions cannot be + merged.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>types.submodule</varname> <replaceable>o</replaceable></term> + <listitem><para>A set of sub options <replaceable>o</replaceable>. + <replaceable>o</replaceable> can be an attribute set or a function + returning an attribute set. Submodules are used in composed types to + create modular options. Submodule are detailed in <xref + linkend='section-option-types-submodule' />.</para></listitem> + </varlistentry> +</variablelist> + +</section> + +<section xml:id='section-option-types-submodule'><title>Submodule</title> + + <para>Submodule is a very powerful type that defines a set of sub-options that + are handled like a separate module. + It is especially interesting when used with composed types like + <literal>attrsOf</literal> or <literal>listOf</literal>.</para> + + <para>The submodule type take a parameter <replaceable>o</replaceable>, that + should be a set, or a function returning a set with an + <literal>options</literal> key defining the sub-options. + The option set can be defined directly (<xref linkend='ex-submodule-direct' + />) or as reference (<xref linkend='ex-submodule-reference' />).</para> + + <para>Submodule option definitions are type-checked accordingly to the options + declarations. It is possible to declare submodule options inside a submodule + sub-options for even higher modularity.</para> + +<example xml:id='ex-submodule-direct'><title>Directly defined submodule</title> +<screen> +options.mod = mkOption { + name = "mod"; + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +};</screen></example> + +<example xml:id='ex-submodule-reference'><title>Submodule defined as a + reference</title> +<screen> +let + modOptions = { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = int; + }; + }; + }; +in +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule modOptions); +};</screen></example> + + +<section><title>Composed with <literal>listOf</literal></title> + + <para>When composed with <literal>listOf</literal>, submodule allows multiple + definitions of the submodule option set.</para> + +<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list + of submodules</title> +<screen> +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +};</screen></example> + +<example xml:id='ex-submodule-listof-definition'><title>Definition of a list of + submodules</title> +<screen> +config.mod = [ + { foo = 1; bar = "one"; } + { foo = 2; bar = "two"; } +];</screen></example> + +</section> + + +<section><title>Composed with <literal>attrsOf</literal></title> + + <para>When composed with <literal>attrsOf</literal>, submodule allows multiple + named definitions of the submodule option set.</para> + +<example xml:id='ex-submodule-attrsof-declaration'><title>Declaration of + attribute sets of submodules</title> +<screen> +options.mod = mkOption { + description = "submodule example"; + type = with types; attrsOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +};</screen></example> + +<example xml:id='ex-submodule-attrsof-definition'><title>Declaration of + attribute sets of submodules</title> +<screen> +config.mod.one = { foo = 1; bar = "one"; }; +config.mod.two = { foo = 2; bar = "two"; };</screen></example> + +</section> +</section> + +<section><title>Extending types</title> + + <para>Types are mainly characterized by their <literal>check</literal> and + <literal>merge</literal> functions.</para> + +<variablelist> + <varlistentry> + <term><varname>check</varname></term> + <listitem><para>The function to type check the value. Takes a value as + parameter and return a boolean. + It is possible to extend a type check with the + <literal>addCheck</literal> function (<xref + linkend='ex-extending-type-check-1' />), or to fully override the + check function (<xref linkend='ex-extending-type-check-2' />).</para> + +<example xml:id='ex-extending-type-check-1'><title>Adding a type check</title> +<screen> +byte = mkOption { + description = "An integer between 0 and 255."; + type = addCheck (x: x >= 0 && x <= 255) types.int; +};</screen></example> + +<example xml:id='ex-extending-type-check-2'><title>Overriding a type + check</title> +<screen> +nixThings = mkOption { + description = "words that start with 'nix'"; + type = types.str // { + check = (x: lib.hasPrefix "nix" x) + }; +};</screen></example> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>merge</varname></term> + <listitem><para>Function to merge the options values when multiple values + are set. +The function takes two parameters, <literal>loc</literal> the option path as a +list of strings, and <literal>defs</literal> the list of defined values as a +list. +It is possible to override a type merge function for custom +needs.</para></listitem> + </varlistentry> +</variablelist> + +</section> + +<section><title>Custom Types</title> + +<para>Custom types can be created with the <literal>mkOptionType</literal> + function. +As type creation includes some more complex topics such as submodule handling, +it is recommended to get familiar with <filename + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/types.nix">types.nix</filename> +code before creating a new type.</para> + +<para>The only required parameter is <literal>name</literal>.</para> + +<variablelist> + <varlistentry> + <term><varname>name</varname></term> + <listitem><para>A string representation of the type function name, name + usually changes accordingly parameters passed to + types.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>check</varname></term> + <listitem><para>A function to type check the definition value. Takes the + definition value as a parameter and returns a boolean indicating the + type check result, <literal>true</literal> for success and + <literal>false</literal> for failure.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>merge</varname></term> + <listitem><para>A function to merge multiple definitions values. Takes two + parameters:</para> + <variablelist> + <varlistentry> + <term><replaceable>loc</replaceable></term> + <listitem><para>The option path as a list of strings, e.g. + <literal>["boot" "loader "grub" + "enable"]</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><replaceable>defs</replaceable></term> + <listitem><para>The list of sets of defined <literal>value</literal> + and <literal>file</literal> where the value was defined, e.g. + <literal>[ { file = "/foo.nix"; value = 1; } { file = "/bar.nix"; + value = 2 } ]</literal>. The <literal>merge</literal> function + should return the merged value or throw an error in case the + values are impossible or not meant to be merged.</para></listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>getSubOptions</varname></term> + <listitem><para>For composed types that can take a submodule as type + parameter, this function generate sub-options documentation. It takes + the current option prefix as a list and return the set of sub-options. + Usually defined in a recursive manner by adding a term to the prefix, + e.g. <literal>prefix: elemType.getSubOptions (prefix ++ + [<replaceable>"prefix"</replaceable>])</literal> where + <replaceable>"prefix"</replaceable> is the newly added + prefix.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>getSubModules</varname></term> + <listitem><para>For composed types that can take a submodule as type + parameter, this function should return the type parameters submodules. + If the type parameter is called <literal>elemType</literal>, the + function should just recursively look into submodules by returning + <literal>elemType.getSubModules;</literal>.</para></listitem> + </varlistentry> + <varlistentry> + <term><varname>substSubModules</varname></term> + <listitem><para>For composed types that can take a submodule as type + parameter, this function can be used to substitute the parameter of a + submodule type. It takes a module as parameter and return the type with + the submodule options substituted. It is usally defined as a type + function call with a recursive call to + <literal>substSubModules</literal>, e.g for a type + <literal>composedType</literal> that take an <literal>elemtype</literal> + type parameter, this function should be defined as <literal>m: + composedType (elemType.substSubModules m)</literal>.</para></listitem> + </varlistentry> +</variablelist> + +</section> +</section> diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml index a68b122ce022..ef6920160e6d 100644 --- a/nixos/doc/manual/development/writing-modules.xml +++ b/nixos/doc/manual/development/writing-modules.xml @@ -176,6 +176,7 @@ in { </example> <xi:include href="option-declarations.xml" /> +<xi:include href="option-types.xml" /> <xi:include href="option-def.xml" /> <xi:include href="meta-attributes.xml" /> diff --git a/nixos/doc/manual/release-notes/rl-1509.xml b/nixos/doc/manual/release-notes/rl-1509.xml index a68baa0d8078..e0271485c361 100644 --- a/nixos/doc/manual/release-notes/rl-1509.xml +++ b/nixos/doc/manual/release-notes/rl-1509.xml @@ -471,7 +471,7 @@ in <listitem> <para> A newly packaged TeX Live 2015 is provided in <literal>pkgs.texlive</literal>, split into 6500 nix packages. For basic user documentation see - <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-15.09/pkgs/tools/typesetting/tex/texlive-new/default.nix#L1" + <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-15.09/pkgs/tools/typesetting/tex/texlive/default.nix#L1" >the source</link>. Beware of <link xlink:href="https://github.com/NixOS/nixpkgs/issues/9757" >an issue</link> when installing a too large package set. diff --git a/nixos/doc/manual/release-notes/rl-1609.xml b/nixos/doc/manual/release-notes/rl-1609.xml index 70759ee25f86..792b4458caaa 100644 --- a/nixos/doc/manual/release-notes/rl-1609.xml +++ b/nixos/doc/manual/release-notes/rl-1609.xml @@ -90,6 +90,15 @@ following incompatible changes:</para> Use <literal>security.audit.enable = true;</literal> to explicitly enable it.</para> </listitem> + <listitem> + <para> + <literal>pkgs.linuxPackages.virtualbox</literal> now contains only the + kernel modules instead of the VirtualBox user space binaries. + If you want to reference the user space binaries, you have to use the new + <literal>pkgs.virtualbox</literal> instead. + </para> + </listitem> + </itemizedlist> diff --git a/nixos/doc/manual/release-notes/rl-1703.xml b/nixos/doc/manual/release-notes/rl-1703.xml index c0fa4388a2ad..2eda8a56b202 100644 --- a/nixos/doc/manual/release-notes/rl-1703.xml +++ b/nixos/doc/manual/release-notes/rl-1703.xml @@ -29,7 +29,11 @@ following incompatible changes:</para> <itemizedlist> <listitem> - <para></para> + <para> + <literal>gnome</literal> alias has been removed along with + <literal>gtk</literal>, <literal>gtkmm</literal> and several others. + Now you need to use versioned attributes, like <literal>gnome3</literal>. + </para> </listitem> </itemizedlist> diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix index 61b214bfba8c..7fad5cbc3cd9 100644 --- a/nixos/lib/testing.nix +++ b/nixos/lib/testing.nix @@ -157,9 +157,7 @@ rec { ${coreutils}/bin/mkdir -p $TMPDIR cd $TMPDIR - $origBuilder $origArgs - - exit $? + exec $origBuilder $origArgs ''; testScript = '' @@ -172,9 +170,22 @@ rec { ''; vmRunCommand = writeText "vm-run" '' + xchg=vm-state-client/xchg ${coreutils}/bin/mkdir $out - ${coreutils}/bin/mkdir -p vm-state-client/xchg - export > vm-state-client/xchg/saved-env + ${coreutils}/bin/mkdir -p $xchg + + for i in $passAsFile; do + i2=''${i}Path + _basename=$(${coreutils}/bin/basename ''${!i2}) + ${coreutils}/bin/cp ''${!i2} $xchg/$_basename + eval $i2=/tmp/xchg/$_basename + ${coreutils}/bin/ls -la $xchg + done + + unset i i2 _basename + export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env + unset xchg + export tests='${testScript}' ${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm ''; # */ diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix index f913b8c33e56..af3d93fc1bc4 100644 --- a/nixos/modules/config/fonts/fonts.nix +++ b/nixos/modules/config/fonts/fonts.nix @@ -11,17 +11,27 @@ with lib; # TODO: find another name for it. fonts = mkOption { type = types.listOf types.path; + default = []; example = literalExample "[ pkgs.dejavu_fonts ]"; description = "List of primary font paths."; }; + enableDefaultFonts = mkOption { + type = types.bool; + default = false; + description = '' + Enable a basic set of fonts providing several font styles + and families and reasonable coverage of Unicode. + ''; + }; + }; }; config = { - fonts.fonts = + fonts.fonts = mkIf config.fonts.enableDefaultFonts [ pkgs.xorg.fontbhlucidatypewriter100dpi pkgs.xorg.fontbhlucidatypewriter75dpi diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 8a2e630a917a..aab5523c6848 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -223,10 +223,10 @@ in # Install the proxy environment variables environment.sessionVariables = cfg.proxy.envVars; - # The ‘ip-up’ target is started when we have IP connectivity. So - # services that depend on IP connectivity (like ntpd) should be - # pulled in by this target. - systemd.targets.ip-up.description = "Services Requiring IP Connectivity"; + # The ‘ip-up’ target is kept for backwards compatibility. + # New services should use systemd upstream targets: + # See https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ + systemd.targets.ip-up.description = "Services Requiring IP Connectivity (deprecated)"; # This is needed when /etc/resolv.conf is being overriden by networkd # and other configurations. If the file is destroyed by an environment diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index 169c86a2eae7..775d0c39c4fa 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -34,10 +34,10 @@ let config.programs.ssh.package pkgs.perl pkgs.procps + pkgs.rsync pkgs.strace pkgs.su pkgs.time - pkgs.texinfoInteractive pkgs.utillinux pkgs.which # 88K size ]; @@ -104,7 +104,6 @@ in "/etc/xdg" "/etc/gtk-2.0" "/etc/gtk-3.0" - "/info" "/lib" # FIXME: remove and update debug-info.nix "/sbin" "/share/applications" @@ -112,7 +111,6 @@ in "/share/doc" "/share/emacs" "/share/icons" - "/share/info" "/share/menus" "/share/mime" "/share/nano" diff --git a/nixos/modules/hardware/video/displaylink.nix b/nixos/modules/hardware/video/displaylink.nix new file mode 100644 index 000000000000..2a9382f39410 --- /dev/null +++ b/nixos/modules/hardware/video/displaylink.nix @@ -0,0 +1,61 @@ +{ config, lib, ... }: + +with lib; + +let + + enabled = elem "displaylink" config.services.xserver.videoDrivers; + + displaylink = config.boot.kernelPackages.displaylink; + +in + +{ + + config = mkIf enabled { + + boot.extraModulePackages = [ displaylink ]; + + boot.kernelModules = [ "evdi" ]; + + # Those are taken from displaylink-installer.sh and from Arch Linux AUR package. + + services.udev.extraRules = '' + ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{bNumInterfaces}=="*5", TAG+="uaccess" + ''; + + powerManagement.powerDownCommands = '' + #flush any bytes in pipe + while read -n 1 -t 1 SUSPEND_RESULT < /tmp/PmMessagesPort_out; do : ; done; + + #suspend DisplayLinkManager + echo "S" > /tmp/PmMessagesPort_in + + #wait until suspend of DisplayLinkManager finish + read -n 1 -t 10 SUSPEND_RESULT < /tmp/PmMessagesPort_out + ''; + + powerManagement.resumeCommands = '' + #resume DisplayLinkManager + echo "R" > /tmp/PmMessagesPort_in + ''; + + systemd.services.displaylink = { + description = "DisplayLink Manager Service"; + after = [ "display-manager.service" ]; + wantedBy = [ "graphical.target" ]; + + serviceConfig = { + ExecStart = "${displaylink}/bin/DisplayLinkManager"; + Restart = "always"; + RestartSec = 5; + }; + + preStart = '' + mkdir -p /var/log/displaylink + ''; + }; + + }; + +} diff --git a/nixos/modules/i18n/input-method/fcitx.nix b/nixos/modules/i18n/input-method/fcitx.nix index e97bb9f80eb5..440f13b41522 100644 --- a/nixos/modules/i18n/input-method/fcitx.nix +++ b/nixos/modules/i18n/input-method/fcitx.nix @@ -20,10 +20,9 @@ in example = literalExample "with pkgs.fcitx-engines; [ mozc hangul ]"; description = let - engines = - lib.concatStringsSep ", " - (map (name: "<literal>${name}</literal>") - (lib.attrNames pkgs.fcitx-engines)); + enginesDrv = filterAttrs (const isDerivation) pkgs.fcitx-engines; + engines = concatStringsSep ", " + (map (name: "<literal>${name}</literal>") (attrNames enginesDrv)); in "Enabled Fcitx engines. Available engines are: ${engines}."; }; diff --git a/nixos/modules/i18n/input-method/ibus.nix b/nixos/modules/i18n/input-method/ibus.nix index 097a662c3c6d..d64cf2f283bf 100644 --- a/nixos/modules/i18n/input-method/ibus.nix +++ b/nixos/modules/i18n/input-method/ibus.nix @@ -30,10 +30,9 @@ in example = literalExample "with pkgs.ibus-engines; [ mozc hangul ]"; description = let - engines = - lib.concatStringsSep ", " - (map (name: "<literal>${name}</literal>") - (lib.attrNames pkgs.ibus-engines)); + enginesDrv = filterAttrs (const isDerivation) pkgs.ibus-engines; + engines = concatStringsSep ", " + (map (name: "<literal>${name}</literal>") (attrNames enginesDrv)); in "Enabled IBus engines. Available engines are: ${engines}."; }; diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix new file mode 100644 index 000000000000..747d9d2bcec5 --- /dev/null +++ b/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -0,0 +1,5 @@ +{ + x86_64-linux = "/nix/store/i4mwf2gpvar7dqvlpp5m86llbq3ahbvb-nix-1.11.4"; + i686-linux = "/nix/store/a3gjrbspb0q4hs3sv5g1y2nza43i8nzv-nix-1.11.4"; + x86_64-darwin = "/nix/store/7v21yd3qpv0nclcy5cqr5njj9bril12s-nix-1.11.4"; +} diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh index 803989789838..36700d2bf566 100644 --- a/nixos/modules/installer/tools/nixos-rebuild.sh +++ b/nixos/modules/installer/tools/nixos-rebuild.sh @@ -261,9 +261,9 @@ fi prebuiltNix() { machine="$1" if [ "$machine" = x86_64 ]; then - echo /nix/store/xryr9g56h8yjddp89d6dw12anyb4ch7c-nix-1.10 + echo @nix_x86_64_linux@ elif [[ "$machine" =~ i.86 ]]; then - echo /nix/store/2w92k5wlpspf0q2k9mnf2z42prx3bwmv-nix-1.10 + echo @nix_i686_linux@ else echo "$0: unsupported platform" exit 1 diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index fc39a653abdc..a35f6ad8ae54 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -32,11 +32,15 @@ let "cp refs $out"; }; - nixos-rebuild = makeProg { - name = "nixos-rebuild"; - src = ./nixos-rebuild.sh; - nix = config.nix.package.out; - }; + nixos-rebuild = + let fallback = import ./nix-fallback-paths.nix; in + makeProg { + name = "nixos-rebuild"; + src = ./nixos-rebuild.sh; + nix = config.nix.package.out; + nix_x86_64_linux = fallback.x86_64-linux; + nix_i686_linux = fallback.i686-linux; + }; nixos-generate-config = makeProg { name = "nixos-generate-config"; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 31c93028bc52..e31349105946 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -181,7 +181,6 @@ systemd-timesync = 154; liquidsoap = 155; etcd = 156; - docker-registry = 157; hbase = 158; opentsdb = 159; scollector = 160; @@ -275,6 +274,7 @@ gocd-server = 252; terraria = 253; mattermost = 254; + prometheus = 255; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -436,7 +436,6 @@ systemd-timesync = 154; liquidsoap = 155; #etcd = 156; # unused - #docker-registry = 157; # unused hbase = 158; opentsdb = 159; scollector = 160; @@ -520,6 +519,7 @@ gocd-server = 252; terraria = 253; mattermost = 254; + prometheus = 255; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix index 2ecdbdbf3925..ec423768296a 100644 --- a/nixos/modules/misc/version.nix +++ b/nixos/modules/misc/version.nix @@ -95,7 +95,7 @@ in nixosVersionSuffix = mkIf (pathIsDirectory gitRepo) (mkDefault (".git." + gitCommitId)); # Note: code names must only increase in alphabetical order. - nixosCodeName = "Flounder"; + nixosCodeName = "Gorilla"; }; # Generate /etc/os-release. See diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 27fbe55cd429..8fef157c458f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -40,6 +40,7 @@ ./hardware/video/amdgpu.nix ./hardware/video/ati.nix ./hardware/video/bumblebee.nix + ./hardware/video/displaylink.nix ./hardware/video/nvidia.nix ./hardware/video/webcam/facetimehd.nix ./i18n/input-method/default.nix @@ -66,8 +67,9 @@ ./programs/command-not-found/command-not-found.nix ./programs/dconf.nix ./programs/environment.nix - ./programs/freetds.nix ./programs/fish.nix + ./programs/freetds.nix + ./programs/info.nix ./programs/kbdlight.nix ./programs/light.nix ./programs/man.nix @@ -113,6 +115,7 @@ ./services/audio/mpd.nix ./services/audio/mopidy.nix ./services/audio/squeezelite.nix + ./services/audio/ympd.nix ./services/backup/almir.nix ./services/backup/bacula.nix ./services/backup/crashplan.nix @@ -228,7 +231,6 @@ ./services/misc/dictd.nix ./services/misc/dysnomia.nix ./services/misc/disnix.nix - ./services/misc/docker-registry.nix ./services/misc/emby.nix ./services/misc/etcd.nix ./services/misc/felix.nix @@ -286,6 +288,8 @@ ./services/monitoring/monit.nix ./services/monitoring/munin.nix ./services/monitoring/nagios.nix + ./services/monitoring/prometheus/default.nix + ./services/monitoring/prometheus/node-exporter.nix ./services/monitoring/riemann.nix ./services/monitoring/riemann-dash.nix ./services/monitoring/riemann-tools.nix @@ -332,7 +336,6 @@ ./services/networking/dnschain.nix ./services/networking/dnscrypt-proxy.nix ./services/networking/dnsmasq.nix - ./services/networking/docker-registry-server.nix ./services/networking/ejabberd.nix ./services/networking/fan.nix ./services/networking/ferm.nix diff --git a/nixos/modules/profiles/minimal.nix b/nixos/modules/profiles/minimal.nix index c353da227aeb..b047b7063653 100644 --- a/nixos/modules/profiles/minimal.nix +++ b/nixos/modules/profiles/minimal.nix @@ -11,4 +11,7 @@ with lib; # This isn't perfect, but let's expect the user specifies an UTF-8 defaultLocale i18n.supportedLocales = [ (config.i18n.defaultLocale + "/UTF-8") ]; services.nixosManual.enable = mkDefault false; + + programs.man.enable = mkDefault false; + programs.info.enable = mkDefault false; } diff --git a/nixos/modules/programs/info.nix b/nixos/modules/programs/info.nix new file mode 100644 index 000000000000..be6439dca5ad --- /dev/null +++ b/nixos/modules/programs/info.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + + options = { + + programs.info.enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable info pages and the <command>info</command> command. + ''; + }; + + }; + + + config = mkIf config.programs.info.enable { + + environment.systemPackages = [ pkgs.texinfoInteractive ]; + + environment.pathsToLink = [ "/info" "/share/info" ]; + + environment.extraOutputsToInstall = [ "info" ]; + + }; + +} diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix index 878c9cc0cf09..ce4d46e19bf9 100644 --- a/nixos/modules/programs/shadow.nix +++ b/nixos/modules/programs/shadow.nix @@ -99,7 +99,6 @@ in groupdel = { rootOK = true; }; login = { startSession = true; allowNullPassword = true; showMotd = true; updateWtmp = true; }; chpasswd = { rootOK = true; }; - chgpasswd = { rootOK = true; }; }; security.setuidPrograms = [ "su" "chfn" ] diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix index cc835081c9f9..b6fd9868f98f 100644 --- a/nixos/modules/programs/ssh.nix +++ b/nixos/modules/programs/ssh.nix @@ -56,7 +56,6 @@ in setXAuthLocation = mkOption { type = types.bool; - default = config.services.xserver.enable; description = '' Whether to set the path to <command>xauth</command> for X11-forwarded connections. This causes a dependency on X11 packages. @@ -165,6 +164,9 @@ in config = { + programs.ssh.setXAuthLocation = + mkDefault (config.services.xserver.enable || config.programs.ssh.forwardX11); + assertions = [ { assertion = cfg.forwardX11 -> cfg.setXAuthLocation; message = "cannot enable X11 forwarding without setting XAuth location"; diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 412cccc20d58..34b9724442eb 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -15,7 +15,6 @@ with lib; (mkRenamedOptionModule [ "networking" "enableRT73Firmware" ] [ "networking" "enableRalinkFirmware" ]) (mkRenamedOptionModule [ "services" "cadvisor" "host" ] [ "services" "cadvisor" "listenAddress" ]) - (mkRenamedOptionModule [ "services" "dockerRegistry" "host" ] [ "services" "dockerRegistry" "listenAddress" ]) (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ]) (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ]) (mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ]) @@ -154,5 +153,7 @@ with lib; "See the 16.03 release notes for more information.") (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "") (mkRemovedOptionModule [ "services" "dovecot2" "package" ] "") + (mkRemovedOptionModule [ "services" "dockerRegistry" ] + "docker-registry has been deprecated upstream since a long time.") ]; } diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index 3dac558b9537..45e8f64046b0 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -166,7 +166,8 @@ in ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains); acmeService = { description = "Renew ACME Certificate for ${cert}"; - after = [ "network.target" ]; + after = [ "network.target" "network-online.target" ]; + wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; SuccessExitStatus = [ "0" "1" ]; diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix index ea1064c2d425..7ba25f866f24 100644 --- a/nixos/modules/security/grsecurity.nix +++ b/nixos/modules/security/grsecurity.nix @@ -72,6 +72,8 @@ in (isNO "GRKERNSEC_NO_RBAC") ]; + nixpkgs.config.grsecurity = true; + # Install PaX related utillities into the system profile. environment.systemPackages = with pkgs; [ gradm paxctl pax-utils ]; diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 77815cd6dcc1..6a4f6634c4b3 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -105,6 +105,16 @@ let ''; }; + setEnvironment = mkOption { + type = types.bool; + default = true; + description = '' + Whether the service should set the environment variables + listed in <option>environment.sessionVariables</option> + using <literal>pam_env.so</literal>. + ''; + }; + setLoginUid = mkOption { type = types.bool; description = '' @@ -219,102 +229,107 @@ let # module provides the right hooks. text = mkDefault ('' - # Account management. - account sufficient pam_unix.so - ${optionalString use_ldap - "account sufficient ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString config.krb5.enable - "account sufficient ${pam_krb5}/lib/security/pam_krb5.so"} - - # Authentication management. - ${optionalString cfg.rootOK - "auth sufficient pam_rootok.so"} - ${optionalString cfg.requireWheel - "auth required pam_wheel.so use_uid"} - ${optionalString cfg.logFailures - "auth required pam_tally.so"} - ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) - "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"} - ${optionalString cfg.fprintAuth - "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"} - ${optionalString cfg.u2fAuth - "auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so"} - ${optionalString cfg.usbAuth - "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"} - '' + - # Modules in this block require having the password set in PAM_AUTHTOK. - # pam_unix is marked as 'sufficient' on NixOS which means nothing will run - # after it succeeds. Certain modules need to run after pam_unix - # prompts the user for password so we run it once with 'required' at an - # earlier point and it will run again with 'sufficient' further down. - # We use try_first_pass the second time to avoid prompting password twice - (optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount)) '' - auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth - ${optionalString config.security.pam.enableEcryptfs - "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"} - ${optionalString cfg.pamMount - "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so"} - '') + '' - ${optionalString cfg.unixAuth - "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"} - ${optionalString cfg.otpwAuth - "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"} - ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth - "auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"} - ${optionalString use_ldap - "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"} - ${optionalString config.krb5.enable '' - auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass - auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass - auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass - ''} - auth required pam_deny.so - - # Password management. - password requisite pam_unix.so nullok sha512 - ${optionalString config.security.pam.enableEcryptfs - "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"} - ${optionalString cfg.pamMount - "password optional ${pkgs.pam_mount}/lib/security/pam_mount.so"} - ${optionalString use_ldap - "password sufficient ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString config.krb5.enable - "password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"} - ${optionalString config.services.samba.syncPasswordsByPam - "password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"} - - # Session management. - session required pam_env.so envfile=${config.system.build.pamEnvironment} - session required pam_unix.so - ${optionalString cfg.setLoginUid + # Account management. + account sufficient pam_unix.so + '' + optionalString use_ldap '' + account sufficient ${pam_ldap}/lib/security/pam_ldap.so + '' + optionalString config.krb5.enable '' + account sufficient ${pam_krb5}/lib/security/pam_krb5.so + '' + '' + + # Authentication management. + '' + optionalString cfg.rootOK '' + auth sufficient pam_rootok.so + '' + optionalString cfg.requireWheel '' + auth required pam_wheel.so use_uid + '' + optionalString cfg.logFailures '' + auth required pam_tally.so + '' + optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) '' + auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u + '' + optionalString cfg.fprintAuth '' + auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so + '' + optionalString cfg.u2fAuth '' + auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so + '' + optionalString cfg.usbAuth '' + auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so + '' + + # Modules in this block require having the password set in PAM_AUTHTOK. + # pam_unix is marked as 'sufficient' on NixOS which means nothing will run + # after it succeeds. Certain modules need to run after pam_unix + # prompts the user for password so we run it once with 'required' at an + # earlier point and it will run again with 'sufficient' further down. + # We use try_first_pass the second time to avoid prompting password twice + + optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount)) ('' + auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok "}likeauth + '' + optionalString config.security.pam.enableEcryptfs '' + auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap + '' + optionalString cfg.pamMount '' + auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so + '') + + optionalString cfg.unixAuth '' + auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok "}likeauth try_first_pass + '' + optionalString cfg.otpwAuth '' + auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so + '' + (let oath = config.security.pam.oath; in optionalString cfg.oathAuth '' + auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits} + '') + optionalString use_ldap '' + auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass + '' + optionalString config.krb5.enable '' + auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass + auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass + auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass + '' + '' + auth required pam_deny.so + + # Password management. + password requisite pam_unix.so nullok sha512 + '' + optionalString config.security.pam.enableEcryptfs '' + password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so + '' + optionalString cfg.pamMount '' + password optional ${pkgs.pam_mount}/lib/security/pam_mount.so + '' + optionalString use_ldap '' + password sufficient ${pam_ldap}/lib/security/pam_ldap.so + '' + optionalString config.krb5.enable '' + password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass + '' + optionalString config.services.samba.syncPasswordsByPam '' + password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass + '' + '' + + # Session management. + '' + optionalString cfg.setEnvironment '' + session required pam_env.so envfile=${config.system.build.pamEnvironment} + '' + '' + session required pam_unix.so + '' + optionalString cfg.setLoginUid "session ${ if config.boot.isContainer then "optional" else "required" - } pam_loginuid.so"} - ${optionalString cfg.makeHomeDir - "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022"} - ${optionalString cfg.updateWtmp - "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"} - ${optionalString config.security.pam.enableEcryptfs - "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"} - ${optionalString use_ldap - "session optional ${pam_ldap}/lib/security/pam_ldap.so"} - ${optionalString config.krb5.enable - "session optional ${pam_krb5}/lib/security/pam_krb5.so"} - ${optionalString cfg.otpwAuth - "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"} - ${optionalString cfg.startSession - "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"} - ${optionalString cfg.forwardXAuth - "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"} - ${optionalString (cfg.limits != []) - "session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"} - ${optionalString (cfg.showMotd && config.users.motd != null) - "session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"} - ${optionalString cfg.pamMount - "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"} - ${optionalString (cfg.enableAppArmor && config.security.apparmor.enable) - "session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"} - ''); + } pam_loginuid.so" + + optionalString cfg.makeHomeDir '' + session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022 + '' + optionalString cfg.updateWtmp '' + session required ${pkgs.pam}/lib/security/pam_lastlog.so silent + '' + optionalString config.security.pam.enableEcryptfs '' + session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so + '' + optionalString use_ldap '' + session optional ${pam_ldap}/lib/security/pam_ldap.so + '' + optionalString config.krb5.enable '' + session optional ${pam_krb5}/lib/security/pam_krb5.so + '' + optionalString cfg.otpwAuth '' + session optional ${pkgs.otpw}/lib/security/pam_otpw.so + '' + optionalString cfg.startSession '' + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + '' + optionalString cfg.forwardXAuth '' + session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99 + '' + optionalString (cfg.limits != []) '' + session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits} + '' + optionalString (cfg.showMotd && config.users.motd != null) '' + session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd} + '' + optionalString cfg.pamMount '' + session optional ${pkgs.pam_mount}/lib/security/pam_mount.so + '' + optionalString (cfg.enableAppArmor && config.security.apparmor.enable) '' + session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug + ''); }; }; @@ -477,6 +492,13 @@ in vlock = {}; xlock = {}; xscreensaver = {}; + + runuser = { rootOK = true; unixAuth = false; setEnvironment = false; }; + + /* FIXME: should runuser -l start a systemd session? Currently + it complains "Cannot create session: Already running in a + session". */ + runuser-l = { rootOK = true; unixAuth = false; }; }; }; diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix index dcccd8342866..fe220c94313f 100644 --- a/nixos/modules/security/setuid-wrappers.nix +++ b/nixos/modules/security/setuid-wrappers.nix @@ -132,7 +132,7 @@ in # Compatibility with old state, just remove the folder and symlink rm -f ${wrapperDir}/* # if it happens to be a tmpfs - umount ${wrapperDir} || true + ${pkgs.utillinux}/bin/umount ${wrapperDir} || true rm -d ${wrapperDir} ln -d --symbolic $wrapperDir ${wrapperDir} else diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index bced2a6ed757..f5612e1b0c5d 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -74,7 +74,7 @@ in Defaults env_keep+=SSH_AUTH_SOCK # "root" is allowed to do anything. - root ALL=(ALL) SETENV: ALL + root ALL=(ALL:ALL) SETENV: ALL # Users in the "wheel" group can do anything. %wheel ALL=(ALL:ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix index 029b14ab4726..c0a0f0374294 100644 --- a/nixos/modules/services/audio/mopidy.nix +++ b/nixos/modules/services/audio/mopidy.nix @@ -21,13 +21,7 @@ in { services.mopidy = { - enable = mkOption { - default = false; - type = types.bool; - description = '' - Whether to enable Mopidy, a music player daemon. - ''; - }; + enable = mkEnableOption "Mopidy, a music player daemon"; dataDir = mkOption { default = "/var/lib/mopidy"; diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index 5d5fef667941..85e0a7d2ac4e 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -33,6 +33,7 @@ in { services.mpd = { enable = mkOption { + type = types.bool; default = false; description = '' Whether to enable MPD, the music player daemon. @@ -40,6 +41,7 @@ in { }; musicDirectory = mkOption { + type = types.path; default = "${cfg.dataDir}/music"; description = '' The directory where mpd reads music from. @@ -47,6 +49,7 @@ in { }; extraConfig = mkOption { + type = types.str; default = ""; description = '' Extra directives added to to the end of MPD's configuration file, @@ -56,6 +59,7 @@ in { }; dataDir = mkOption { + type = types.path; default = "/var/lib/mpd"; description = '' The directory where MPD stores its state, tag cache, @@ -64,11 +68,13 @@ in { }; user = mkOption { + type = types.str; default = "mpd"; description = "User account under which MPD runs."; }; group = mkOption { + type = types.str; default = "mpd"; description = "Group account under which MPD runs."; }; @@ -76,6 +82,7 @@ in { network = { listenAddress = mkOption { + type = types.str; default = "any"; description = '' This setting sets the address for the daemon to listen on. Careful attention @@ -85,6 +92,7 @@ in { }; port = mkOption { + type = types.int; default = 6600; description = '' This setting is the TCP port that is desired for the daemon to get assigned @@ -114,12 +122,12 @@ in { after = [ "network.target" "sound.target" ]; description = "Music Player Daemon"; wantedBy = [ "multi-user.target" ]; - path = [ pkgs.mpd ]; + preStart = "mkdir -p ${cfg.dataDir} && chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}"; - script = "exec mpd --no-daemon ${mpdConf}"; serviceConfig = { User = "${cfg.user}"; PermissionsStartOnly = true; + ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon ${mpdConf}"; }; }; diff --git a/nixos/modules/services/audio/ympd.nix b/nixos/modules/services/audio/ympd.nix new file mode 100644 index 000000000000..d34c1c9d83cc --- /dev/null +++ b/nixos/modules/services/audio/ympd.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.ympd; +in { + + ###### interface + + options = { + + services.ympd = { + + enable = mkEnableOption "ympd, the MPD Web GUI"; + + webPort = mkOption { + type = types.string; + default = "8080"; + description = "The port where ympd's web interface will be available."; + example = "ssl://8080:/path/to/ssl-private-key.pem"; + }; + + mpd = { + host = mkOption { + type = types.string; + default = "localhost"; + description = "The host where MPD is listening."; + example = "localhost"; + }; + + port = mkOption { + type = types.int; + default = config.services.mpd.network.port; + description = "The port where MPD is listening."; + example = 6600; + }; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.ympd = { + description = "Standalone MPD Web GUI written in C"; + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${pkgs.ympd}/bin/ympd --host ${cfg.mpd.host} --port ${toString cfg.mpd.port} --webport ${cfg.webPort} --user nobody"; + }; + + }; + +} diff --git a/nixos/modules/services/continuous-integration/gocd-agent/default.nix b/nixos/modules/services/continuous-integration/gocd-agent/default.nix index 21f319f7fcf6..d60b55e83d11 100644 --- a/nixos/modules/services/continuous-integration/gocd-agent/default.nix +++ b/nixos/modules/services/continuous-integration/gocd-agent/default.nix @@ -98,7 +98,7 @@ in { ]; description = '' Specifies startup command line arguments to pass to Go.CD agent - java process. Example contains debug and gcLog arguments. + java process. ''; }; diff --git a/nixos/modules/services/continuous-integration/gocd-server/default.nix b/nixos/modules/services/continuous-integration/gocd-server/default.nix index 2d1986301216..4bb792055d25 100644 --- a/nixos/modules/services/continuous-integration/gocd-server/default.nix +++ b/nixos/modules/services/continuous-integration/gocd-server/default.nix @@ -90,7 +90,7 @@ in { ''; }; - extraOptions = mkOption { + startupOptions = mkOption { default = [ "-Xms${cfg.initialJavaHeapSize}" "-Xmx${cfg.maxJavaHeapMemory}" @@ -103,6 +103,15 @@ in { "-Dcruise.server.port=${toString cfg.port}" "-Dcruise.server.ssl.port=${toString cfg.sslPort}" ]; + + description = '' + Specifies startup command line arguments to pass to Go.CD server + java process. + ''; + }; + + extraOptions = mkOption { + default = [ ]; example = [ "-X debug" "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" @@ -169,7 +178,8 @@ in { script = '' ${pkgs.git}/bin/git config --global --add http.sslCAinfo /etc/ssl/certs/ca-certificates.crt - ${pkgs.jre}/bin/java -server ${concatStringsSep " " cfg.extraOptions} \ + ${pkgs.jre}/bin/java -server ${concatStringsSep " " cfg.startupOptions} \ + ${concatStringsSep " " cfg.extraOptions} \ -jar ${pkgs.gocd-server}/go-server/go.jar ''; diff --git a/nixos/modules/services/databases/4store-endpoint.nix b/nixos/modules/services/databases/4store-endpoint.nix index 5c55ef406d57..906cb320df98 100644 --- a/nixos/modules/services/databases/4store-endpoint.nix +++ b/nixos/modules/services/databases/4store-endpoint.nix @@ -61,7 +61,9 @@ with lib; services.avahi.enable = true; systemd.services."4store-endpoint" = { - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + script = '' ${run} '${pkgs.rdf4store}/bin/4s-httpd -D ${cfg.options} ${if cfg.listenAddress!=null then "-H ${cfg.listenAddress}" else "" } -p ${toString cfg.port} ${cfg.database}' ''; diff --git a/nixos/modules/services/databases/4store.nix b/nixos/modules/services/databases/4store.nix index 33e731e96816..62856822f906 100644 --- a/nixos/modules/services/databases/4store.nix +++ b/nixos/modules/services/databases/4store.nix @@ -53,7 +53,8 @@ with lib; services.avahi.enable = true; systemd.services."4store" = { - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p ${stateDir}/ diff --git a/nixos/modules/services/databases/virtuoso.nix b/nixos/modules/services/databases/virtuoso.nix index bdd210a2550e..3231fede08fa 100644 --- a/nixos/modules/services/databases/virtuoso.nix +++ b/nixos/modules/services/databases/virtuoso.nix @@ -62,7 +62,8 @@ with lib; }; systemd.services.virtuoso = { - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p ${stateDir} diff --git a/nixos/modules/services/editors/emacs.nix b/nixos/modules/services/editors/emacs.nix index 6795ec52fe4d..08fa6de6374c 100644 --- a/nixos/modules/services/editors/emacs.nix +++ b/nixos/modules/services/editors/emacs.nix @@ -79,9 +79,13 @@ in { environment.systemPackages = [ cfg.package editorScript ]; - environment.variables = if cfg.defaultEditor then { - EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor"; - } else {}; + environment.variables = { + # This is required so that GTK applications launched from Emacs + # get properly themed: + GTK_DATA_PREFIX = "${config.system.path}"; + } // (if cfg.defaultEditor then { + EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor"; + } else {}); }; meta.doc = ./emacs.xml; diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index f239dda564a2..e79d5dadd828 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -271,6 +271,9 @@ in { assertion = cfg.showPAMFailure -> cfg.enablePAM; message = "dovecot is configured with showPAMFailure while enablePAM is disabled"; } + { assertion = (cfg.sieveScripts != {}) -> ((cfg.mailUser != null) && (cfg.mailGroup != null)); + message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set"; + } ]; }; diff --git a/nixos/modules/services/mail/freepops.nix b/nixos/modules/services/mail/freepops.nix index e8c30a36923f..5b729ca50a5e 100644 --- a/nixos/modules/services/mail/freepops.nix +++ b/nixos/modules/services/mail/freepops.nix @@ -74,7 +74,8 @@ in config = mkIf cfg.enable { systemd.services.freepopsd = { description = "Freepopsd (webmail over POP3)"; - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; script = '' ${pkgs.freepops}/bin/freepopsd \ -p ${toString cfg.port} \ diff --git a/nixos/modules/services/misc/docker-registry.nix b/nixos/modules/services/misc/docker-registry.nix deleted file mode 100644 index add339f9bdfe..000000000000 --- a/nixos/modules/services/misc/docker-registry.nix +++ /dev/null @@ -1,81 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.dockerRegistry; - -in { - ###### interface - - options.services.dockerRegistry = { - enable = mkOption { - description = "Whether to enable docker registry server."; - default = false; - type = types.bool; - }; - - listenAddress = mkOption { - description = "Docker registry host or ip to bind to."; - default = "127.0.0.1"; - type = types.str; - }; - - port = mkOption { - description = "Docker registry port to bind to."; - default = 5000; - type = types.int; - }; - - storagePath = mkOption { - type = types.path; - default = "/var/lib/docker-registry"; - description = "Docker registry storage path."; - }; - - extraConfig = mkOption { - description = '' - Docker extra registry configuration. See - <link xlink:href="https://github.com/docker/docker-registry/blob/master/config/config_sample.yml"/> - ''; - default = {}; - type = types.attrsOf types.str; - }; - }; - - config = mkIf cfg.enable { - systemd.services.docker-registry = { - description = "Docker Container Registry"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - environment = { - REGISTRY_HOST = cfg.listenAddress; - REGISTRY_PORT = toString cfg.port; - GUNICORN_OPTS = "[--preload]"; # see https://github.com/docker/docker-registry#sqlalchemy - STORAGE_PATH = cfg.storagePath; - } // cfg.extraConfig; - - serviceConfig = { - ExecStart = "${pkgs.pythonPackages.docker_registry}/bin/docker-registry"; - User = "docker-registry"; - Group = "docker"; - PermissionsStartOnly = true; - WorkingDirectory = cfg.storagePath; - }; - - postStart = '' - until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/'; do - sleep 1; - done - ''; - }; - - users.extraGroups.docker.gid = mkDefault config.ids.gids.docker; - users.extraUsers.docker-registry = { - createHome = true; - home = cfg.storagePath; - uid = config.ids.uids.docker-registry; - }; - }; -} diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix new file mode 100644 index 000000000000..31979d2660cc --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -0,0 +1,418 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.prometheus; + promUser = "prometheus"; + promGroup = "prometheus"; + + # Get a submodule without any embedded metadata: + _filter = x: filterAttrs (k: v: k != "_module") x; + + # Pretty-print JSON to a file + writePrettyJSON = name: x: + pkgs.runCommand name { } '' + echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out + ''; + + # This becomes the main config file + promConfig = { + global = cfg.globalConfig; + rule_files = cfg.ruleFiles ++ [ + (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules)) + ]; + scrape_configs = cfg.scrapeConfigs; + }; + + cmdlineArgs = cfg.extraFlags ++ [ + "-storage.local.path=${cfg.dataDir}/metrics" + "-config.file=${writePrettyJSON "prometheus.yml" promConfig}" + "-web.listen-address=${cfg.listenAddress}" + ]; + + promTypes.globalConfig = types.submodule { + options = { + scrape_interval = mkOption { + type = types.str; + default = "1m"; + description = '' + How frequently to scrape targets by default. + ''; + }; + + scrape_timeout = mkOption { + type = types.str; + default = "10s"; + description = '' + How long until a scrape request times out. + ''; + }; + + evaluation_interval = mkOption { + type = types.str; + default = "1m"; + description = '' + How frequently to evaluate rules by default. + ''; + }; + + labels = mkOption { + type = types.attrsOf types.str; + default = {}; + description = '' + The labels to add to any timeseries that this Prometheus instance + scrapes. + ''; + }; + }; + }; + + promTypes.scrape_config = types.submodule { + options = { + job_name = mkOption { + type = types.str; + description = '' + The job name assigned to scraped metrics by default. + ''; + }; + scrape_interval = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + How frequently to scrape targets from this job. Defaults to the + globally configured default. + ''; + }; + scrape_timeout = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Per-target timeout when scraping this job. Defaults to the + globally configured default. + ''; + }; + metrics_path = mkOption { + type = types.str; + default = "/metrics"; + description = '' + The HTTP resource path on which to fetch metrics from targets. + ''; + }; + scheme = mkOption { + type = types.enum ["http" "https"]; + default = "http"; + description = '' + The URL scheme with which to fetch metrics from targets. + ''; + }; + basic_auth = mkOption { + type = types.nullOr (types.submodule { + options = { + username = mkOption { + type = types.str; + description = '' + HTTP username + ''; + }; + password = mkOption { + type = types.str; + description = '' + HTTP password + ''; + }; + }; + }); + default = null; + description = '' + Optional http login credentials for metrics scraping. + ''; + }; + dns_sd_configs = mkOption { + type = types.listOf promTypes.dns_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of DNS service discovery configurations. + ''; + }; + consul_sd_configs = mkOption { + type = types.listOf promTypes.consul_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of Consul service discovery configurations. + ''; + }; + file_sd_configs = mkOption { + type = types.listOf promTypes.file_sd_config; + default = []; + apply = x: map _filter x; + description = '' + List of file service discovery configurations. + ''; + }; + static_configs = mkOption { + type = types.listOf promTypes.static_config; + default = []; + apply = x: map _filter x; + description = '' + List of labeled target groups for this job. + ''; + }; + relabel_configs = mkOption { + type = types.listOf promTypes.relabel_config; + default = []; + apply = x: map _filter x; + description = '' + List of relabel configurations. + ''; + }; + }; + }; + + promTypes.static_config = types.submodule { + options = { + targets = mkOption { + type = types.listOf types.str; + description = '' + The targets specified by the target group. + ''; + }; + labels = mkOption { + type = types.attrsOf types.str; + description = '' + Labels assigned to all metrics scraped from the targets. + ''; + }; + }; + }; + + promTypes.dns_sd_config = types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; + description = '' + A list of DNS SRV record names to be queried. + ''; + }; + refresh_interval = mkOption { + type = types.str; + default = "30s"; + description = '' + The time after which the provided names are refreshed. + ''; + }; + }; + }; + + promTypes.consul_sd_config = types.submodule { + options = { + server = mkOption { + type = types.str; + description = "Consul server to query."; + }; + token = mkOption { + type = types.nullOr types.str; + description = "Consul token"; + }; + datacenter = mkOption { + type = types.nullOr types.str; + description = "Consul datacenter"; + }; + scheme = mkOption { + type = types.nullOr types.str; + description = "Consul scheme"; + }; + username = mkOption { + type = types.nullOr types.str; + description = "Consul username"; + }; + password = mkOption { + type = types.nullOr types.str; + description = "Consul password"; + }; + + services = mkOption { + type = types.listOf types.str; + description = '' + A list of services for which targets are retrieved. + ''; + }; + tag_separator = mkOption { + type = types.str; + default = ","; + description = '' + The string by which Consul tags are joined into the tag label. + ''; + }; + }; + }; + + promTypes.file_sd_config = types.submodule { + options = { + files = mkOption { + type = types.listOf types.str; + description = '' + Patterns for files from which target groups are extracted. Refer + to the Prometheus documentation for permitted filename patterns + and formats. + + ''; + }; + refresh_interval = mkOption { + type = types.str; + default = "30s"; + description = '' + Refresh interval to re-read the files. + ''; + }; + }; + }; + + promTypes.relabel_config = types.submodule { + options = { + source_labels = mkOption { + type = types.listOf types.str; + description = '' + The source labels select values from existing labels. Their content + is concatenated using the configured separator and matched against + the configured regular expression. + ''; + }; + separator = mkOption { + type = types.str; + default = ";"; + description = '' + Separator placed between concatenated source label values. + ''; + }; + target_label = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Label to which the resulting value is written in a replace action. + It is mandatory for replace actions. + ''; + }; + regex = mkOption { + type = types.str; + description = '' + Regular expression against which the extracted value is matched. + ''; + }; + replacement = mkOption { + type = types.str; + default = ""; + description = '' + Replacement value against which a regex replace is performed if the + regular expression matches. + ''; + }; + action = mkOption { + type = types.enum ["replace" "keep" "drop"]; + description = '' + Action to perform based on regex matching. + ''; + }; + }; + }; + +in { + options = { + services.prometheus = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the Prometheus monitoring daemon. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = "0.0.0.0:9090"; + description = '' + Address to listen on for the web interface, API, and telemetry. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/prometheus"; + description = '' + Directory to store Prometheus metrics data. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Extra commandline options when launching Prometheus. + ''; + }; + + globalConfig = mkOption { + type = promTypes.globalConfig; + default = {}; + apply = _filter; + description = '' + Parameters that are valid in all configuration contexts. They + also serve as defaults for other configuration sections + ''; + }; + + rules = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Alerting and/or Recording rules to evaluate at runtime. + ''; + }; + + ruleFiles = mkOption { + type = types.listOf types.path; + default = []; + description = '' + Any additional rules files to include in this configuration. + ''; + }; + + scrapeConfigs = mkOption { + type = types.listOf promTypes.scrape_config; + default = []; + apply = x: map _filter x; + description = '' + A list of scrape configurations. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraGroups.${promGroup}.gid = config.ids.gids.prometheus; + users.extraUsers.${promUser} = { + description = "Prometheus daemon user"; + uid = config.ids.uids.prometheus; + group = promGroup; + home = cfg.dataDir; + createHome = true; + }; + systemd.services.prometheus = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + script = '' + #!/bin/sh + exec ${pkgs.prometheus}/bin/prometheus \ + ${concatStringsSep " \\\n " cmdlineArgs} + ''; + serviceConfig = { + User = promUser; + Restart = "always"; + WorkingDirectory = cfg.dataDir; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/node-exporter.nix b/nixos/modules/services/monitoring/prometheus/node-exporter.nix new file mode 100644 index 000000000000..02aedb53564d --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/node-exporter.nix @@ -0,0 +1,74 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.prometheus.nodeExporter; + cmdlineArgs = cfg.extraFlags ++ [ + "-web.listen-address=${cfg.listenAddress}" + ]; +in { + options = { + services.prometheus.nodeExporter = { + enable = mkEnableOption "prometheus node exporter"; + + port = mkOption { + type = types.int; + default = 9100; + description = '' + Port to listen on. + ''; + }; + + listenAddress = mkOption { + type = types.string; + default = "0.0.0.0"; + description = '' + Address to listen on. + ''; + }; + + enabledCollectors = mkOption { + type = types.listOf types.string; + default = []; + example = ''[ "systemd" ]''; + description = '' + Collectors to enable, additionally to the defaults. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Extra commandline options when launching the node exporter. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ cfg.port ]; + + systemd.services.prometheus-node-exporter = { + description = "Prometheus exporter for machine metrics"; + unitConfig.Documentation = "https://github.com/prometheus/node_exporter"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + script = '' + exec ${pkgs.prometheus-node-exporter}/bin/node_exporter \ + ${optionalString (cfg.enabledCollectors != []) + ''-collectors.enabled ${concatStringsSep "," cfg.enabledCollectors}''} \ + -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ + ${concatStringsSep " \\\n " cfg.extraFlags} + ''; + serviceConfig = { + User = "nobody"; + Restart = "always"; + PrivateTmp = true; + WorkingDirectory = /tmp; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix index 5f80d547dbcb..febf0c95f5bd 100644 --- a/nixos/modules/services/monitoring/ups.nix +++ b/nixos/modules/services/monitoring/ups.nix @@ -182,7 +182,8 @@ in systemd.services.upsmon = { description = "Uninterruptible Power Supplies (Monitor)"; - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; serviceConfig.Type = "forking"; script = "${pkgs.nut}/sbin/upsmon"; environment.NUT_CONFPATH = "/etc/nut/"; @@ -191,8 +192,8 @@ in systemd.services.upsd = { description = "Uninterruptible Power Supplies (Daemon)"; + after = [ "network.target" "upsmon.service" ]; wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" "upsmon.service" ]; serviceConfig.Type = "forking"; # TODO: replace 'root' by another username. script = "${pkgs.nut}/sbin/upsd -u root"; @@ -202,8 +203,8 @@ in systemd.services.upsdrv = { description = "Uninterruptible Power Supplies (Register all UPS)"; - wantedBy = [ "multi-user.target" ]; after = [ "upsd.service" ]; + wantedBy = [ "multi-user.target" ]; # TODO: replace 'root' by another username. script = ''${pkgs.nut}/bin/upsdrvctl -u root start''; serviceConfig = { diff --git a/nixos/modules/services/network-filesystems/drbd.nix b/nixos/modules/services/network-filesystems/drbd.nix index 9896a93b1894..57b1fbb597c7 100644 --- a/nixos/modules/services/network-filesystems/drbd.nix +++ b/nixos/modules/services/network-filesystems/drbd.nix @@ -53,9 +53,9 @@ let cfg = config.services.drbd; in }; systemd.services.drbd = { - after = [ "systemd-udev.settle.service" ]; + after = [ "systemd-udev.settle.service" "network.target" ]; wants = [ "systemd-udev.settle.service" ]; - wantedBy = [ "ip-up.target" ]; + wantedBy = [ "multi-user.target" ]; script = '' ${pkgs.drbd}/sbin/drbdadm up all ''; diff --git a/nixos/modules/services/networking/amuled.nix b/nixos/modules/services/networking/amuled.nix index bc488d0e9100..fc7d56a24fa7 100644 --- a/nixos/modules/services/networking/amuled.nix +++ b/nixos/modules/services/networking/amuled.nix @@ -59,7 +59,8 @@ in systemd.services.amuled = { description = "AMule daemon"; - wantedBy = [ "ip-up.target" ]; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; preStart = '' mkdir -p ${cfg.dataDir} diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix index 7650f45c5570..ecc091d1d03d 100644 --- a/nixos/modules/services/networking/avahi-daemon.nix +++ b/nixos/modules/services/networking/avahi-daemon.nix @@ -7,10 +7,6 @@ let cfg = config.services.avahi; - # We must escape interfaces due to the systemd interpretation - subsystemDevice = interface: - "sys-subsystem-net-devices-${utils.escapeSystemdPath interface}.device"; - avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" '' [server] ${# Users can set `networking.hostName' to the empty string, when getting @@ -75,7 +71,8 @@ in }; browseDomains = mkOption { - default = [ "0pointer.de" "zeroconf.org" ]; + default = [ ]; + example = [ "0pointer.de" "zeroconf.org" ]; description = '' List of non-local DNS domains to be browsed. ''; @@ -179,14 +176,8 @@ in environment.systemPackages = [ pkgs.avahi ]; systemd.services.avahi-daemon = - let - deps = optionals (cfg.interfaces!=null) (map subsystemDevice cfg.interfaces); - in { description = "Avahi daemon"; - wantedBy = [ "ip-up.target" ]; - bindsTo = deps; - after = deps; - before = [ "ip-up.target" ]; + wantedBy = [ "multi-user.target" ]; # Receive restart event after resume partOf = [ "post-resume.target" ]; diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index b31d479ab4fd..4b0e90886510 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -10,7 +10,8 @@ let interfaces = attrValues config.networking.interfaces; - enableDHCP = config.networking.useDHCP || any (i: i.useDHCP == true) interfaces; + enableDHCP = config.networking.dhcpcd.enable && + (config.networking.useDHCP || any (i: i.useDHCP == true) interfaces); # Don't start dhcpcd on explicitly configured interfaces or on # interfaces that are part of a bridge, bond or sit device. @@ -61,7 +62,6 @@ let ${cfg.extraConfig} ''; - # Hook for emitting ip-up/ip-down events. exitHook = pkgs.writeText "dhcpcd.exit-hook" '' if [ "$reason" = BOUND -o "$reason" = REBOOT ]; then @@ -73,14 +73,8 @@ let # applies to openntpd. ${config.systemd.package}/bin/systemctl try-restart ntpd.service ${config.systemd.package}/bin/systemctl try-restart openntpd.service - - ${config.systemd.package}/bin/systemctl start ip-up.target fi - #if [ "$reason" = EXPIRE -o "$reason" = RELEASE -o "$reason" = NOCARRIER ] ; then - # ${config.systemd.package}/bin/systemctl start ip-down.target - #fi - ${cfg.runHook} ''; @@ -92,6 +86,15 @@ in options = { + networking.dhcpcd.enable = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable dhcpcd for device configuration. This is mainly to + explicitly disable dhcpcd (for example when using networkd). + ''; + }; + networking.dhcpcd.persistent = mkOption { type = types.bool; default = false; @@ -154,10 +157,9 @@ in systemd.services.dhcpcd = { description = "DHCP Client"; - wantedBy = [ "network.target" ]; - # Work-around to deal with problems where the kernel would remove & - # re-create Wifi interfaces early during boot. - after = [ "network-interfaces.target" ]; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + before = [ "network.target" ]; # Stopping dhcpcd during a reconfiguration is undesirable # because it brings down the network interfaces configured by diff --git a/nixos/modules/services/networking/docker-registry-server.nix b/nixos/modules/services/networking/docker-registry-server.nix deleted file mode 100644 index d21bbb6a86c3..000000000000 --- a/nixos/modules/services/networking/docker-registry-server.nix +++ /dev/null @@ -1,98 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.nodeDockerRegistry; - -in { - options.services.nodeDockerRegistry = { - enable = mkEnableOption "docker registry service"; - - port = mkOption { - description = "Docker registry listening port."; - default = 8080; - type = types.int; - }; - - users = mkOption { - description = "Docker registry list of users."; - default = []; - options = [{ - user = mkOption { - description = "Docker registry user username."; - type = types.str; - }; - - pass = mkOption { - description = "Docker registry user password."; - type = types.str; - }; - }]; - type = types.listOf types.optionSet; - }; - - onTag = mkOption { - description = "Docker registry hook triggered when an image is tagged."; - default = ""; - type = types.str; - }; - - onImage = mkOption { - description = "Docker registry hook triggered when an image metadata is uploaded."; - default = ""; - type = types.str; - }; - - onLayer = mkOption { - description = "Docker registry hook triggered when an when an image layer is uploaded."; - default = ""; - type = types.str; - }; - - onVerify = mkOption { - description = "Docker registry hook triggered when an image layer+metadata has been verified."; - default = ""; - type = types.str; - }; - - onIndex = mkOption { - description = "Docker registry hook triggered when an when an image file system data has been indexed."; - default = ""; - type = types.str; - }; - - dataDir = mkOption { - description = "Docker registry data directory"; - default = "/var/lib/docker-registry"; - type = types.path; - }; - }; - - config = mkIf cfg.enable { - systemd.services.docker-registry-server = { - description = "Docker Registry Service."; - wantedBy = ["multi-user.target"]; - after = ["network.target"]; - script = '' - ${pkgs.nodePackages.docker-registry-server}/bin/docker-registry-server \ - --dir ${cfg.dataDir} \ - --port ${toString cfg.port} \ - ${concatMapStringsSep " " (u: "--user ${u.user}:${u.pass}") cfg.users} \ - ${optionalString (cfg.onTag != "") "--on-tag '${cfg.onTag}'"} \ - ${optionalString (cfg.onImage != "") "--on-image '${cfg.onImage}'"} \ - ${optionalString (cfg.onVerify != "") "--on-verify '${cfg.onVerify}'"} \ - ${optionalString (cfg.onIndex != "") "--on-index '${cfg.onIndex}'"} - ''; - - serviceConfig.User = "docker-registry"; - }; - - users.extraUsers.docker-registry = { - uid = config.ids.uids.docker-registry; - description = "Docker registry user"; - createHome = true; - home = cfg.dataDir; - }; - }; -} diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix index 138153306dd8..942fcc03f59b 100644 --- a/nixos/modules/services/networking/firewall.nix +++ b/nixos/modules/services/networking/firewall.nix @@ -490,7 +490,8 @@ in systemd.services.firewall = { description = "Firewall"; - wantedBy = [ "network-pre.target" ]; + wantedBy = [ "sysinit.target" ]; + wants = [ "network-pre.target" ]; before = [ "network-pre.target" ]; after = [ "systemd-modules-load.service" ]; @@ -500,6 +501,7 @@ in # containers don't have CAP_SYS_MODULE. So the host system had # better have all necessary modules already loaded. unitConfig.ConditionCapability = "CAP_NET_ADMIN"; + unitConfig.DefaultDependencies = false; reloadIfChanged = true; diff --git a/nixos/modules/services/networking/git-daemon.nix b/nixos/modules/services/networking/git-daemon.nix index 215ffe48a563..cd3fcd0f8f66 100644 --- a/nixos/modules/services/networking/git-daemon.nix +++ b/nixos/modules/services/networking/git-daemon.nix @@ -116,7 +116,8 @@ in }; systemd.services."git-daemon" = { - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; script = "${pkgs.git}/bin/git daemon --reuseaddr " + (optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ") + (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ") diff --git a/nixos/modules/services/networking/iodine.nix b/nixos/modules/services/networking/iodine.nix index 1b0d2d9a517c..512dbd77ae4b 100644 --- a/nixos/modules/services/networking/iodine.nix +++ b/nixos/modules/services/networking/iodine.nix @@ -106,7 +106,8 @@ in createIodineClientService = name: cfg: { description = "iodine client - ${name}"; - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; serviceConfig = { RestartSec = "30s"; Restart = "always"; @@ -121,7 +122,8 @@ in ) // { iodined = mkIf (cfg.server.enable) { description = "iodine, ip over dns server daemon"; - wantedBy = [ "ip-up.target" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; serviceConfig.ExecStart = "${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${cfg.server.ip} ${cfg.server.domain}"; }; }; diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index d198e3bfc02c..65ffaece4772 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -52,14 +52,6 @@ let }); ''; - ipUpScript = writeScript "01nixos-ip-up" '' - #!/bin/sh - if test "$2" = "up"; then - ${config.systemd.package}/bin/systemctl start ip-up.target - ${config.systemd.package}/bin/systemctl start network-online.target - fi - ''; - ns = xs: writeText "nameservers" ( concatStrings (map (s: "nameserver ${s}\n") xs) ); @@ -188,9 +180,6 @@ in { boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections. environment.etc = with cfg.basePackages; [ - { source = ipUpScript; - target = "NetworkManager/dispatcher.d/01nixos-ip-up"; - } { source = configFile; target = "NetworkManager/NetworkManager.conf"; } diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix index 19762f4e570c..d5e2e3041b49 100644 --- a/nixos/modules/services/networking/radicale.nix +++ b/nixos/modules/services/networking/radicale.nix @@ -52,8 +52,7 @@ in description = "A Simple Calendar and Contact Server"; after = [ "network-interfaces.target" ]; wantedBy = [ "multi-user.target" ]; - script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -d"; - serviceConfig.Type = "forking"; + script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -f"; serviceConfig.User = "radicale"; serviceConfig.Group = "radicale"; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index f900ef494abf..1d15a1419722 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -85,7 +85,7 @@ in forwardX11 = mkOption { type = types.bool; - default = cfgc.setXAuthLocation; + default = false; description = '' Whether to allow X11 connections to be forwarded. ''; @@ -227,6 +227,8 @@ in config = mkIf cfg.enable { + programs.ssh.setXAuthLocation = mkForce cfg.forwardX11; + users.extraUsers.sshd = { isSystemUser = true; description = "SSH privilege separation user"; diff --git a/nixos/modules/services/networking/toxvpn.nix b/nixos/modules/services/networking/toxvpn.nix index c38424c8e273..911836fdee42 100644 --- a/nixos/modules/services/networking/toxvpn.nix +++ b/nixos/modules/services/networking/toxvpn.nix @@ -25,8 +25,8 @@ with lib; systemd.services.toxvpn = { description = "toxvpn daemon"; - requires = [ "network-online.target" ]; # consider replacing by NetworkManager-wait-online.service wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; preStart = '' mkdir -p /run/toxvpn || true diff --git a/nixos/modules/services/security/haveged.nix b/nixos/modules/services/security/haveged.nix index 2aa523bf70a4..eca529188810 100644 --- a/nixos/modules/services/security/haveged.nix +++ b/nixos/modules/services/security/haveged.nix @@ -48,14 +48,18 @@ in { description = "Entropy Harvesting Daemon"; unitConfig.Documentation = "man:haveged(8)"; wantedBy = [ "multi-user.target" ]; - + path = [ pkgs.haveged ]; - - serviceConfig = - { Type = "forking"; - ExecStart = "${pkgs.haveged}/sbin/haveged -w ${toString cfg.refill_threshold} -v 1"; - PIDFile = "/run/haveged.pid"; - }; + + serviceConfig = { + ExecStart = "${pkgs.haveged}/bin/haveged -F -w ${toString cfg.refill_threshold} -v 1"; + SuccessExitStatus = 143; + PrivateTmp = true; + PrivateDevices = true; + PrivateNetwork = true; + ProtectSystem = "full"; + ProtectHome = true; + }; }; }; diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 8bcd6f01656d..6c4833afbe8b 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -84,7 +84,7 @@ in config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus_tools ]; + environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ]; environment.etc = singleton { source = configDir; @@ -104,7 +104,7 @@ in security.setuidOwners = singleton { program = "dbus-daemon-launch-helper"; - source = "${pkgs.dbus_daemon.out}/libexec/dbus-daemon-launch-helper"; + source = "${pkgs.dbus.daemon}/libexec/dbus-daemon-launch-helper"; owner = "root"; group = "messagebus"; setuid = true; diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix index ea7196fc8733..051d54e932fb 100644 --- a/nixos/modules/services/ttys/agetty.nix +++ b/nixos/modules/services/ttys/agetty.nix @@ -80,8 +80,7 @@ in }; systemd.services."container-getty@" = - { unitConfig.ConditionPathExists = "/dev/pts/%I"; # Work around being respawned when "machinectl login" exits. - serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM"; + { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM"; restartIfChanged = false; }; diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index b08070f1e366..5193814da725 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -18,7 +18,6 @@ let poolName = "tt-rss"; phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock"; - virtualHostName = "tt-rss"; tt-rss-config = pkgs.writeText "config.php" '' <?php @@ -34,10 +33,10 @@ let define('MYSQL_CHARSET', 'UTF8'); define('DB_TYPE', '${cfg.database.type}'); - define('DB_HOST', '${cfg.database.host}'); + define('DB_HOST', '${optionalString (cfg.database.host != null) cfg.database.host}'); define('DB_USER', '${cfg.database.user}'); define('DB_NAME', '${cfg.database.name}'); - define('DB_PASS', '${escape ["'" "\\"] cfg.database.password}'); + define('DB_PASS', '${optionalString (cfg.database.password != null) (escape ["'" "\\"] cfg.database.password)}'); define('DB_PORT', '${toString dbPort}'); define('AUTH_AUTO_CREATE', ${boolToString cfg.auth.autoCreate}); @@ -91,12 +90,21 @@ let enable = mkEnableOption "tt-rss"; + root = mkOption { + type = types.path; + default = "/var/lib/tt-rss"; + example = "/var/lib/tt-rss"; + description = '' + Root of the application. + ''; + }; + user = mkOption { type = types.str; default = "nginx"; example = "nginx"; description = '' - User account under which both the service and the web-application run. + User account under which both the update daemon and the web-application run. ''; }; @@ -110,17 +118,13 @@ let ''; }; - # TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged - - # virtualHost = mkOption { - # type = types.str; - # default = "${virtualHostName}"; - # description = '' - # Name of existing nginx virtual host that is used to run web-application. - # If not specified a host will be created automatically with - # default values. - # ''; - # }; + virtualHost = mkOption { + type = types.nullOr types.str; + default = "tt-rss"; + description = '' + Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost. + ''; + }; database = { type = mkOption { @@ -132,10 +136,10 @@ let }; host = mkOption { - type = types.str; - default = "localhost"; + type = types.nullOr types.str; + default = null; description = '' - Host of the database. + Host of the database. Leave null to use Unix domain socket. ''; }; @@ -362,7 +366,7 @@ let singleUserMode = mkOption { type = types.bool; - default = true; + default = false; description = '' Operate in single user mode, disables all functionality related to @@ -445,17 +449,15 @@ let ###### implementation - config = let - root = "/var/lib/tt-rss"; - in mkIf cfg.enable { + config = mkIf cfg.enable { - services.phpfpm.poolConfigs = if cfg.pool == "${poolName}" then { + services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") { "${poolName}" = '' listen = "${phpfpmSocketName}"; listen.owner = nginx listen.group = nginx listen.mode = 0600 - user = nginx + user = ${cfg.user} pm = dynamic pm.max_children = 75 pm.start_servers = 10 @@ -464,36 +466,26 @@ let pm.max_requests = 500 catch_workers_output = 1 ''; - } else {}; - - # TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged - - # services.nginx.virtualHosts = if cfg.virtualHost == "${virtualHostName}" then { - # "${virtualHostName}" = { - # root = "${root}"; - # extraConfig = '' - # access_log /var/log/nginx-${virtualHostName}-access.log; - # error_log /var/log/nginx-${virtualHostName}-error.log; - # ''; - - # locations."/" = { - # extraConfig = '' - # index index.php; - # ''; - # }; - - # locations."~ \.php$" = { - # extraConfig = '' - # fastcgi_split_path_info ^(.+\.php)(/.+)$; - # fastcgi_pass unix:${phpfpmSocketName}; - # fastcgi_index index.php; - # fastcgi_param SCRIPT_FILENAME ${root}/$fastcgi_script_name; - - # include ${pkgs.nginx}/conf/fastcgi_params; - # ''; - # }; - # }; - # } else {}; + }; + + services.nginx.virtualHosts = mkIf (cfg.virtualHost != null) { + "${cfg.virtualHost}" = { + root = "${cfg.root}"; + + locations."/" = { + index = "index.php"; + }; + + locations."~ \.php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME ${cfg.root}/$fastcgi_script_name; + ''; + }; + }; + }; systemd.services.tt-rss = let @@ -503,35 +495,34 @@ let description = "Tiny Tiny RSS feeds update daemon"; preStart = let - callSql = if cfg.database.type == "pgsql" then (e: '' - ${optionalString (cfg.database.password != null) - "PGPASSWORD=${cfg.database.password}"} ${pkgs.postgresql95}/bin/psql \ - -U ${cfg.database.user} \ - -h ${cfg.database.host} \ - --port ${toString dbPort} \ - -c '${e}' \ - ${cfg.database.name}'') - - else if cfg.database.type == "mysql" then (e: '' - echo '${e}' | ${pkgs.mysql}/bin/mysql \ - ${optionalString (cfg.database.password != null) - "-p${cfg.database.password}"} \ - -u ${cfg.database.user} \ - -h ${cfg.database.host} \ - -P ${toString dbPort} \ - ${cfg.database.name}'') - - else ""; + callSql = e: + if cfg.database.type == "pgsql" then '' + ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \ + ${pkgs.postgresql95}/bin/psql \ + -U ${cfg.database.user} \ + ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \ + -c '${e}' \ + ${cfg.database.name}'' + + else if cfg.database.type == "mysql" then '' + echo '${e}' | ${pkgs.mysql}/bin/mysql \ + -u ${cfg.database.user} \ + ${optionalString (cfg.database.password != null) "-p${cfg.database.password}"} \ + ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} -P ${toString dbPort}"} \ + ${cfg.database.name}'' + + else ""; in '' - rm -rf "${root}/*" - mkdir -m 755 -p "${root}" - cp -r "${pkgs.tt-rss}/"* "${root}" - ln -sf "${tt-rss-config}" "${root}/config.php" - chown -R "${cfg.user}" "${root}" - chmod -R 755 "${root}" - '' + (optionalString (cfg.database.type == "pgsql") '' - + rm -rf "${cfg.root}/*" + mkdir -m 755 -p "${cfg.root}" + cp -r "${pkgs.tt-rss}/"* "${cfg.root}" + ln -sf "${tt-rss-config}" "${cfg.root}/config.php" + chown -R "${cfg.user}" "${cfg.root}" + chmod -R 755 "${cfg.root}" + '' + + + (optionalString (cfg.database.type == "pgsql") '' exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') @@ -540,8 +531,9 @@ let else echo 'The database contains some data. Leaving it as it is.' fi; - '') + (optionalString (cfg.database.type == "mysql") '' + '') + + (optionalString (cfg.database.type == "mysql") '' exists=$(${callSql "select count(*) > 0 from information_schema.tables where table_schema = schema()"} \ | tail -n+2 | sed -e 's/[ \n\t]*//') @@ -554,7 +546,7 @@ let serviceConfig = { User = "${cfg.user}"; - ExecStart = "${pkgs.php}/bin/php /var/lib/tt-rss/update.php --daemon"; + ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon"; StandardOutput = "syslog"; StandardError = "syslog"; PermissionsStartOnly = true; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 6e62606f323e..94c442e165b7 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -114,17 +114,18 @@ let port = if vhost.port != null then vhost.port else (if ssl then 443 else 80); listenString = toString port + optionalString ssl " ssl http2" + optionalString vhost.default " default"; - acmeLocation = optionalString vhost.enableACME '' + acmeLocation = optionalString vhost.enableACME ('' location /.well-known/acme-challenge { - try_files $uri @acme-fallback; + ${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"} root ${vhost.acmeRoot}; auth_basic off; } + '' + (optionalString (vhost.acmeFallbackHost != null) '' location @acme-fallback { auth_basic off; proxy_pass http://${vhost.acmeFallbackHost}; } - ''; + '')); in '' ${optionalString vhost.forceSSL '' server { diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index ee3f68bf8059..dcebbc9229fc 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -39,8 +39,8 @@ with lib; }; acmeFallbackHost = mkOption { - type = types.str; - default = "0.0.0.0"; + type = types.nullOr types.str; + default = null; description = '' Host which to proxy requests to if acme challenge is not found. Useful if you want multiple hosts to be able to verify the same domain name. diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix index c3be20b41e29..fa6b4c0629d7 100644 --- a/nixos/modules/services/web-servers/tomcat.nix +++ b/nixos/modules/services/web-servers/tomcat.nix @@ -10,6 +10,10 @@ in { + meta = { + maintainers = with maintainers; [ danbst ]; + }; + ###### interface options = { @@ -23,9 +27,9 @@ in package = mkOption { type = types.package; - default = pkgs.tomcat7; - defaultText = "pkgs.tomcat7"; - example = lib.literalExample "pkgs.tomcat8"; + default = pkgs.tomcat85; + defaultText = "pkgs.tomcat85"; + example = lib.literalExample "pkgs.tomcatUnstable"; description = '' Which tomcat package to use. ''; @@ -74,8 +78,8 @@ in webapps = mkOption { type = types.listOf types.package; - default = [ tomcat ]; - defaultText = "[ tomcat ]"; + default = [ tomcat.webapps ]; + defaultText = "[ tomcat.webapps ]"; description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat"; }; @@ -352,7 +356,7 @@ in ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh' ''; - postStop = '' + preStop = '' echo "Stopping tomcat..." CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh ''; diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index b03f70385b1f..6c6a1e79ed0e 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -654,6 +654,8 @@ in ${xrandrMonitorSections} ''; + fonts.enableDefaultFonts = mkDefault true; + }; } diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 1c587413121e..60298362d767 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -12,11 +12,13 @@ let ''; }); - path = map getBin - [ pkgs.coreutils pkgs.gnugrep pkgs.findutils - pkgs.glibc # needed for getent - pkgs.shadow - pkgs.nettools # needed for hostname + path = with pkgs; map getBin + [ coreutils + gnugrep + findutils + glibc # needed for getent + shadow + nettools # needed for hostname ]; in @@ -137,8 +139,13 @@ in mkdir -m 1777 -p /var/tmp - # Empty, read-only home directory of many system accounts. - mkdir -m 0555 -p /var/empty + # Empty, immutable home directory of many system accounts. + mkdir -p /var/empty + # Make sure it's really empty + ${pkgs.e2fsprogs}/bin/chattr -i /var/empty + find /var/empty -mindepth 1 -delete + chmod 0555 /var/empty + ${pkgs.e2fsprogs}/bin/chattr +i /var/empty ''; system.activationScripts.usrbinenv = if config.environment.usrbinenv != null diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix index 0f342f44fe76..ba15d0318b17 100644 --- a/nixos/modules/system/boot/kernel.nix +++ b/nixos/modules/system/boot/kernel.nix @@ -203,6 +203,12 @@ in # Misc. stuff. "pcips2" "atkbd" + # Temporary fix for https://github.com/NixOS/nixpkgs/issues/18451 + # Remove as soon as upstream gets fixed - marking it: + # TODO + # FIXME + "i8042" + # To wait for SCSI devices to appear. "scsi_wait_scan" diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index ab7485500261..38b4b437369d 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -677,8 +677,7 @@ in }; systemd.services.systemd-networkd-wait-online = { - before = [ "network-online.target" "ip-up.target" ]; - wantedBy = [ "network-online.target" "ip-up.target" ]; + wantedBy = [ "network-online.target" ]; }; systemd.services."systemd-network-wait-online@" = { diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh index 704150e77d72..ae88222f2780 100644 --- a/nixos/modules/system/boot/stage-2-init.sh +++ b/nixos/modules/system/boot/stage-2-init.sh @@ -29,7 +29,7 @@ setPath "@path@" # Normally, stage 1 mounts the root filesystem read/writable. # However, in some environments, stage 2 is executed directly, and the # root is read-only. So make it writable here. -if [ "$container" != systemd-nspawn ]; then +if [ -z "$container" ]; then mount -n -o remount,rw none / fi diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index df72be1b4be5..b724995bb1fc 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -14,6 +14,7 @@ let upstreamSystemUnits = [ # Targets. "basic.target" + "busnames.target" "sysinit.target" "sockets.target" "graphical.target" @@ -140,6 +141,7 @@ let "user.slice" "machine.slice" "systemd-machined.service" + "systemd-nspawn@.service" # Temporary file creation / cleanup. "systemd-tmpfiles-clean.service" @@ -569,6 +571,16 @@ in ''; }; + systemd.user.extraConfig = mkOption { + default = ""; + type = types.lines; + example = "DefaultCPUAccounting=yes"; + description = '' + Extra config options for systemd user instances. See man systemd-user.conf for + available options. + ''; + }; + systemd.tmpfiles.rules = mkOption { type = types.listOf types.str; default = []; @@ -663,6 +675,11 @@ in ${config.systemd.extraConfig} ''; + "systemd/user.conf".text = '' + [Manager] + ${config.systemd.user.extraConfig} + ''; + "systemd/journald.conf".text = '' [Journal] RateLimitInterval=${config.services.journald.rateLimitInterval} @@ -725,18 +742,6 @@ in unitConfig.X-StopOnReconfiguration = true; }; - systemd.targets.network-online.after = [ "ip-up.target" ]; - - systemd.targets.network-pre = { - wantedBy = [ "network.target" ]; - before = [ "network.target" ]; - }; - - systemd.targets.remote-fs-pre = { - wantedBy = [ "remote-fs.target" ]; - before = [ "remote-fs.target" ]; - }; - systemd.units = mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index a66ece1020f8..3c822c8716d0 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -286,11 +286,15 @@ in # Sync mount options with systemd's src/core/mount-setup.c: mount_table. boot.specialFileSystems = { "/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; }; - "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; }; "/run" = { fsType = "tmpfs"; options = [ "nodev" "strictatime" "mode=755" "size=${config.boot.runSize}" ]; }; "/dev" = { fsType = "devtmpfs"; options = [ "nosuid" "strictatime" "mode=755" "size=${config.boot.devSize}" ]; }; "/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; }; "/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "gid=${toString config.ids.gids.tty}" ]; }; + } // optionalAttrs (!config.boot.isContainer) { + # systemd-nspawn populates /sys by itself, and remounting it causes all + # kinds of weird issues (most noticeably, waiting for host disk device + # nodes). + "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; }; }; }; diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix index e454eca3a0e5..e9a7ccc721a9 100644 --- a/nixos/modules/tasks/filesystems/nfs.nix +++ b/nixos/modules/tasks/filesystems/nfs.nix @@ -38,15 +38,17 @@ in default = null; example = 4000; description = '' - Use fixed port for rpc.statd, useful if NFS server is behind firewall. + Use a fixed port for <command>rpc.statd</command>. This is + useful if the NFS server is behind a firewall. ''; }; lockdPort = mkOption { default = null; example = 4001; description = '' - Use fixed port for NFS lock manager kernel module (lockd/nlockmgr), - useful if NFS server is behind firewall. + Use a fixed port for the NFS lock manager kernel module + (<literal>lockd/nlockmgr</literal>). This is useful if the + NFS server is behind a firewall. ''; }; }; @@ -68,13 +70,16 @@ in boot.initrd.kernelModules = mkIf inInitrd [ "nfs" ]; + # FIXME: should use upstream units from nfs-utils. + systemd.services.statd = { description = "NFSv3 Network Status Monitor"; path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ]; - wantedBy = [ "remote-fs-pre.target" ]; + wants = [ "remote-fs-pre.target" ]; before = [ "remote-fs-pre.target" ]; + wantedBy = [ "remote-fs.target" ]; requires = [ "basic.target" "rpcbind.service" ]; after = [ "basic.target" "rpcbind.service" ]; @@ -100,8 +105,9 @@ in path = [ pkgs.sysvtools pkgs.utillinux ]; - wantedBy = [ "remote-fs-pre.target" ]; + wants = [ "remote-fs-pre.target" ]; before = [ "remote-fs-pre.target" ]; + wantedBy = [ "remote-fs.target" ]; requires = [ "rpcbind.service" ]; after = [ "rpcbind.service" ]; diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index c960e401f9b1..d1b62e0fd4e4 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -142,7 +142,6 @@ in # (Flushing this interface may have removed it.) ${config.systemd.package}/bin/systemctl try-restart --no-block network-setup.service fi - ${config.systemd.package}/bin/systemctl start ip-up.target ''; preStop = flip concatMapStrings (ips) (ip: let diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 301ee43fd0e5..974041d7e1a5 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -43,7 +43,7 @@ in message = "networking.bridges.${n}.rstp is not supported by networkd."; }); - systemd.services.dhcpcd.enable = mkDefault false; + networking.dhcpcd.enable = mkDefault false; systemd.services.network-local-commands = { after = [ "systemd-networkd.service" ]; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index c52bd904caec..dc62cae24c7a 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -231,7 +231,7 @@ let type = types.bool; description = '' Whether this interface is virtual and should be created by tunctl. - This is mainly useful for creating bridges between a host a virtual + This is mainly useful for creating bridges between a host and a virtual network such as VPN or a virtual machine. ''; }; diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix index a89cd454dc73..6817eb837a01 100644 --- a/nixos/modules/virtualisation/azure-agent.nix +++ b/nixos/modules/virtualisation/azure-agent.nix @@ -178,7 +178,8 @@ in systemd.services.waagent = { wantedBy = [ "multi-user.target" ]; - after = [ "ip-up.target" "sshd.service" ]; + after = [ "network-online.target" "sshd.service" ]; + wants = [ "network-online.target" ]; path = [ pkgs.e2fsprogs ]; description = "Windows Azure Agent Service"; diff --git a/nixos/modules/virtualisation/azure-bootstrap-blobs.nix b/nixos/modules/virtualisation/azure-bootstrap-blobs.nix new file mode 100644 index 000000000000..281be9a12318 --- /dev/null +++ b/nixos/modules/virtualisation/azure-bootstrap-blobs.nix @@ -0,0 +1,3 @@ +{ + "16.03" = "https://nixos.blob.core.windows.net/images/nixos-image-16.03.847.8688c17-x86_64-linux.vhd"; +} diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix index ab49d8871f85..e2905913b6c5 100644 --- a/nixos/modules/virtualisation/brightbox-image.nix +++ b/nixos/modules/virtualisation/brightbox-image.nix @@ -116,8 +116,8 @@ in wantedBy = [ "multi-user.target" "sshd.service" ]; before = [ "sshd.service" ]; - wants = [ "ip-up.target" ]; - after = [ "ip-up.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; path = [ pkgs.wget pkgs.iproute ]; diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index ebc2be087a5b..92fe98f3f9c2 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -40,13 +40,25 @@ in }; storageDriver = mkOption { - type = types.enum ["aufs" "btrfs" "devicemapper" "overlay" "zfs"]; - default = "devicemapper"; + type = types.nullOr (types.enum ["aufs" "btrfs" "devicemapper" "overlay" "overlay2" "zfs"]); + default = null; description = '' - This option determines which Docker storage driver to use. + This option determines which Docker storage driver to use. By default + it let's docker automatically choose preferred storage driver. ''; }; + + logDriver = + mkOption { + type = types.enum ["none" "json-file" "syslog" "journald" "gelf" "fluentd" "awslogs" "splunk" "etwlogs" "gcplogs"]; + default = "journald"; + description = + '' + This option determines which Docker log driver to use. + ''; + }; + extraOptions = mkOption { type = types.separatedString " "; @@ -88,7 +100,12 @@ in after = [ "network.target" ] ++ (optional cfg.socketActivation "docker.socket") ; requires = optional cfg.socketActivation "docker.socket"; serviceConfig = { - ExecStart = "${pkgs.docker}/bin/docker daemon --group=docker --storage-driver=${cfg.storageDriver} ${optionalString cfg.socketActivation "--host=fd://"} ${cfg.extraOptions}"; + ExecStart = ''${pkgs.docker}/bin/dockerd \ + --group=docker --log-driver=${cfg.logDriver} \ + ${optionalString (cfg.storageDriver != null) "--storage-driver=${cfg.storageDriver}"} \ + ${optionalString cfg.socketActivation "--host=fd://"} \ + ${cfg.extraOptions} + ''; # I'm not sure if that limits aren't too high, but it's what # goes in config bundled with docker itself LimitNOFILE = 1048576; diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index 59b77dde5d9a..489b612f1675 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -134,8 +134,8 @@ in wantedBy = [ "sshd.service" ]; before = [ "sshd.service" ]; - after = [ "network-online.target" "ip-up.target" ]; - wants = [ "network-online.target" "ip-up.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'"; mktemp = "mktemp --tmpdir=/run"; in diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix index ce4abecd6762..7214543871d6 100644 --- a/nixos/modules/virtualisation/virtualbox-host.nix +++ b/nixos/modules/virtualisation/virtualbox-host.nix @@ -4,10 +4,15 @@ with lib; let cfg = config.virtualisation.virtualbox.host; - virtualbox = config.boot.kernelPackages.virtualbox.override { + + virtualbox = pkgs.virtualbox.override { inherit (cfg) enableHardening headless; }; + kernelModules = config.boot.kernelPackages.virtualbox.override { + inherit virtualbox; + }; + in { @@ -60,7 +65,7 @@ in config = mkIf cfg.enable (mkMerge [{ boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ]; - boot.extraModulePackages = [ virtualbox ]; + boot.extraModulePackages = [ kernelModules ]; environment.systemPackages = [ virtualbox ]; security.setuidOwners = let diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index b6a5b3e4788d..d68b3bb73904 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -34,7 +34,7 @@ in { postVM = '' export HOME=$PWD - export PATH=${pkgs.linuxPackages.virtualbox}/bin:$PATH + export PATH=${pkgs.virtualbox}/bin:$PATH echo "creating VirtualBox pass-through disk wrapper (no copying invovled)..." VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index f2ca6af7e3a4..70b29aa23a5b 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -73,6 +73,7 @@ in rec { (all nixos.tests.ipv6) (all nixos.tests.i3wm) (all nixos.tests.kde4) + (all nixos.tests.kde5) #(all nixos.tests.lightdm) (all nixos.tests.login) (all nixos.tests.misc) @@ -88,6 +89,7 @@ in rec { (all nixos.tests.networking.scripted.sit) (all nixos.tests.networking.scripted.vlan) (all nixos.tests.nfs3) + (all nixos.tests.nfs4) (all nixos.tests.openssh) (all nixos.tests.printing) (all nixos.tests.proxy) diff --git a/nixos/release.nix b/nixos/release.nix index a5b4ab5f04cf..d66ebd7cb15c 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -228,7 +228,6 @@ in rec { tests.containers-imperative = callTest tests/containers-imperative.nix {}; tests.containers-extra_veth = callTest tests/containers-extra_veth.nix {}; tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; }); - tests.dockerRegistry = hydraJob (import tests/docker-registry.nix { system = "x86_64-linux"; }); tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; }; tests.ecryptfs = callTest tests/ecryptfs.nix {}; tests.etcd = hydraJob (import tests/etcd.nix { system = "x86_64-linux"; }); @@ -251,6 +250,7 @@ in rec { tests.ipv6 = callTest tests/ipv6.nix {}; tests.jenkins = callTest tests/jenkins.nix {}; tests.kde4 = callTest tests/kde4.nix {}; + tests.kde5 = callTest tests/kde5.nix {}; tests.keymap = callSubTests tests/keymap.nix {}; tests.initrdNetwork = callTest tests/initrd-network.nix {}; tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; }); @@ -274,7 +274,7 @@ in rec { tests.nfs4 = callTest tests/nfs.nix { version = 4; }; tests.nsd = callTest tests/nsd.nix {}; tests.openssh = callTest tests/openssh.nix {}; - tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; }); + #tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; }); tests.peerflix = callTest tests/peerflix.nix {}; tests.postgresql = callTest tests/postgresql.nix {}; tests.printing = callTest tests/printing.nix {}; @@ -284,7 +284,6 @@ in rec { tests.quake3 = callTest tests/quake3.nix {}; tests.runInMachine = callTest tests/run-in-machine.nix {}; tests.sddm = callTest tests/sddm.nix {}; - tests.sddm-kde5 = callTest tests/sddm-kde5.nix {}; tests.simple = callTest tests/simple.nix {}; tests.smokeping = callTest tests/smokeping.nix {}; tests.taskserver = callTest tests/taskserver.nix {}; diff --git a/nixos/tests/blivet.nix b/nixos/tests/blivet.nix index 33a79e65efe1..a7b836ce99a6 100644 --- a/nixos/tests/blivet.nix +++ b/nixos/tests/blivet.nix @@ -69,6 +69,7 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.pythonPackages; rec { sed -i \ -e '1i import tempfile' \ -e 's|_STORE_FILE_PATH = .*|_STORE_FILE_PATH = tempfile.gettempdir()|' \ + -e 's|DEFAULT_STORE_SIZE = .*|DEFAULT_STORE_SIZE = 409600|' \ tests/loopbackedtestcase.py PYTHONPATH=".:$(< "${pkgs.stdenv.mkDerivation { diff --git a/nixos/tests/docker-registry.nix b/nixos/tests/docker-registry.nix deleted file mode 100644 index eed3284202f5..000000000000 --- a/nixos/tests/docker-registry.nix +++ /dev/null @@ -1,43 +0,0 @@ -# This test runs docker-registry and check if it works - -import ./make-test.nix ({ pkgs, ...} : { - name = "docker-registry"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ offline ]; - }; - - nodes = { - registry = { config, pkgs, ... }: { - services.dockerRegistry.enable = true; - services.dockerRegistry.port = 8080; - services.dockerRegistry.host = "0.0.0.0"; - networking.firewall.allowedTCPPorts = [ 8080 ]; - }; - - client1 = { config, pkgs, ...}: { - virtualisation.docker.enable = true; - virtualisation.docker.extraOptions = "--insecure-registry registry:8080"; - }; - - client2 = { config, pkgs, ...}: { - virtualisation.docker.enable = true; - virtualisation.docker.extraOptions = "--insecure-registry registry:8080"; - }; - }; - - testScript = '' - $client1->start(); - $client1->waitForUnit("docker.service"); - $client1->succeed("tar cv --files-from /dev/null | docker import - scratch"); - $client1->succeed("docker tag scratch registry:8080/scratch"); - - $registry->start(); - $registry->waitForUnit("docker-registry.service"); - $client1->succeed("docker push registry:8080/scratch"); - - $client2->start(); - $client2->waitForUnit("docker.service"); - $client2->succeed("docker pull registry:8080/scratch"); - $client2->succeed("docker images | grep scratch"); - ''; -}) diff --git a/nixos/tests/docker.nix b/nixos/tests/docker.nix index 06e511d6e0bd..1b57a94a05d4 100644 --- a/nixos/tests/docker.nix +++ b/nixos/tests/docker.nix @@ -11,9 +11,6 @@ import ./make-test.nix ({ pkgs, ...} : { { config, pkgs, ... }: { virtualisation.docker.enable = true; - # FIXME: The default "devicemapper" storageDriver fails in NixOS VM - # tests. - virtualisation.docker.storageDriver = "overlay"; }; }; diff --git a/nixos/tests/firewall.nix b/nixos/tests/firewall.nix index 8f2cb27b60f1..1119a5312eb5 100644 --- a/nixos/tests/firewall.nix +++ b/nixos/tests/firewall.nix @@ -15,6 +15,16 @@ import ./make-test.nix ( { pkgs, ... } : { services.httpd.adminAddr = "foo@example.org"; }; + # Dummy configuration to check whether firewall.service will be honored + # during system activation. This only needs to be different to the + # original walled configuration so that there is a change in the service + # file. + walled2 = + { config, pkgs, nodes, ... }: + { networking.firewall.enable = true; + networking.firewall.rejectPackets = true; + }; + attacker = { config, pkgs, ... }: { services.httpd.enable = true; @@ -23,28 +33,33 @@ import ./make-test.nix ( { pkgs, ... } : { }; }; - testScript = - { nodes, ... }: - '' - startAll; + testScript = { nodes, ... }: let + newSystem = nodes.walled2.config.system.build.toplevel; + in '' + $walled->start; + $attacker->start; + + $walled->waitForUnit("firewall"); + $walled->waitForUnit("httpd"); + $attacker->waitForUnit("network.target"); - $walled->waitForUnit("firewall"); - $walled->waitForUnit("httpd"); - $attacker->waitForUnit("network.target"); + # Local connections should still work. + $walled->succeed("curl -v http://localhost/ >&2"); - # Local connections should still work. - $walled->succeed("curl -v http://localhost/ >&2"); + # Connections to the firewalled machine should fail, but ping should succeed. + $attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2"); + $attacker->succeed("ping -c 1 walled >&2"); - # Connections to the firewalled machine should fail, but ping should succeed. - $attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2"); - $attacker->succeed("ping -c 1 walled >&2"); + # Outgoing connections/pings should still work. + $walled->succeed("curl -v http://attacker/ >&2"); + $walled->succeed("ping -c 1 attacker >&2"); - # Outgoing connections/pings should still work. - $walled->succeed("curl -v http://attacker/ >&2"); - $walled->succeed("ping -c 1 attacker >&2"); + # If we stop the firewall, then connections should succeed. + $walled->stopJob("firewall"); + $attacker->succeed("curl -v http://walled/ >&2"); - # If we stop the firewall, then connections should succeed. - $walled->stopJob("firewall"); - $attacker->succeed("curl -v http://walled/ >&2"); - ''; + # Check whether activation of a new configuration reloads the firewall. + $walled->succeed("${newSystem}/bin/switch-to-configuration test 2>&1" . + " | grep -qF firewall.service"); + ''; }) diff --git a/nixos/tests/influxdb.nix b/nixos/tests/influxdb.nix index 0408d8983ade..aca2189716a4 100644 --- a/nixos/tests/influxdb.nix +++ b/nixos/tests/influxdb.nix @@ -22,18 +22,15 @@ import ./make-test.nix ({ pkgs, ...} : { # create database $one->succeed(q~ - curl -X POST 'http://localhost:8086/db?u=root&p=root' \ - -d '{"name": "test"}' + curl -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE test" ~); # write some points and run simple query $one->succeed(q~ - curl -X POST 'http://localhost:8086/db/test/series?u=root&p=root' \ - -d '[{"name":"foo","columns":["val"],"points":[[6666]]}]' + curl -XPOST 'http://localhost:8086/write?db=test' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000' ~); $one->succeed(q~ - curl -G 'http://localhost:8086/db/test/series?u=root&p=root' \ - --data-urlencode 'q=select * from foo limit 1' | grep 6666 + curl -GET 'http://localhost:8086/query' --data-urlencode "db=test" --data-urlencode "q=SELECT \"value\" FROM \"cpu_load_short\" WHERE \"region\"='us-west'" | grep "0\.64" ~); ''; }) diff --git a/nixos/tests/sddm-kde5.nix b/nixos/tests/kde5.nix index 0247d267aaa4..787dd2f8cbdd 100644 --- a/nixos/tests/sddm-kde5.nix +++ b/nixos/tests/kde5.nix @@ -24,29 +24,26 @@ import ./make-test.nix ({ pkgs, ...} : testScript = { nodes, ... }: let xdo = "${pkgs.xdotool}/bin/xdotool"; in - '' - sub krunner { - my ($win,) = @_; - $machine->execute("${xdo} key Alt+F2 sleep 1 type $win"); - $machine->execute("${xdo} search --sync --onlyvisible --class krunner sleep 5 key Return"); - } + '' + startAll; + + $machine->waitForFile("/home/alice/.Xauthority"); + $machine->succeed("xauth merge ~alice/.Xauthority"); $machine->waitUntilSucceeds("pgrep plasmashell"); - $machine->succeed("xauth merge ~alice/.Xauthority"); - $machine->waitForWindow(qr/Desktop.*/); + $machine->waitForWindow("^Desktop "); # Check that logging in has given the user ownership of devices. $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); - - krunner("dolphin"); - $machine->waitForWindow(qr/.*Dolphin/); - - krunner("konsole"); - $machine->waitForWindow(qr/.*Konsole/); - - krunner("systemsettings5"); - $machine->waitForWindow(qr/.*Settings/); - $machine->sleep(20); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 dolphin &'"); + $machine->waitForWindow(" Dolphin"); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 konsole &'"); + $machine->waitForWindow("Konsole"); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 systemsettings5 &'"); + $machine->waitForWindow("Settings"); $machine->execute("${xdo} key Alt+F1 sleep 10"); $machine->screenshot("screen"); diff --git a/nixos/tests/mumble.nix b/nixos/tests/mumble.nix index 35f440026997..7959b85a0cf0 100644 --- a/nixos/tests/mumble.nix +++ b/nixos/tests/mumble.nix @@ -36,18 +36,29 @@ in # cancel client audio configuration $client1->waitForWindow(qr/Audio Tuning Wizard/); $client2->waitForWindow(qr/Audio Tuning Wizard/); + $server->sleep(5); # wait because mumble is slow to register event handlers $client1->sendKeys("esc"); $client2->sendKeys("esc"); # cancel client cert configuration $client1->waitForWindow(qr/Certificate Management/); $client2->waitForWindow(qr/Certificate Management/); + $server->sleep(5); # wait because mumble is slow to register event handlers $client1->sendKeys("esc"); $client2->sendKeys("esc"); # accept server certificate $client1->waitForWindow(qr/^Mumble$/); $client2->waitForWindow(qr/^Mumble$/); + $server->sleep(5); # wait because mumble is slow to register event handlers + $client1->sendChars("y"); + $client2->sendChars("y"); + $server->sleep(5); # wait because mumble is slow to register event handlers + + # sometimes the wrong of the 2 windows is focused, we switch focus and try pressing "y" again + $client1->sendKeys("alt-tab"); + $client2->sendKeys("alt-tab"); + $server->sleep(5); # wait because mumble is slow to register event handlers $client1->sendChars("y"); $client2->sendChars("y"); diff --git a/nixos/tests/prometheus.nix b/nixos/tests/prometheus.nix new file mode 100644 index 000000000000..7605227100d2 --- /dev/null +++ b/nixos/tests/prometheus.nix @@ -0,0 +1,29 @@ +import ./make-test.nix { + name = "prometheus"; + + nodes = { + one = { config, pkgs, ... }: { + services.prometheus = { + enable = true; + globalConfig = { + labels = { foo = "bar"; }; + }; + scrapeConfigs = [{ + job_name = "prometheus"; + target_groups = [{ + targets = [ "127.0.0.1:9090" ]; + labels = { instance = "localhost"; }; + }]; + }]; + rules = [ ''testrule = count(up{job="prometheus"})'' ]; + }; + }; + }; + + testScript = '' + startAll; + $one->waitForUnit("prometheus.service"); + $one->waitForOpenPort(9090); + $one->succeed("curl -s http://127.0.0.1:9090/metrics"); + ''; +} diff --git a/nixos/tests/pump.io.nix b/nixos/tests/pump.io.nix index 89fa23c3336e..3864f676497e 100644 --- a/nixos/tests/pump.io.nix +++ b/nixos/tests/pump.io.nix @@ -81,7 +81,7 @@ in { ''; }; systemd.services.mongodb.unitConfig.Before = "pump.io.service"; - systemd.services.mongodb.unitConfig.RequiredBy = "pump.io.service"; + systemd.services."pump.io".unitConfig.Requires = "mongodb.service"; }; }; diff --git a/nixos/tests/tomcat.nix b/nixos/tests/tomcat.nix index 92680d82ba89..475c947e72d9 100644 --- a/nixos/tests/tomcat.nix +++ b/nixos/tests/tomcat.nix @@ -23,9 +23,8 @@ import ./make-test.nix ({ pkgs, ...} : { startAll; $server->waitForUnit("tomcat"); - $server->sleep(30); # Dirty, but it takes a while before Tomcat handles to requests properly $client->waitForUnit("network.target"); - $client->succeed("curl --fail http://server/examples/servlets/servlet/HelloWorldExample"); - $client->succeed("curl --fail http://server/examples/jsp/jsp2/simpletag/hello.jsp"); + $client->waitUntilSucceeds("curl --fail http://server/examples/servlets/servlet/HelloWorldExample"); + $client->waitUntilSucceeds("curl --fail http://server/examples/jsp/jsp2/simpletag/hello.jsp"); ''; }) diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index ab4d46ab7e15..66f16ed8bcc5 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -144,6 +144,7 @@ let "--uart1 0x3F8 4" "--uartmode1 client /run/virtualbox-log-${name}.sock" "--memory 768" + "--audio none" ] ++ (attrs.vmFlags or [])); controllerFlags = mkFlags [ @@ -273,9 +274,12 @@ let sub shutdownVM_${name} { $machine->succeed(ru "touch ${sharePath}/shutdown"); - $machine->waitUntilSucceeds( - "test ! -e ${sharePath}/shutdown ". - " -a ! -e ${sharePath}/boot-done" + $machine->execute( + 'set -e; i=0; '. + 'while test -e ${sharePath}/shutdown '. + ' -o -e ${sharePath}/boot-done; do '. + 'sleep 1; i=$(($i + 1)); [ $i -le 3600 ]; '. + 'done' ); waitForShutdown_${name}; } @@ -386,6 +390,7 @@ in mapAttrs mkVBoxTest { $machine->sendKeys("ctrl-q"); $machine->sleep(5); $machine->screenshot("gui_manager_stopped"); + destroyVM_simple; ''; simple-cli = '' @@ -403,6 +408,7 @@ in mapAttrs mkVBoxTest { }); shutdownVM_simple; + destroyVM_simple; ''; headless = '' @@ -411,6 +417,7 @@ in mapAttrs mkVBoxTest { waitForStartup_headless; waitForVMBoot_headless; shutdownVM_headless; + destroyVM_headless; ''; host-usb-permissions = '' |