diff options
Diffstat (limited to 'nixos')
27 files changed, 1005 insertions, 146 deletions
diff --git a/nixos/doc/manual/README b/nixos/doc/manual/README deleted file mode 100644 index 120c127d7af..00000000000 --- a/nixos/doc/manual/README +++ /dev/null @@ -1,3 +0,0 @@ -Moved to: ./contributing-to-this-manual.xml. Link: - -https://nixos.org/manual/nixos/unstable/#chap-contributing diff --git a/nixos/doc/manual/README.md b/nixos/doc/manual/README.md new file mode 100644 index 00000000000..bc649761df6 --- /dev/null +++ b/nixos/doc/manual/README.md @@ -0,0 +1,3 @@ +[Moved to ./contributing-to-this-manual.chapter.md](./contributing-to-this-manual.chapter.md). Link: + +https://nixos.org/manual/nixos/unstable/#chap-contributing diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index b9967ffb982..88d075a9a48 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -7,7 +7,7 @@ <itemizedlist spacing="compact"> <listitem> <para> - Support is planned until the end of April 2022, handing over to + Support is planned until the end of June 2022, handing over to 22.05. </para> </listitem> @@ -49,6 +49,13 @@ </listitem> <listitem> <para> + <link xlink:href="https://www.isc.org/kea/">Kea</link>, ISCs + 2nd generation DHCP and DDNS server suite. Available at + <link xlink:href="options.html#opt-services.kea">services.kea</link>. + </para> + </listitem> + <listitem> + <para> <link xlink:href="https://sr.ht">sourcehut</link>, a collection of tools useful for software development. Available as @@ -85,6 +92,13 @@ <link linkend="opt-snapraid.enable">snapraid</link>. </para> </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/hockeypuck/hockeypuck">Hockeypuck</link>, + a OpenPGP Key Server. Available as + <link linkend="opt-services.hockeypuck.enable">services.hockeypuck</link>. + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-21.11-incompatibilities"> @@ -503,6 +517,12 @@ changelog</link>. </para> </listitem> + <listitem> + <para> + The <literal>isabelle</literal> package has been upgraded from + 2020 to 2021 + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-21.11-notable-changes"> @@ -546,6 +566,22 @@ <literal>claws-mail-gtk2</literal> package. </para> </listitem> + <listitem> + <para> + The wordpress module provides a new interface which allows to + use different webservers with the new option + <link xlink:href="options.html#opt-services.wordpress.webserver"><literal>services.wordpress.webserver</literal></link>. + Currently <literal>httpd</literal> and + <literal>nginx</literal> are supported. The definitions of + wordpress sites should now be set in + <link xlink:href="options.html#opt-services.wordpress.sites"><literal>services.wordpress.sites</literal></link>. + </para> + <para> + Sites definitions that use the old interface are automatically + migrated in the new option. This backward compatibility will + be removed in 22.05. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 377dbf598d9..f7275480ff8 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -2,7 +2,7 @@ In addition to numerous new and upgraded packages, this release has the following highlights: -- Support is planned until the end of April 2022, handing over to 22.05. +- Support is planned until the end of June 2022, handing over to 22.05. ## Highlights {#sec-release-21.11-highlights} @@ -15,6 +15,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [geoipupdate](https://github.com/maxmind/geoipupdate), a GeoIP database updater from MaxMind. Available as [services.geoipupdate](options.html#opt-services.geoipupdate.enable). +- [Kea](https://www.isc.org/kea/), ISCs 2nd generation DHCP and DDNS server suite. Available at [services.kea](options.html#opt-services.kea). + - [sourcehut](https://sr.ht), a collection of tools useful for software development. Available as [services.sourcehut](options.html#opt-services.sourcehut.enable). - [ucarp](https://download.pureftpd.org/pub/ucarp/README), an userspace implementation of the Common Address Redundancy Protocol (CARP). Available as [networking.ucarp](options.html#opt-networking.ucarp.enable). @@ -26,6 +28,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [snapraid](https://www.snapraid.it/), a backup program for disk arrays. Available as [snapraid](#opt-snapraid.enable). +- [Hockeypuck](https://github.com/hockeypuck/hockeypuck), a OpenPGP Key Server. Available as [services.hockeypuck](#opt-services.hockeypuck.enable). + ## Backward Incompatibilities {#sec-release-21.11-incompatibilities} @@ -126,6 +130,8 @@ In addition to numerous new and upgraded packages, this release has the followin - `icingaweb2` was upgraded to a new release which requires a manual database upgrade, see [upstream changelog](https://github.com/Icinga/icingaweb2/releases/tag/v2.9.0). +- The `isabelle` package has been upgraded from 2020 to 2021 + ## Other Notable Changes {#sec-release-21.11-notable-changes} - The setting [`services.openssh.logLevel`](options.html#opt-services.openssh.logLevel) `"VERBOSE"` `"INFO"`. This brings NixOS in line with upstream and other Linux distributions, and reduces log spam on servers due to bruteforcing botnets. @@ -135,3 +141,7 @@ In addition to numerous new and upgraded packages, this release has the followin - Sway: The terminal emulator `rxvt-unicode` is no longer installed by default via `programs.sway.extraPackages`. The current default configuration uses `alacritty` (and soon `foot`) so this is only an issue when using a customized configuration and not installing `rxvt-unicode` explicitly. - The `claws-mail` package now references the new GTK+ 3 release branch, major version 4. To use the GTK+ 2 releases, one can install the `claws-mail-gtk2` package. + +- The wordpress module provides a new interface which allows to use different webservers with the new option [`services.wordpress.webserver`](options.html#opt-services.wordpress.webserver). Currently `httpd` and `nginx` are supported. The definitions of wordpress sites should now be set in [`services.wordpress.sites`](options.html#opt-services.wordpress.sites). + + Sites definitions that use the old interface are automatically migrated in the new option. This backward compatibility will be removed in 22.05. diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 2cbbbc522e1..858c7ee53db 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -229,7 +229,7 @@ in grafana = 196; skydns = 197; # ripple-rest = 198; # unused, removed 2017-08-12 - nix-serve = 199; + # nix-serve = 199; # unused, removed 2020-12-12 tvheadend = 200; uwsgi = 201; gitit = 202; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 3474c6e99d2..13463359a66 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -727,6 +727,7 @@ ./services/networking/iwd.nix ./services/networking/jicofo.nix ./services/networking/jitsi-videobridge.nix + ./services/networking/kea.nix ./services/networking/keepalived/default.nix ./services/networking/keybase.nix ./services/networking/kippo.nix @@ -885,6 +886,7 @@ ./services/security/fprot.nix ./services/security/haka.nix ./services/security/haveged.nix + ./services/security/hockeypuck.nix ./services/security/hologram-server.nix ./services/security/hologram-agent.nix ./services/security/munge.nix diff --git a/nixos/modules/services/cluster/k3s/default.nix b/nixos/modules/services/cluster/k3s/default.nix index d0fb8cc5098..e5c51441690 100644 --- a/nixos/modules/services/cluster/k3s/default.nix +++ b/nixos/modules/services/cluster/k3s/default.nix @@ -67,6 +67,12 @@ in default = false; description = "Only run the server. This option only makes sense for a server."; }; + + configPath = mkOption { + type = types.nullOr types.path; + default = null; + description = "File path containing the k3s YAML config. This is useful when the config is generated (for example on boot)."; + }; }; # implementation @@ -74,12 +80,12 @@ in config = mkIf cfg.enable { assertions = [ { - assertion = cfg.role == "agent" -> cfg.serverAddr != ""; - message = "serverAddr should be set if role is 'agent'"; + assertion = cfg.role == "agent" -> (cfg.configPath != null || cfg.serverAddr != ""); + message = "serverAddr or configPath (with 'server' key) should be set if role is 'agent'"; } { - assertion = cfg.role == "agent" -> cfg.token != "" || cfg.tokenFile != null; - message = "token or tokenFile should be set if role is 'agent'"; + assertion = cfg.role == "agent" -> cfg.configPath != null || cfg.tokenFile != null || cfg.token != ""; + message = "token or tokenFile or configPath (with 'token' or 'token-file' keys) should be set if role is 'agent'"; } ]; @@ -115,12 +121,10 @@ in "${cfg.package}/bin/k3s ${cfg.role}" ] ++ (optional cfg.docker "--docker") ++ (optional cfg.disableAgent "--disable-agent") - ++ (optional (cfg.role == "agent") "--server ${cfg.serverAddr} ${ - if cfg.tokenFile != null then - "--token-file ${cfg.tokenFile}" - else - "--token ${cfg.token}" - }") + ++ (optional (cfg.serverAddr != "") "--server ${cfg.serverAddr}") + ++ (optional (cfg.token != "") "--token ${cfg.token}") + ++ (optional (cfg.tokenFile != null) "--token-file ${cfg.tokenFile}") + ++ (optional (cfg.configPath != null) "--config ${cfg.configPath}") ++ [ cfg.extraFlags ] ); }; diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix index 2f0b573e872..70d85a97f3b 100644 --- a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix +++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix @@ -105,7 +105,7 @@ let pkgs.stdenv.mkDerivation { name = "hercules-ci-check-system-nix-src"; inherit (config.nix.package) src patches; - configurePhase = ":"; + dontConfigure = true; buildPhase = '' echo "Checking in-memory pathInfoCache expiry" if ! grep 'PathInfoCacheValue' src/libstore/store-api.hh >/dev/null; then diff --git a/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix b/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix index 556f6bbb419..9d083a615a2 100644 --- a/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix +++ b/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix @@ -54,8 +54,7 @@ stdenv.mkDerivation { ${addAllNetDev netDevices} ''; - installPhase = ":"; - + dontInstall = true; dontStrip = true; dontPatchELF = true; diff --git a/nixos/modules/services/misc/klipper.nix b/nixos/modules/services/misc/klipper.nix index 2f04c011a65..4930648ba8e 100644 --- a/nixos/modules/services/misc/klipper.nix +++ b/nixos/modules/services/misc/klipper.nix @@ -2,7 +2,6 @@ with lib; let cfg = config.services.klipper; - package = pkgs.klipper; format = pkgs.formats.ini { mkKeyValue = generators.mkKeyValueDefault {} ":"; }; in { @@ -11,12 +10,51 @@ in services.klipper = { enable = mkEnableOption "Klipper, the 3D printer firmware"; + package = mkOption { + type = types.package; + default = pkgs.klipper; + description = "The Klipper package."; + }; + + inputTTY = mkOption { + type = types.path; + default = "/run/klipper/tty"; + description = "Path of the virtual printer symlink to create."; + }; + + apiSocket = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/klipper/api"; + description = "Path of the API socket to create."; + }; + octoprintIntegration = mkOption { type = types.bool; default = false; description = "Allows Octoprint to control Klipper."; }; + user = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + User account under which Klipper runs. + + If null is specified (default), a temporary user will be created by systemd. + ''; + }; + + group = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Group account under which Klipper runs. + + If null is specified (default), a temporary user will be created by systemd. + ''; + }; + settings = mkOption { type = format.type; default = { }; @@ -30,26 +68,40 @@ in ##### implementation config = mkIf cfg.enable { - assertions = [{ - assertion = cfg.octoprintIntegration -> config.services.octoprint.enable; - message = "Option klipper.octoprintIntegration requires Octoprint to be enabled on this system. Please enable services.octoprint to use it."; - }]; + assertions = [ + { + assertion = cfg.octoprintIntegration -> config.services.octoprint.enable; + message = "Option klipper.octoprintIntegration requires Octoprint to be enabled on this system. Please enable services.octoprint to use it."; + } + { + assertion = cfg.user != null -> cfg.group != null; + message = "Option klipper.group is not set when a user is specified."; + } + ]; environment.etc."klipper.cfg".source = format.generate "klipper.cfg" cfg.settings; - systemd.services.klipper = { + services.klipper = mkIf cfg.octoprintIntegration { + user = config.services.octoprint.user; + group = config.services.octoprint.group; + }; + + systemd.services.klipper = let + klippyArgs = "--input-tty=${cfg.inputTTY}" + + optionalString (cfg.apiSocket != null) " --api-server=${cfg.apiSocket}"; + in { description = "Klipper 3D Printer Firmware"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { - ExecStart = "${package}/lib/klipper/klippy.py --input-tty=/run/klipper/tty /etc/klipper.cfg"; + ExecStart = "${cfg.package}/lib/klipper/klippy.py ${klippyArgs} /etc/klipper.cfg"; RuntimeDirectory = "klipper"; SupplementaryGroups = [ "dialout" ]; - WorkingDirectory = "${package}/lib"; - } // (if cfg.octoprintIntegration then { - Group = config.services.octoprint.group; - User = config.services.octoprint.user; + WorkingDirectory = "${cfg.package}/lib"; + } // (if cfg.user != null then { + Group = cfg.group; + User = cfg.user; } else { DynamicUser = true; User = "klipper"; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 46015c9ec1e..6bd075697fa 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -180,7 +180,7 @@ let serviceConfig.PrivateTmp = mkDefault true; serviceConfig.WorkingDirectory = mkDefault /tmp; serviceConfig.DynamicUser = mkDefault enableDynamicUser; - serviceConfig.User = conf.user; + serviceConfig.User = mkDefault conf.user; serviceConfig.Group = conf.group; } serviceOpts ]); }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix index b6cd89c3866..9677281f877 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/kea.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/kea.nix @@ -26,6 +26,7 @@ in { }; serviceOpts = { serviceConfig = { + User = "kea"; ExecStart = '' ${pkgs.prometheus-kea-exporter}/bin/kea-exporter \ --address ${cfg.listenAddress} \ diff --git a/nixos/modules/services/monitoring/telegraf.nix b/nixos/modules/services/monitoring/telegraf.nix index bc30ca3b77c..4046260c164 100644 --- a/nixos/modules/services/monitoring/telegraf.nix +++ b/nixos/modules/services/monitoring/telegraf.nix @@ -25,10 +25,9 @@ in { default = []; example = "/run/keys/telegraf.env"; description = '' - File to load as environment file. Environment variables - from this file will be interpolated into the config file - using envsubst with this syntax: - <literal>$ENVIRONMENT ''${VARIABLE}</literal> + File to load as environment file. Environment variables from this file + will be interpolated into the config file using envsubst with this + syntax: <literal>$ENVIRONMENT</literal> or <literal>''${VARIABLE}</literal>. This is useful to avoid putting secrets into the nix store. ''; }; @@ -73,6 +72,7 @@ in { ExecReload="${pkgs.coreutils}/bin/kill -HUP $MAINPID"; RuntimeDirectory = "telegraf"; User = "telegraf"; + Group = "telegraf"; Restart = "on-failure"; # for ping probes AmbientCapabilities = [ "CAP_NET_RAW" ]; @@ -81,7 +81,10 @@ in { users.users.telegraf = { uid = config.ids.uids.telegraf; + group = "telegraf"; description = "telegraf daemon user"; }; + + users.groups.telegraf = {}; }; } diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix index 33da4071638..480d5a184f2 100644 --- a/nixos/modules/services/networking/bind.nix +++ b/nixos/modules/services/networking/bind.nix @@ -61,7 +61,7 @@ let blackhole { badnetworks; }; forward first; forwarders { ${concatMapStrings (entry: " ${entry}; ") cfg.forwarders} }; - directory "/run/named"; + directory "${cfg.directory}"; pid-file "/run/named/named.pid"; ${cfg.extraOptions} }; @@ -166,6 +166,12 @@ in "; }; + directory = mkOption { + type = types.str; + default = "/run/named"; + description = "Working directory of BIND."; + }; + zones = mkOption { default = [ ]; type = with types; coercedTo (listOf attrs) bindZoneCoerce (attrsOf (types.submodule bindZoneOptions)); @@ -240,6 +246,9 @@ in ${pkgs.coreutils}/bin/mkdir -p /run/named chown ${bindUser} /run/named + + ${pkgs.coreutils}/bin/mkdir -p ${cfg.directory} + chown ${bindUser} ${cfg.directory} ''; serviceConfig = { diff --git a/nixos/modules/services/networking/kea.nix b/nixos/modules/services/networking/kea.nix new file mode 100644 index 00000000000..72773b83a49 --- /dev/null +++ b/nixos/modules/services/networking/kea.nix @@ -0,0 +1,361 @@ +{ config +, lib +, pkgs +, ... +}: + +with lib; + +let + cfg = config.services.kea; + + format = pkgs.formats.json {}; + + ctrlAgentConfig = format.generate "kea-ctrl-agent.conf" { + Control-agent = cfg.ctrl-agent.settings; + }; + dhcp4Config = format.generate "kea-dhcp4.conf" { + Dhcp4 = cfg.dhcp4.settings; + }; + dhcp6Config = format.generate "kea-dhcp6.conf" { + Dhcp6 = cfg.dhcp6.settings; + }; + dhcpDdnsConfig = format.generate "kea-dhcp-ddns.conf" { + DhcpDdns = cfg.dhcp-ddns.settings; + }; + + package = pkgs.kea; +in +{ + options.services.kea = with types; { + ctrl-agent = mkOption { + description = '' + Kea Control Agent configuration + ''; + default = {}; + type = submodule { + options = { + enable = mkEnableOption "Kea Control Agent"; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + List of additonal arguments to pass to the daemon. + ''; + }; + + settings = mkOption { + type = format.type; + default = null; + description = '' + Kea Control Agent configuration as an attribute set, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html"/>. + ''; + }; + }; + }; + }; + + dhcp4 = mkOption { + description = '' + DHCP4 Server configuration + ''; + default = {}; + type = submodule { + options = { + enable = mkEnableOption "Kea DHCP4 server"; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + List of additonal arguments to pass to the daemon. + ''; + }; + + settings = mkOption { + type = format.type; + default = null; + example = { + valid-lifetime = 4000; + renew-timer = 1000; + rebind-timer = 2000; + interfaces-config = { + interfaces = [ + "eth0" + ]; + }; + lease-database = { + type = "memfile"; + persist = true; + name = "/var/lib/kea/dhcp4.leases"; + }; + subnet4 = [ { + subnet = "192.0.2.0/24"; + pools = [ { + pool = "192.0.2.100 - 192.0.2.240"; + } ]; + } ]; + }; + description = '' + Kea DHCP4 configuration as an attribute set, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp4-srv.html"/>. + ''; + }; + }; + }; + }; + + dhcp6 = mkOption { + description = '' + DHCP6 Server configuration + ''; + default = {}; + type = submodule { + options = { + enable = mkEnableOption "Kea DHCP6 server"; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + List of additonal arguments to pass to the daemon. + ''; + }; + + settings = mkOption { + type = format.type; + default = null; + example = { + valid-lifetime = 4000; + renew-timer = 1000; + rebind-timer = 2000; + preferred-lifetime = 3000; + interfaces-config = { + interfaces = [ + "eth0" + ]; + }; + lease-database = { + type = "memfile"; + persist = true; + name = "/var/lib/kea/dhcp6.leases"; + }; + subnet6 = [ { + subnet = "2001:db8:1::/64"; + pools = [ { + pool = "2001:db8:1::1-2001:db8:1::ffff"; + } ]; + } ]; + }; + description = '' + Kea DHCP6 configuration as an attribute set, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp6-srv.html"/>. + ''; + }; + }; + }; + }; + + dhcp-ddns = mkOption { + description = '' + Kea DHCP-DDNS configuration + ''; + default = {}; + type = submodule { + options = { + enable = mkEnableOption "Kea DDNS server"; + + extraArgs = mkOption { + type = listOf str; + default = []; + description = '' + List of additonal arguments to pass to the daemon. + ''; + }; + + settings = mkOption { + type = format.type; + default = null; + example = { + ip-address = "127.0.0.1"; + port = 53001; + dns-server-timeout = 100; + ncr-protocol = "UDP"; + ncr-format = "JSON"; + tsig-keys = [ ]; + forward-ddns = { + ddns-domains = [ ]; + }; + reverse-ddns = { + ddns-domains = [ ]; + }; + }; + description = '' + Kea DHCP-DDNS configuration as an attribute set, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html"/>. + ''; + }; + }; + }; + }; + }; + + config = let + commonServiceConfig = { + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + DynamicUser = true; + User = "kea"; + ConfigurationDirectory = "kea"; + RuntimeDirectory = "kea"; + StateDirectory = "kea"; + UMask = "0077"; + }; + in mkIf (cfg.ctrl-agent.enable || cfg.dhcp4.enable || cfg.dhcp6.enable || cfg.dhcp-ddns.enable) (mkMerge [ + { + environment.systemPackages = [ package ]; + } + + (mkIf cfg.ctrl-agent.enable { + + environment.etc."kea/ctrl-agent.conf".source = ctrlAgentConfig; + + systemd.services.kea-ctrl-agent = { + description = "Kea Control Agent"; + documentation = [ + "man:kea-ctrl-agent(8)" + "https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html" + ]; + + after = [ + "network-online.target" + "time-sync.target" + ]; + wantedBy = [ + "kea-dhcp4-server.service" + "kea-dhcp6-server.service" + "kea-dhcp-ddns-server.service" + ]; + + environment = { + KEA_PIDFILE_DIR = "/run/kea"; + }; + + serviceConfig = { + ExecStart = "${package}/bin/kea-ctrl-agent -c /etc/kea/ctrl-agent.conf ${lib.escapeShellArgs cfg.dhcp4.extraArgs}"; + KillMode = "process"; + Restart = "on-failure"; + } // commonServiceConfig; + }; + }) + + (mkIf cfg.dhcp4.enable { + + environment.etc."kea/dhcp4-server.conf".source = dhcp4Config; + + systemd.services.kea-dhcp4-server = { + description = "Kea DHCP4 Server"; + documentation = [ + "man:kea-dhcp4(8)" + "https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp4-srv.html" + ]; + + after = [ + "network-online.target" + "time-sync.target" + ]; + wantedBy = [ + "multi-user.target" + ]; + + environment = { + KEA_PIDFILE_DIR = "/run/kea"; + }; + + serviceConfig = { + ExecStart = "${package}/bin/kea-dhcp4 -c /etc/kea/dhcp4-server.conf ${lib.escapeShellArgs cfg.dhcp4.extraArgs}"; + # Kea does not request capabilities by itself + AmbientCapabilities = [ + "CAP_NET_BIND_SERVICE" + "CAP_NET_RAW" + ]; + CapabilityBoundingSet = [ + "CAP_NET_BIND_SERVICE" + "CAP_NET_RAW" + ]; + } // commonServiceConfig; + }; + }) + + (mkIf cfg.dhcp6.enable { + + environment.etc."kea/dhcp6-server.conf".source = dhcp6Config; + + systemd.services.kea-dhcp6-server = { + description = "Kea DHCP6 Server"; + documentation = [ + "man:kea-dhcp6(8)" + "https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp6-srv.html" + ]; + + after = [ + "network-online.target" + "time-sync.target" + ]; + wantedBy = [ + "multi-user.target" + ]; + + environment = { + KEA_PIDFILE_DIR = "/run/kea"; + }; + + serviceConfig = { + ExecStart = "${package}/bin/kea-dhcp6 -c /etc/kea/dhcp6-server.conf ${lib.escapeShellArgs cfg.dhcp6.extraArgs}"; + # Kea does not request capabilities by itself + AmbientCapabilities = [ + "CAP_NET_BIND_SERVICE" + ]; + CapabilityBoundingSet = [ + "CAP_NET_BIND_SERVICE" + ]; + } // commonServiceConfig; + }; + }) + + (mkIf cfg.dhcp-ddns.enable { + + environment.etc."kea/dhcp-ddns.conf".source = dhcpDdnsConfig; + + systemd.services.kea-dhcp-ddns-server = { + description = "Kea DHCP-DDNS Server"; + documentation = [ + "man:kea-dhcp-ddns(8)" + "https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html" + ]; + + after = [ + "network-online.target" + "time-sync.target" + ]; + wantedBy = [ + "multi-user.target" + ]; + + environment = { + KEA_PIDFILE_DIR = "/run/kea"; + }; + + serviceConfig = { + ExecStart = "${package}/bin/kea-dhcp-ddns -c /etc/kea/dhcp-ddns.conf ${lib.escapeShellArgs cfg.dhcp-ddns.extraArgs}"; + AmbientCapabilites = [ + "CAP_NET_BIND_SERVICE" + ]; + CapabilityBoundingSet = [ + "CAP_NET_BIND_SERVICE" + ]; + } // commonServiceConfig; + }; + }) + + ]); + + meta.maintainers = with maintainers; [ hexa ]; +} diff --git a/nixos/modules/services/networking/nix-serve.nix b/nixos/modules/services/networking/nix-serve.nix index b17f35c769b..7fc145f2303 100644 --- a/nixos/modules/services/networking/nix-serve.nix +++ b/nixos/modules/services/networking/nix-serve.nix @@ -69,13 +69,9 @@ in ExecStart = "${pkgs.nix-serve}/bin/nix-serve " + "--listen ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}"; User = "nix-serve"; - Group = "nogroup"; + Group = "nix-serve"; + DynamicUser = true; }; }; - - users.users.nix-serve = { - description = "Nix-serve user"; - uid = config.ids.uids.nix-serve; - }; }; } diff --git a/nixos/modules/services/security/hockeypuck.nix b/nixos/modules/services/security/hockeypuck.nix new file mode 100644 index 00000000000..686634c8add --- /dev/null +++ b/nixos/modules/services/security/hockeypuck.nix @@ -0,0 +1,104 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.hockeypuck; + settingsFormat = pkgs.formats.toml { }; +in { + meta.maintainers = with lib.maintainers; [ etu ]; + + options.services.hockeypuck = { + enable = lib.mkEnableOption "Hockeypuck OpenPGP Key Server"; + + port = lib.mkOption { + default = 11371; + type = lib.types.port; + description = "HKP port to listen on."; + }; + + settings = lib.mkOption { + type = settingsFormat.type; + default = { }; + example = lib.literalExample '' + { + hockeypuck = { + loglevel = "INFO"; + logfile = "/var/log/hockeypuck/hockeypuck.log"; + indexTemplate = "''${pkgs.hockeypuck-web}/share/templates/index.html.tmpl"; + vindexTemplate = "''${pkgs.hockeypuck-web}/share/templates/index.html.tmpl"; + statsTemplate = "''${pkgs.hockeypuck-web}/share/templates/stats.html.tmpl"; + webroot = "''${pkgs.hockeypuck-web}/share/webroot"; + + hkp.bind = ":''${toString cfg.port}"; + + openpgp.db = { + driver = "postgres-jsonb"; + dsn = "database=hockeypuck host=/var/run/postgresql sslmode=disable"; + }; + }; + } + ''; + description = '' + Configuration file for hockeypuck, here you can override + certain settings (<literal>loglevel</literal> and + <literal>openpgp.db.dsn</literal>) by just setting those values. + + For other settings you need to use lib.mkForce to override them. + + This service doesn't provision or enable postgres on your + system, it rather assumes that you enable postgres and create + the database yourself. + + Example: + <literal> + services.postgresql = { + enable = true; + ensureDatabases = [ "hockeypuck" ]; + ensureUsers = [{ + name = "hockeypuck"; + ensurePermissions."DATABASE hockeypuck" = "ALL PRIVILEGES"; + }]; + }; + </literal> + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.hockeypuck.settings.hockeypuck = { + loglevel = lib.mkDefault "INFO"; + logfile = "/var/log/hockeypuck/hockeypuck.log"; + indexTemplate = "${pkgs.hockeypuck-web}/share/templates/index.html.tmpl"; + vindexTemplate = "${pkgs.hockeypuck-web}/share/templates/index.html.tmpl"; + statsTemplate = "${pkgs.hockeypuck-web}/share/templates/stats.html.tmpl"; + webroot = "${pkgs.hockeypuck-web}/share/webroot"; + + hkp.bind = ":${toString cfg.port}"; + + openpgp.db = { + driver = "postgres-jsonb"; + dsn = lib.mkDefault "database=hockeypuck host=/var/run/postgresql sslmode=disable"; + }; + }; + + users.users.hockeypuck = { + isSystemUser = true; + description = "Hockeypuck user"; + }; + + systemd.services.hockeypuck = { + description = "Hockeypuck OpenPGP Key Server"; + after = [ "network.target" "postgresql.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + WorkingDirectory = "/var/lib/hockeypuck"; + User = "hockeypuck"; + ExecStart = "${pkgs.hockeypuck}/bin/hockeypuck -config ${settingsFormat.generate "config.toml" cfg.settings}"; + Restart = "always"; + RestartSec = "5s"; + LogsDirectory = "hockeypuck"; + LogsDirectoryMode = "0755"; + StateDirectory = "hockeypuck"; + }; + }; + }; +} diff --git a/nixos/modules/services/ttys/getty.nix b/nixos/modules/services/ttys/getty.nix index 8345dfabeb7..7cf2ff87da2 100644 --- a/nixos/modules/services/ttys/getty.nix +++ b/nixos/modules/services/ttys/getty.nix @@ -6,7 +6,7 @@ let cfg = config.services.getty; baseArgs = [ - "--login-program" "${pkgs.shadow}/bin/login" + "--login-program" "${cfg.loginProgram}" ] ++ optionals (cfg.autologinUser != null) [ "--autologin" cfg.autologinUser ] ++ optionals (cfg.loginOptions != null) [ @@ -39,6 +39,14 @@ in ''; }; + loginProgram = mkOption { + type = types.path; + default = "${pkgs.shadow}/bin/login"; + description = '' + Path to the login binary executed by agetty. + ''; + }; + loginOptions = mkOption { type = types.nullOr types.str; default = null; diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix index 775ecb3acaf..6f1ef815bc4 100644 --- a/nixos/modules/services/web-apps/wordpress.nix +++ b/nixos/modules/services/web-apps/wordpress.nix @@ -3,13 +3,18 @@ let inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types; inherit (lib) any attrValues concatMapStringsSep flatten literalExample; - inherit (lib) mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString; + inherit (lib) filterAttrs mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString; - eachSite = config.services.wordpress; + cfg = migrateOldAttrs config.services.wordpress; + eachSite = cfg.sites; user = "wordpress"; - group = config.services.httpd.group; + webserver = config.services.${cfg.webserver}; stateDir = hostName: "/var/lib/wordpress/${hostName}"; + # Migrate config.services.wordpress.<hostName> to config.services.wordpress.sites.<hostName> + oldSites = filterAttrs (o: _: o != "sites" && o != "webserver"); + migrateOldAttrs = cfg: cfg // { sites = cfg.sites // oldSites cfg; }; + pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec { pname = "wordpress-${hostName}"; version = src.version; @@ -261,21 +266,48 @@ in # interface options = { services.wordpress = mkOption { - type = types.attrsOf (types.submodule siteOpts); + type = types.submodule { + # Used to support old interface + freeformType = types.attrsOf (types.submodule siteOpts); + + # New interface + options.sites = mkOption { + type = types.attrsOf (types.submodule siteOpts); + default = {}; + description = "Specification of one or more WordPress sites to serve"; + }; + + options.webserver = mkOption { + type = types.enum [ "httpd" "nginx" ]; + default = "httpd"; + description = '' + Whether to use apache2 or nginx for virtual host management. + + Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.<name></literal>. + See <xref linkend="opt-services.nginx.virtualHosts"/> for further information. + + Further apache2 configuration can be done by adapting <literal>services.httpd.virtualHosts.<name></literal>. + See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. + ''; + }; + }; default = {}; - description = "Specification of one or more WordPress sites to serve via Apache."; + description = "Wordpress configuration"; }; + }; # implementation - config = mkIf (eachSite != {}) { + config = mkIf (eachSite != {}) (mkMerge [{ assertions = mapAttrsToList (hostName: cfg: { assertion = cfg.database.createLocally -> cfg.database.user == user; - message = "services.wordpress.${hostName}.database.user must be ${user} if the database is to be automatically provisioned"; + message = ''services.wordpress.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned''; } ) eachSite; + warnings = mapAttrsToList (hostName: _: ''services.wordpress."${hostName}" is deprecated use services.wordpress.sites."${hostName}"'') (oldSites cfg); + services.mysql = mkIf (any (v: v.database.createLocally) (attrValues eachSite)) { enable = true; package = mkDefault pkgs.mariadb; @@ -289,14 +321,18 @@ in services.phpfpm.pools = mapAttrs' (hostName: cfg: ( nameValuePair "wordpress-${hostName}" { - inherit user group; + inherit user; + group = webserver.group; settings = { - "listen.owner" = config.services.httpd.user; - "listen.group" = config.services.httpd.group; + "listen.owner" = webserver.user; + "listen.group" = webserver.group; } // cfg.poolConfig; } )) eachSite; + } + + (mkIf (cfg.webserver == "httpd") { services.httpd = { enable = true; extraModules = [ "proxy_fcgi" ]; @@ -332,11 +368,13 @@ in ''; } ]) eachSite; }; + }) + { systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [ - "d '${stateDir hostName}' 0750 ${user} ${group} - -" - "d '${cfg.uploadsDir}' 0750 ${user} ${group} - -" - "Z '${cfg.uploadsDir}' 0750 ${user} ${group} - -" + "d '${stateDir hostName}' 0750 ${user} ${webserver.group} - -" + "d '${cfg.uploadsDir}' 0750 ${user} ${webserver.group} - -" + "Z '${cfg.uploadsDir}' 0750 ${user} ${webserver.group} - -" ]) eachSite); systemd.services = mkMerge [ @@ -350,7 +388,7 @@ in serviceConfig = { Type = "oneshot"; User = user; - Group = group; + Group = webserver.group; }; })) eachSite) @@ -360,9 +398,65 @@ in ]; users.users.${user} = { - group = group; + group = webserver.group; isSystemUser = true; }; + } - }; + (mkIf (cfg.webserver == "nginx") { + services.nginx = { + enable = true; + virtualHosts = mapAttrs (hostName: cfg: { + serverName = mkDefault hostName; + root = "${pkg hostName cfg}/share/wordpress"; + extraConfig = '' + index index.php; + ''; + locations = { + "/" = { + priority = 200; + extraConfig = '' + try_files $uri $uri/ /index.php$is_args$args; + ''; + }; + "~ \\.php$" = { + priority = 500; + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket}; + fastcgi_index index.php; + include "${config.services.nginx.package}/conf/fastcgi.conf"; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + # Mitigate https://httpoxy.org/ vulnerabilities + fastcgi_param HTTP_PROXY ""; + fastcgi_intercept_errors off; + fastcgi_buffer_size 16k; + fastcgi_buffers 4 16k; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + ''; + }; + "~ /\\." = { + priority = 800; + extraConfig = "deny all;"; + }; + "~* /(?:uploads|files)/.*\\.php$" = { + priority = 900; + extraConfig = "deny all;"; + }; + "~* \\.(js|css|png|jpg|jpeg|gif|ico)$" = { + priority = 1000; + extraConfig = '' + expires max; + log_not_found off; + ''; + }; + }; + }) eachSite; + }; + }) + + ]); } diff --git a/nixos/modules/virtualisation/cri-o.nix b/nixos/modules/virtualisation/cri-o.nix index 8d352e36ef9..c135081959a 100644 --- a/nixos/modules/virtualisation/cri-o.nix +++ b/nixos/modules/virtualisation/cri-o.nix @@ -6,6 +6,9 @@ let crioPackage = (pkgs.cri-o.override { inherit (cfg) extraPackages; }); + format = pkgs.formats.toml { }; + + cfgFile = format.generate "00-default.conf" cfg.settings; in { imports = [ @@ -13,7 +16,7 @@ in ]; meta = { - maintainers = lib.teams.podman.members; + maintainers = teams.podman.members; }; options.virtualisation.cri-o = { @@ -55,7 +58,7 @@ in extraPackages = mkOption { type = with types; listOf package; default = [ ]; - example = lib.literalExample '' + example = literalExample '' [ pkgs.gvisor ] @@ -65,7 +68,7 @@ in ''; }; - package = lib.mkOption { + package = mkOption { type = types.package; default = crioPackage; internal = true; @@ -80,6 +83,15 @@ in description = "Override the network_dir option."; internal = true; }; + + settings = mkOption { + type = format.type; + default = { }; + description = '' + Configuration for cri-o, see + <link xlink:href="https://github.com/cri-o/cri-o/blob/master/docs/crio.conf.5.md"/>. + ''; + }; }; config = mkIf cfg.enable { @@ -87,36 +99,38 @@ in environment.etc."crictl.yaml".source = utils.copyFile "${pkgs.cri-o-unwrapped.src}/crictl.yaml"; - environment.etc."crio/crio.conf.d/00-default.conf".text = '' - [crio] - storage_driver = "${cfg.storageDriver}" - - [crio.image] - ${optionalString (cfg.pauseImage != null) ''pause_image = "${cfg.pauseImage}"''} - ${optionalString (cfg.pauseCommand != null) ''pause_command = "${cfg.pauseCommand}"''} - - [crio.network] - plugin_dirs = ["${pkgs.cni-plugins}/bin/"] - ${optionalString (cfg.networkDir != null) ''network_dir = "${cfg.networkDir}"''} - - [crio.runtime] - cgroup_manager = "systemd" - log_level = "${cfg.logLevel}" - pinns_path = "${cfg.package}/bin/pinns" - hooks_dir = [ - ${lib.optionalString config.virtualisation.containers.ociSeccompBpfHook.enable - ''"${config.boot.kernelPackages.oci-seccomp-bpf-hook}",''} - ] - - ${optionalString (cfg.runtime != null) '' - default_runtime = "${cfg.runtime}" - [crio.runtime.runtimes] - [crio.runtime.runtimes.${cfg.runtime}] - ''} - ''; + virtualisation.cri-o.settings.crio = { + storage_driver = cfg.storageDriver; + + image = { + pause_image = mkIf (cfg.pauseImage != null) cfg.pauseImage; + pause_command = mkIf (cfg.pauseCommand != null) cfg.pauseCommand; + }; + + network = { + plugin_dirs = [ "${pkgs.cni-plugins}/bin" ]; + network_dir = mkIf (cfg.networkDir != null) cfg.networkDir; + }; + + runtime = { + cgroup_manager = "systemd"; + log_level = cfg.logLevel; + manage_ns_lifecycle = true; + pinns_path = "${cfg.package}/bin/pinns"; + hooks_dir = + optional (config.virtualisation.containers.ociSeccompBpfHook.enable) + config.boot.kernelPackages.oci-seccomp-bpf-hook; + + default_runtime = mkIf (cfg.runtime != null) cfg.runtime; + runtimes = mkIf (cfg.runtime != null) { + "${cfg.runtime}" = { }; + }; + }; + }; environment.etc."cni/net.d/10-crio-bridge.conf".source = utils.copyFile "${pkgs.cri-o-unwrapped.src}/contrib/cni/10-crio-bridge.conf"; environment.etc."cni/net.d/99-loopback.conf".source = utils.copyFile "${pkgs.cri-o-unwrapped.src}/contrib/cni/99-loopback.conf"; + environment.etc."crio/crio.conf.d/00-default.conf".source = cfgFile; # Enable common /etc/containers configuration virtualisation.containers.enable = true; @@ -139,6 +153,7 @@ in TimeoutStartSec = "0"; Restart = "on-abnormal"; }; + restartTriggers = [ cfgFile ]; }; }; } diff --git a/nixos/tests/agda.nix b/nixos/tests/agda.nix index f282788519c..ec61af2afe7 100644 --- a/nixos/tests/agda.nix +++ b/nixos/tests/agda.nix @@ -2,6 +2,7 @@ import ./make-test-python.nix ({ pkgs, ... }: let hello-world = pkgs.writeText "hello-world" '' + {-# OPTIONS --guardedness #-} open import IO open import Level @@ -35,10 +36,6 @@ in machine.succeed("touch TestEmpty.agda") machine.succeed("agda TestEmpty.agda") - # Minimal script that actually uses the standard library - machine.succeed('echo "import IO" > TestIO.agda') - machine.succeed("agda -l standard-library -i . TestIO.agda") - # Hello world machine.succeed( "cp ${hello-world} HelloWorld.agda" diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 76e5077f42d..746139c4816 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -174,6 +174,7 @@ in hitch = handleTest ./hitch {}; hledger-web = handleTest ./hledger-web.nix {}; hocker-fetchdocker = handleTest ./hocker-fetchdocker {}; + hockeypuck = handleTest ./hockeypuck.nix { }; home-assistant = handleTest ./home-assistant.nix {}; hostname = handleTest ./hostname.nix {}; hound = handleTest ./hound.nix {}; @@ -203,6 +204,7 @@ in k3s = handleTest ./k3s.nix {}; kafka = handleTest ./kafka.nix {}; kbd-setfont-decompress = handleTest ./kbd-setfont-decompress.nix {}; + kea = handleTest ./kea.nix {}; keepalived = handleTest ./keepalived.nix {}; keepassxc = handleTest ./keepassxc.nix {}; kerberos = handleTest ./kerberos/default.nix {}; @@ -295,6 +297,7 @@ in nginx-sandbox = handleTestOn ["x86_64-linux"] ./nginx-sandbox.nix {}; nginx-sso = handleTest ./nginx-sso.nix {}; nginx-variants = handleTest ./nginx-variants.nix {}; + nix-serve = handleTest ./nix-ssh-serve.nix {}; nix-ssh-serve = handleTest ./nix-ssh-serve.nix {}; nixos-generate-config = handleTest ./nixos-generate-config.nix {}; nomad = handleTest ./nomad.nix {}; diff --git a/nixos/tests/hockeypuck.nix b/nixos/tests/hockeypuck.nix new file mode 100644 index 00000000000..79313f314fd --- /dev/null +++ b/nixos/tests/hockeypuck.nix @@ -0,0 +1,63 @@ +import ./make-test-python.nix ({ lib, pkgs, ... }: +let + gpgKeyring = (pkgs.runCommandNoCC "gpg-keyring" { buildInputs = [ pkgs.gnupg ]; } '' + mkdir -p $out + export GNUPGHOME=$out + cat > foo <<EOF + %echo Generating a basic OpenPGP key + %no-protection + Key-Type: DSA + Key-Length: 1024 + Subkey-Type: ELG-E + Subkey-Length: 1024 + Name-Real: Foo Example + Name-Email: foo@example.org + Expire-Date: 0 + # Do a commit here, so that we can later print "done" + %commit + %echo done + EOF + gpg --batch --generate-key foo + rm $out/S.gpg-agent $out/S.gpg-agent.* + ''); +in { + name = "hockeypuck"; + meta.maintainers = with lib.maintainers; [ etu ]; + + machine = { ... }: { + # Used for test + environment.systemPackages = [ pkgs.gnupg ]; + + services.hockeypuck.enable = true; + + services.postgresql = { + enable = true; + ensureDatabases = [ "hockeypuck" ]; + ensureUsers = [{ + name = "hockeypuck"; + ensurePermissions."DATABASE hockeypuck" = "ALL PRIVILEGES"; + }]; + }; + }; + + testScript = '' + machine.wait_for_unit("hockeypuck.service") + machine.wait_for_open_port(11371) + + response = machine.succeed("curl -vvv -s http://127.0.0.1:11371/") + + assert "<title>OpenPGP Keyserver</title>" in response, "HTML title not found" + + # Copy the keyring + machine.succeed("cp -R ${gpgKeyring} /tmp/GNUPGHOME") + + # Extract our GPG key id + keyId = machine.succeed("GNUPGHOME=/tmp/GNUPGHOME gpg --list-keys | grep dsa1024 --after-context=1 | grep -v dsa1024").strip() + + # Send the key to our local keyserver + machine.succeed("GNUPGHOME=/tmp/GNUPGHOME gpg --keyserver hkp://127.0.0.1:11371 --send-keys " + keyId) + + # Recieve the key from our local keyserver to a separate directory + machine.succeed("GNUPGHOME=$(mktemp -d) gpg --keyserver hkp://127.0.0.1:11371 --recv-keys " + keyId) + ''; +}) diff --git a/nixos/tests/kea.nix b/nixos/tests/kea.nix new file mode 100644 index 00000000000..6b345893108 --- /dev/null +++ b/nixos/tests/kea.nix @@ -0,0 +1,73 @@ +import ./make-test-python.nix ({ pkgs, lib, ...}: { + meta.maintainers = with lib.maintainers; [ hexa ]; + + nodes = { + router = { config, pkgs, ... }: { + virtualisation.vlans = [ 1 ]; + + networking = { + useNetworkd = true; + useDHCP = false; + firewall.allowedUDPPorts = [ 67 ]; + }; + + systemd.network = { + networks = { + "01-eth1" = { + name = "eth1"; + networkConfig = { + Address = "10.0.0.1/30"; + }; + }; + }; + }; + + services.kea.dhcp4 = { + enable = true; + settings = { + valid-lifetime = 3600; + renew-timer = 900; + rebind-timer = 1800; + + lease-database = { + type = "memfile"; + persist = true; + name = "/var/lib/kea/dhcp4.leases"; + }; + + interfaces-config = { + dhcp-socket-type = "raw"; + interfaces = [ + "eth1" + ]; + }; + + subnet4 = [ { + subnet = "10.0.0.0/30"; + pools = [ { + pool = "10.0.0.2 - 10.0.0.2"; + } ]; + } ]; + }; + }; + }; + + client = { config, pkgs, ... }: { + virtualisation.vlans = [ 1 ]; + systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug"; + networking = { + useNetworkd = true; + useDHCP = false; + firewall.enable = false; + interfaces.eth1.useDHCP = true; + }; + }; + }; + testScript = { ... }: '' + start_all() + router.wait_for_unit("kea-dhcp4-server.service") + client.wait_for_unit("systemd-networkd-wait-online.service") + client.wait_until_succeeds("ping -c 5 10.0.0.1") + router.wait_until_succeeds("ping -c 5 10.0.0.2") + ''; +}) diff --git a/nixos/tests/nix-serve.nix b/nixos/tests/nix-serve.nix new file mode 100644 index 00000000000..ab82f4be43e --- /dev/null +++ b/nixos/tests/nix-serve.nix @@ -0,0 +1,22 @@ +import ./make-test-python.nix ({ pkgs, ... }: +{ + name = "nix-serve"; + machine = { pkgs, ... }: { + services.nix-serve.enable = true; + environment.systemPackages = [ + pkgs.hello + ]; + }; + testScript = let + pkgHash = builtins.head ( + builtins.match "${builtins.storeDir}/([^-]+).+" (toString pkgs.hello) + ); + in '' + start_all() + machine.wait_for_unit("nix-serve.service") + machine.wait_for_open_port(5000) + machine.succeed( + "curl --fail -g http://0.0.0.0:5000/nar/${pkgHash}.nar -o /tmp/hello.nar" + ) + ''; +}) diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index a33aca29fd2..e8bc6339ecf 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -326,49 +326,36 @@ let ''; }; - kea = { + kea = let + controlSocketPath = "/run/kea/dhcp6.sock"; + in + { exporterConfig = { enable = true; controlSocketPaths = [ - "/run/kea/kea-dhcp6.sock" + controlSocketPath ]; }; metricProvider = { - users.users.kea = { - isSystemUser = true; - }; - users.groups.kea = {}; + systemd.services.prometheus-kea-exporter.after = [ "kea-dhcp6-server.service" ]; - systemd.services.prometheus-kea-exporter.after = [ "kea-dhcp6.service" ]; - - systemd.services.kea-dhcp6 = let - configFile = pkgs.writeText "kea-dhcp6.conf" (builtins.toJSON { - Dhcp6 = { - "control-socket" = { - "socket-type" = "unix"; - "socket-name" = "/run/kea/kea-dhcp6.sock"; + services.kea = { + enable = true; + dhcp6 = { + enable = true; + settings = { + control-socket = { + socket-type = "unix"; + socket-name = controlSocketPath; }; }; - }); - in - { - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - DynamicUser = false; - User = "kea"; - Group = "kea"; - ExecStart = "${pkgs.kea}/bin/kea-dhcp6 -c ${configFile}"; - StateDirectory = "kea"; - RuntimeDirectory = "kea"; - UMask = "0007"; }; }; }; + exporterTest = '' - wait_for_unit("kea-dhcp6.service") - wait_for_file("/run/kea/kea-dhcp6.sock") + wait_for_unit("kea-dhcp6-server.service") + wait_for_file("${controlSocketPath}") wait_for_unit("prometheus-kea-exporter.service") wait_for_open_port(9547) succeed( diff --git a/nixos/tests/wordpress.nix b/nixos/tests/wordpress.nix index a5c10c2de74..45c58b5b65c 100644 --- a/nixos/tests/wordpress.nix +++ b/nixos/tests/wordpress.nix @@ -10,48 +10,68 @@ import ./make-test-python.nix ({ pkgs, ... }: ]; }; - machine = - { ... }: - { services.httpd.adminAddr = "webmaster@site.local"; + nodes = { + wp_httpd = { ... }: { + services.httpd.adminAddr = "webmaster@site.local"; services.httpd.logPerVirtualHost = true; - services.wordpress."site1.local" = { - database.tablePrefix = "site1_"; + services.wordpress = { + # Test support for old interface + "site1.local" = { + database.tablePrefix = "site1_"; + }; + sites = { + "site2.local" = { + database.tablePrefix = "site2_"; + }; + }; }; - services.wordpress."site2.local" = { - database.tablePrefix = "site2_"; + networking.firewall.allowedTCPPorts = [ 80 ]; + networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ]; + }; + + wp_nginx = { ... }: { + services.wordpress.webserver = "nginx"; + services.wordpress.sites = { + "site1.local" = { + database.tablePrefix = "site1_"; + }; + "site2.local" = { + database.tablePrefix = "site2_"; + }; }; + networking.firewall.allowedTCPPorts = [ 80 ]; networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ]; }; + }; testScript = '' import re start_all() - machine.wait_for_unit("httpd") - - machine.wait_for_unit("phpfpm-wordpress-site1.local") - machine.wait_for_unit("phpfpm-wordpress-site2.local") + wp_httpd.wait_for_unit("httpd") + wp_nginx.wait_for_unit("nginx") site_names = ["site1.local", "site2.local"] - with subtest("website returns welcome screen"): + for machine in (wp_httpd, wp_nginx): for site_name in site_names: - assert "Welcome to the famous" in machine.succeed(f"curl -fL {site_name}") + machine.wait_for_unit(f"phpfpm-wordpress-{site_name}") - with subtest("wordpress-init went through"): - for site_name in site_names: - info = machine.get_unit_info(f"wordpress-init-{site_name}") - assert info["Result"] == "success" + with subtest("website returns welcome screen"): + assert "Welcome to the famous" in machine.succeed(f"curl -L {site_name}") - with subtest("secret keys are set"): - pattern = re.compile(r"^define.*NONCE_SALT.{64,};$", re.MULTILINE) - for site_name in site_names: - assert pattern.search( - machine.succeed(f"cat /var/lib/wordpress/{site_name}/secret-keys.php") - ) + with subtest("wordpress-init went through"): + info = machine.get_unit_info(f"wordpress-init-{site_name}") + assert info["Result"] == "success" + + with subtest("secret keys are set"): + pattern = re.compile(r"^define.*NONCE_SALT.{64,};$", re.MULTILINE) + assert pattern.search( + machine.succeed(f"cat /var/lib/wordpress/{site_name}/secret-keys.php") + ) ''; }) |