diff options
Diffstat (limited to 'nixos')
64 files changed, 968 insertions, 194 deletions
diff --git a/nixos/doc/manual/from_md/installation/installing-from-other-distro.section.xml b/nixos/doc/manual/from_md/installation/installing-from-other-distro.section.xml index 525531a4781..024a24379dd 100644 --- a/nixos/doc/manual/from_md/installation/installing-from-other-distro.section.xml +++ b/nixos/doc/manual/from_md/installation/installing-from-other-distro.section.xml @@ -248,7 +248,7 @@ $ nix-env -p /nix/var/nix/profiles/system -f '<nixpkgs/nixos>' -I nixos-co (since your Nix install was probably single user): </para> <programlisting> -$ sudo chown -R 0.0 /nix +$ sudo chown -R 0:0 /nix </programlisting> </listitem> <listitem> diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 6da24e3a8a8..ab0edcebc67 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -455,6 +455,12 @@ <link xlink:href="options.html#opt-services.nifi.enable">services.nifi</link>. </para> </listitem> + <listitem> + <para> + <link xlink:href="https://kanidm.github.io/kanidm/stable/">kanidm</link>, + an identity management server written in Rust. + </para> + </listitem> </itemizedlist> </section> <section xml:id="sec-release-22.05-incompatibilities"> @@ -2465,6 +2471,21 @@ hosts. </para> </listitem> + <listitem> + <para> + The option + <link xlink:href="options.html#opt-networking.useDHCP">networking.useDHCP</link> + isn’t deprecated anymore. When using + <link xlink:href="options.html#opt-networking.useNetworkd"><literal>systemd-networkd</literal></link>, + a generic <literal>.network</literal>-unit is added which + enables DHCP for each interface matching + <literal>en*</literal>, <literal>eth*</literal> or + <literal>wl*</literal> with priority 99 (which means that it + doesn’t have any effect if such an interface is matched by a + <literal>.network-</literal>unit with a lower priority). In + case of scripted networking, no behavior was changed. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/doc/manual/installation/installing-from-other-distro.section.md b/nixos/doc/manual/installation/installing-from-other-distro.section.md index d9060eb89c3..fa8806f791d 100644 --- a/nixos/doc/manual/installation/installing-from-other-distro.section.md +++ b/nixos/doc/manual/installation/installing-from-other-distro.section.md @@ -177,7 +177,7 @@ The first steps to all these are the same: was probably single user): ```ShellSession - $ sudo chown -R 0.0 /nix + $ sudo chown -R 0:0 /nix ``` 1. Set up the `/etc/NIXOS` and `/etc/NIXOS_LUSTRATE` files: diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 90d22643701..af65ae46131 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -135,6 +135,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [nifi](https://nifi.apache.org), an easy to use, powerful, and reliable system to process and distribute data. Available as [services.nifi](options.html#opt-services.nifi.enable). +- [kanidm](https://kanidm.github.io/kanidm/stable/), an identity management server written in Rust. + <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> ## Backward Incompatibilities {#sec-release-22.05-incompatibilities} @@ -875,4 +877,11 @@ In addition to numerous new and upgraded packages, this release has the followin `true` starting with NixOS 22.11. Enable it explicitly if you need to control Snapserver remotely or connect streamig clients from other hosts. +- The option [networking.useDHCP](options.html#opt-networking.useDHCP) isn't deprecated anymore. + When using [`systemd-networkd`](options.html#opt-networking.useNetworkd), a generic + `.network`-unit is added which enables DHCP for each interface matching `en*`, `eth*` + or `wl*` with priority 99 (which means that it doesn't have any effect if such an interface is matched + by a `.network-`unit with a lower priority). In case of scripted networking, no behavior + was changed. + <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> diff --git a/nixos/modules/hardware/keyboard/uhk.nix b/nixos/modules/hardware/keyboard/uhk.nix new file mode 100644 index 00000000000..bf2d739c3a9 --- /dev/null +++ b/nixos/modules/hardware/keyboard/uhk.nix @@ -0,0 +1,21 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.hardware.keyboard.uhk; +in +{ + options.hardware.keyboard.uhk = { + enable = mkEnableOption '' + non-root access to the firmware of UHK keyboards. + You need it when you want to flash a new firmware on the keyboard. + Access to the keyboard is granted to users in the "input" group. + You may want to install the uhk-agent package. + ''; + + }; + + config = mkIf cfg.enable { + services.udev.packages = [ pkgs.uhk-udev-rules ]; + }; +} diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix index 618057618d0..3f92b779d60 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix @@ -46,5 +46,5 @@ with lib; done ''; - system.stateVersion = mkDefault "18.03"; + system.stateVersion = lib.mkDefault lib.trivial.release; } diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index fb5d3ba4732..b74ec838df4 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -581,17 +581,19 @@ ${\join "", (map { " $_\n" } (uniq @attrs))}} EOF sub generateNetworkingDhcpConfig { + # FIXME disable networking.useDHCP by default when switching to networkd. my $config = <<EOF; - # The global useDHCP flag is deprecated, therefore explicitly set to false here. - # Per-interface useDHCP will be mandatory in the future, so this generated config - # replicates the default behaviour. - networking.useDHCP = lib.mkDefault false; + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. + networking.useDHCP = lib.mkDefault true; EOF foreach my $path (glob "/sys/class/net/*") { my $dev = basename($path); if ($dev ne "lo") { - $config .= " networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n"; + $config .= " # networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n"; } } diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index bf5ec0f9690..04be272742c 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -34,7 +34,7 @@ let name = "nixos-generate-config"; src = ./nixos-generate-config.pl; perl = "${pkgs.perl.withPackages (p: [ p.FileSlurp ])}/bin/perl"; - detectvirt = "${pkgs.systemd}/bin/systemd-detect-virt"; + detectvirt = "${config.systemd.package}/bin/systemd-detect-virt"; btrfs = "${pkgs.btrfs-progs}/bin/btrfs"; inherit (config.system.nixos-generate-config) configuration desktopConfiguration; xserverEnabled = config.services.xserver.enable; @@ -177,6 +177,10 @@ in # users.users.jane = { # isNormalUser = true; # extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + # packages = with pkgs; [ + # firefox + # thunderbird + # ]; # }; # List packages installed in system profile. To search, run: @@ -184,7 +188,6 @@ in # environment.systemPackages = with pkgs; [ # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. # wget - # firefox # ]; # Some programs need SUID wrappers, can be configured further or are diff --git a/nixos/modules/misc/mandoc.nix b/nixos/modules/misc/mandoc.nix index 3da60f2f8e6..838f2087656 100644 --- a/nixos/modules/misc/mandoc.nix +++ b/nixos/modules/misc/mandoc.nix @@ -53,7 +53,9 @@ in { # see: https://inbox.vuxu.org/mandoc-tech/20210906171231.GF83680@athene.usta.de/T/#e85f773c1781e3fef85562b2794f9cad7b2909a3c extraSetup = lib.mkIf config.documentation.man.generateCaches '' ${makewhatis} -T utf8 ${ - lib.concatMapStringsSep " " (path: "\"$out/${path}\"") cfg.manPath + lib.concatMapStringsSep " " (path: + "$out/" + lib.escapeShellArg path + ) cfg.manPath } ''; }; diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix index 931201ade29..010acdb72f6 100644 --- a/nixos/modules/misc/version.nix +++ b/nixos/modules/misc/version.nix @@ -146,6 +146,15 @@ in "/etc/os-release".source = initrdRelease; "/etc/initrd-release".source = initrdRelease; }; + + # We have to use `warnings` because when warning in the default of the option + # the warning would also be shown when building the manual since the manual + # has to evaluate the default. + # + # TODO Remove this and drop the default of the option so people are forced to set it. + # Doing this also means fixing the comment in nixos/modules/testing/test-instrumentation.nix + warnings = lib.optional (options.system.stateVersion.highestPrio == (lib.mkOptionDefault { }).priority) + "system.stateVersion is not set, defaulting to ${config.system.stateVersion}. Read why this matters on https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion."; }; # uses version info nixpkgs, which requires a full nixpkgs path diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9d9f2e9057c..b3efa5d5e6f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -57,6 +57,7 @@ ./hardware/sensor/hddtemp.nix ./hardware/sensor/iio.nix ./hardware/keyboard/teck.nix + ./hardware/keyboard/uhk.nix ./hardware/keyboard/zsa.nix ./hardware/ksm.nix ./hardware/ledger.nix @@ -196,7 +197,6 @@ ./programs/partition-manager.nix ./programs/plotinus.nix ./programs/proxychains.nix - ./programs/phosh.nix ./programs/qt5ct.nix ./programs/screen.nix ./programs/sedutil.nix @@ -975,6 +975,7 @@ ./services/security/hockeypuck.nix ./services/security/hologram-server.nix ./services/security/hologram-agent.nix + ./services/security/kanidm.nix ./services/security/munge.nix ./services/security/nginx-sso.nix ./services/security/oauth2_proxy.nix diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index b1fcb0b461f..23d1344a57a 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -626,7 +626,7 @@ let session optional ${pkgs.otpw}/lib/security/pam_otpw.so '' + optionalString cfg.startSession '' - session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${config.systemd.package}/lib/security/pam_systemd.so '' + optionalString cfg.forwardXAuth '' session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99 @@ -1242,7 +1242,7 @@ in mr ${pkgs.gnome3.gnome-keyring}/lib/security/pam_gnome_keyring.so, '' + optionalString (isEnabled (cfg: cfg.startSession)) '' - mr ${pkgs.systemd}/lib/security/pam_systemd.so, + mr ${config.systemd.package}/lib/security/pam_systemd.so, '' + optionalString (isEnabled (cfg: cfg.enableAppArmor) && config.security.apparmor.enable) '' diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index e63f19010de..169ef744262 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -98,7 +98,7 @@ let # Prevent races chmod 0000 "$wrapperDir/${program}" - chown ${owner}.${group} "$wrapperDir/${program}" + chown ${owner}:${group} "$wrapperDir/${program}" # Set desired capabilities on the file plus cap_setpcap so # the wrapper program can elevate the capabilities set on @@ -126,7 +126,7 @@ let # Prevent races chmod 0000 "$wrapperDir/${program}" - chown ${owner}.${group} "$wrapperDir/${program}" + chown ${owner}:${group} "$wrapperDir/${program}" chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" "$wrapperDir/${program}" ''; diff --git a/nixos/modules/services/backup/borgmatic.nix b/nixos/modules/services/backup/borgmatic.nix index 5e5c0bbeccc..9414d78aa75 100644 --- a/nixos/modules/services/backup/borgmatic.nix +++ b/nixos/modules/services/backup/borgmatic.nix @@ -4,7 +4,8 @@ with lib; let cfg = config.services.borgmatic; - cfgfile = pkgs.writeText "config.yaml" (builtins.toJSON cfg.settings); + settingsFormat = pkgs.formats.yaml { }; + cfgfile = settingsFormat.generate "config.yaml" cfg.settings; in { options.services.borgmatic = { enable = mkEnableOption "borgmatic"; @@ -14,7 +15,7 @@ in { See https://torsion.org/borgmatic/docs/reference/configuration/ ''; type = types.submodule { - freeformType = with lib.types; attrsOf anything; + freeformType = settingsFormat.type; options.location = { source_directories = mkOption { type = types.listOf types.str; diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix index cc5de97d6d1..90adab7fbf2 100644 --- a/nixos/modules/services/continuous-integration/hydra/default.nix +++ b/nixos/modules/services/continuous-integration/hydra/default.nix @@ -300,17 +300,17 @@ in }; preStart = '' mkdir -p ${baseDir} - chown hydra.hydra ${baseDir} + chown hydra:hydra ${baseDir} chmod 0750 ${baseDir} ln -sf ${hydraConf} ${baseDir}/hydra.conf mkdir -m 0700 -p ${baseDir}/www - chown hydra-www.hydra ${baseDir}/www + chown hydra-www:hydra ${baseDir}/www mkdir -m 0700 -p ${baseDir}/queue-runner mkdir -m 0750 -p ${baseDir}/build-logs - chown hydra-queue-runner.hydra ${baseDir}/queue-runner ${baseDir}/build-logs + chown hydra-queue-runner:hydra ${baseDir}/queue-runner ${baseDir}/build-logs ${optionalString haveLocalDB '' if ! [ -e ${baseDir}/.db-created ]; then @@ -338,7 +338,7 @@ in rmdir /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots fi - chown hydra.hydra ${cfg.gcRootsDir} + chown hydra:hydra ${cfg.gcRootsDir} chmod 2775 ${cfg.gcRootsDir} ''; serviceConfig.ExecStart = "${hydra-package}/bin/hydra-init"; diff --git a/nixos/modules/services/desktops/pipewire/daemon/pipewire-pulse.conf.json b/nixos/modules/services/desktops/pipewire/daemon/pipewire-pulse.conf.json index b19fb33ec17..114afbfb0ea 100644 --- a/nixos/modules/services/desktops/pipewire/daemon/pipewire-pulse.conf.json +++ b/nixos/modules/services/desktops/pipewire/daemon/pipewire-pulse.conf.json @@ -62,6 +62,9 @@ "application.process.binary": "teams" }, { + "application.process.binary": "teams-insiders" + }, + { "application.process.binary": "skypeforlinux" } ], diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix index ff73d7a46ed..bb6898a08c5 100644 --- a/nixos/modules/services/games/factorio.nix +++ b/nixos/modules/services/games/factorio.nix @@ -87,6 +87,18 @@ in a new map with default settings will be generated before starting the service. ''; }; + loadLatestSave = mkOption { + type = types.bool; + default = false; + description = '' + Load the latest savegame on startup. This overrides saveName, in that the latest + save will always be used even if a saved game of the given name exists. It still + controls the 'canonical' name of the savegame. + + Set this to true to have the server automatically reload a recent autosave after + a crash or desync. + ''; + }; # TODO Add more individual settings as nixos-options? # TODO XXX The server tries to copy a newly created config file over the old one # on shutdown, but fails, because it's in the nix store. When is this needed? @@ -250,8 +262,9 @@ in "--config=${cfg.configFile}" "--port=${toString cfg.port}" "--bind=${cfg.bind}" - "--start-server=${mkSavePath cfg.saveName}" + (optionalString (!cfg.loadLatestSave) "--start-server=${mkSavePath cfg.saveName}") "--server-settings=${serverSettingsFile}" + (optionalString cfg.loadLatestSave "--start-server-load-latest") (optionalString (cfg.mods != []) "--mod-directory=${modDir}") (optionalString (cfg.admins != []) "--server-adminlist=${serverAdminsFile}") ]; diff --git a/nixos/modules/services/hardware/illum.nix b/nixos/modules/services/hardware/illum.nix index ff73c99a653..7f7a8500023 100644 --- a/nixos/modules/services/hardware/illum.nix +++ b/nixos/modules/services/hardware/illum.nix @@ -28,6 +28,7 @@ in { description = "Backlight Adjustment Service"; wantedBy = [ "multi-user.target" ]; serviceConfig.ExecStart = "${pkgs.illum}/bin/illum-d"; + serviceConfig.Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/hardware/usbrelayd.nix b/nixos/modules/services/hardware/usbrelayd.nix index c0322e89e6b..2cee4e1ff7e 100644 --- a/nixos/modules/services/hardware/usbrelayd.nix +++ b/nixos/modules/services/hardware/usbrelayd.nix @@ -26,8 +26,7 @@ in config = mkIf cfg.enable { - # TODO: Rename to .conf in upcomming release - environment.etc."usbrelayd.ini".text = '' + environment.etc."usbrelayd.conf".text = '' [MQTT] BROKER = ${cfg.broker} CLIENTNAME = ${cfg.clientName} @@ -41,4 +40,8 @@ in }; users.groups.usbrelay = { }; }; + + meta = { + maintainers = with lib.maintainers; [ wentasah ]; + }; } diff --git a/nixos/modules/services/home-automation/home-assistant.nix b/nixos/modules/services/home-automation/home-assistant.nix index 6022227f6ea..e255e5d2218 100644 --- a/nixos/modules/services/home-automation/home-assistant.nix +++ b/nixos/modules/services/home-automation/home-assistant.nix @@ -360,7 +360,14 @@ in { }; config = mkIf cfg.enable { - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; + assertions = [ + { + assertion = cfg.openFirewall -> !isNull cfg.config; + message = "openFirewall can only be used with a declarative config"; + } + ]; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.config.http.server_port ]; systemd.services.home-assistant = { description = "Home Assistant"; diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index a08203dffe7..5d00feabe1c 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -109,7 +109,7 @@ in ''' # Read from journal pipe { - command => "''${pkgs.systemd}/bin/journalctl -f -o json" + command => "''${config.systemd.package}/bin/journalctl -f -o json" type => "syslog" codec => json {} } ''' diff --git a/nixos/modules/services/mail/spamassassin.nix b/nixos/modules/services/mail/spamassassin.nix index ac878222b26..3b10d8d2909 100644 --- a/nixos/modules/services/mail/spamassassin.nix +++ b/nixos/modules/services/mail/spamassassin.nix @@ -135,7 +135,7 @@ in User = "spamd"; Group = "spamd"; StateDirectory = "spamassassin"; - ExecStartPost = "+${pkgs.systemd}/bin/systemctl -q --no-block try-reload-or-restart spamd.service"; + ExecStartPost = "+${config.systemd.package}/bin/systemctl -q --no-block try-reload-or-restart spamd.service"; }; script = '' diff --git a/nixos/modules/services/matrix/matrix-synapse.nix b/nixos/modules/services/matrix/matrix-synapse.nix index a498aff7a55..87a977f8e1e 100644 --- a/nixos/modules/services/matrix/matrix-synapse.nix +++ b/nixos/modules/services/matrix/matrix-synapse.nix @@ -296,6 +296,7 @@ in { default = if lib.versionAtLeast config.system.stateVersion "22.05" then "${cfg.dataDir}/media_store" else "${cfg.dataDir}/media"; + defaultText = "${cfg.dataDir}/media_store for when system.stateVersion is at least 22.05, ${cfg.dataDir}/media when lower than 22.05"; description = '' Directory where uploaded images and attachments are stored. ''; diff --git a/nixos/modules/services/misc/heisenbridge.nix b/nixos/modules/services/misc/heisenbridge.nix index 7ce8a23d9af..deefb061d8b 100644 --- a/nixos/modules/services/misc/heisenbridge.nix +++ b/nixos/modules/services/misc/heisenbridge.nix @@ -204,7 +204,7 @@ in NoNewPrivileges = true; LockPersonality = true; RestrictRealtime = true; - SystemCallFilter = ["@system-service" "~@priviledged" "@chown"]; + SystemCallFilter = ["@system-service" "~@privileged" "@chown"]; SystemCallArchitectures = "native"; RestrictAddressFamilies = "AF_INET AF_INET6"; }; diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix index 52525e8935b..ceb2db1faef 100644 --- a/nixos/modules/services/monitoring/prometheus/default.nix +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -3,6 +3,7 @@ with lib; let + json = pkgs.formats.json { }; cfg = config.services.prometheus; workingDir = "/var/lib/" + cfg.stateDir; @@ -34,13 +35,7 @@ let promtool ${what} $out '' else file; - # Pretty-print JSON to a file - writePrettyJSON = name: x: - pkgs.runCommandLocal name { } '' - echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out - ''; - - generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig; + generatedPrometheusYml = json.generate "prometheus.yml" promConfig; # This becomes the main config file for Prometheus promConfig = { diff --git a/nixos/modules/services/networking/gateone.nix b/nixos/modules/services/networking/gateone.nix index 3e3a3c1aa94..e68f8a47d5c 100644 --- a/nixos/modules/services/networking/gateone.nix +++ b/nixos/modules/services/networking/gateone.nix @@ -36,11 +36,11 @@ config = mkIf cfg.enable { preStart = '' if [ ! -d ${cfg.settingsDir} ] ; then mkdir -m 0750 -p ${cfg.settingsDir} - chown -R gateone.gateone ${cfg.settingsDir} + chown -R gateone:gateone ${cfg.settingsDir} fi if [ ! -d ${cfg.pidDir} ] ; then mkdir -m 0750 -p ${cfg.pidDir} - chown -R gateone.gateone ${cfg.pidDir} + chown -R gateone:gateone ${cfg.pidDir} fi ''; #unitConfig.RequiresMountsFor = "${cfg.settingsDir}"; diff --git a/nixos/modules/services/networking/ircd-hybrid/ircd.conf b/nixos/modules/services/networking/ircd-hybrid/ircd.conf index 17ef203840a..b82094cf5f0 100644 --- a/nixos/modules/services/networking/ircd-hybrid/ircd.conf +++ b/nixos/modules/services/networking/ircd-hybrid/ircd.conf @@ -98,7 +98,7 @@ serverinfo { * * openssl genrsa -out rsa.key 2048 * openssl rsa -in rsa.key -pubout -out rsa.pub - * chown <ircd-user>.<ircd.group> rsa.key rsa.pub + * chown <ircd-user>:<ircd.group> rsa.key rsa.pub * chmod 0600 rsa.key * chmod 0644 rsa.pub */ diff --git a/nixos/modules/services/networking/pleroma.nix b/nixos/modules/services/networking/pleroma.nix index c6d4c14dcb7..9b8382392c0 100644 --- a/nixos/modules/services/networking/pleroma.nix +++ b/nixos/modules/services/networking/pleroma.nix @@ -1,7 +1,6 @@ { config, options, lib, pkgs, stdenv, ... }: let cfg = config.services.pleroma; - cookieFile = "/var/lib/pleroma/.cookie"; in { options = { services.pleroma = with lib; { @@ -9,7 +8,7 @@ in { package = mkOption { type = types.package; - default = pkgs.pleroma.override { inherit cookieFile; }; + default = pkgs.pleroma; defaultText = literalExpression "pkgs.pleroma"; description = "Pleroma package to use."; }; @@ -101,6 +100,7 @@ in { after = [ "network-online.target" "postgresql.service" ]; wantedBy = [ "multi-user.target" ]; restartTriggers = [ config.environment.etc."/pleroma/config.exs".source ]; + environment.RELEASE_COOKIE = "/var/lib/pleroma/.cookie"; serviceConfig = { User = cfg.user; Group = cfg.group; @@ -118,10 +118,10 @@ in { # Better be safe than sorry migration-wise. ExecStartPre = let preScript = pkgs.writers.writeBashBin "pleromaStartPre" '' - if [ ! -f "${cookieFile}" ] || [ ! -s "${cookieFile}" ] + if [ ! -f /var/lib/pleroma/.cookie ] then echo "Creating cookie file" - dd if=/dev/urandom bs=1 count=16 | ${pkgs.hexdump}/bin/hexdump -e '16/1 "%02x"' > "${cookieFile}" + dd if=/dev/urandom bs=1 count=16 | hexdump -e '16/1 "%02x"' > /var/lib/pleroma/.cookie fi ${cfg.package}/bin/pleroma_ctl migrate ''; diff --git a/nixos/modules/services/networking/pptpd.nix b/nixos/modules/services/networking/pptpd.nix index 3e7753b9dd3..423e14e998f 100644 --- a/nixos/modules/services/networking/pptpd.nix +++ b/nixos/modules/services/networking/pptpd.nix @@ -108,7 +108,7 @@ with lib; #username pptpd password * EOF - chown root.root "$secrets" + chown root:root "$secrets" chmod 600 "$secrets" ''; diff --git a/nixos/modules/services/networking/prayer.nix b/nixos/modules/services/networking/prayer.nix index ae9258b2712..513509eaca3 100644 --- a/nixos/modules/services/networking/prayer.nix +++ b/nixos/modules/services/networking/prayer.nix @@ -82,7 +82,7 @@ in serviceConfig.Type = "forking"; preStart = '' mkdir -m 0755 -p ${stateDir} - chown ${prayerUser}.${prayerGroup} ${stateDir} + chown ${prayerUser}:${prayerGroup} ${stateDir} ''; script = "${prayer}/sbin/prayer --config-file=${prayerCfg}"; }; diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix index 8df450a11c6..e111b311d68 100644 --- a/nixos/modules/services/networking/supplicant.nix +++ b/nixos/modules/services/networking/supplicant.nix @@ -226,10 +226,10 @@ in ACTION=="add", SUBSYSTEM=="net", ENV{INTERFACE}=="${i}", TAG+="systemd", ENV{SYSTEMD_WANTS}+="supplicant-${replaceChars [" "] ["-"] iface}.service", TAG+="SUPPLICANT_ASSIGNED"''))} ${optionalString (hasAttr "WLAN" cfg) '' - ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="${pkgs.systemd}/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-wlan@$result.service" + ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="/run/current-system/systemd/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-wlan@$result.service" ''} ${optionalString (hasAttr "LAN" cfg) '' - ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="lan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="${pkgs.systemd}/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-lan@$result.service" + ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="lan", TAG!="SUPPLICANT_ASSIGNED", TAG+="systemd", PROGRAM="/run/current-system/systemd/bin/systemd-escape -p %E{INTERFACE}", ENV{SYSTEMD_WANTS}+="supplicant-lan@$result.service" ''} ''; })]; diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix index 1f64113950a..0133874d0e0 100644 --- a/nixos/modules/services/networking/tailscale.nix +++ b/nixos/modules/services/networking/tailscale.nix @@ -2,9 +2,13 @@ with lib; -let cfg = config.services.tailscale; +let + cfg = config.services.tailscale; + firewallOn = config.networking.firewall.enable; + rpfMode = config.networking.firewall.checkReversePath; + rpfIsStrict = rpfMode == true || rpfMode == "strict"; in { - meta.maintainers = with maintainers; [ danderson mbaillie ]; + meta.maintainers = with maintainers; [ danderson mbaillie twitchyliquid64 ]; options.services.tailscale = { enable = mkEnableOption "Tailscale client daemon"; @@ -36,17 +40,34 @@ in { }; config = mkIf cfg.enable { + warnings = optional (firewallOn && rpfIsStrict) "Strict reverse path filtering breaks Tailscale exit node use and some subnet routing setups. Consider setting `networking.firewall.checkReversePath` = 'loose'"; environment.systemPackages = [ cfg.package ]; # for the CLI systemd.packages = [ cfg.package ]; systemd.services.tailscaled = { wantedBy = [ "multi-user.target" ]; - path = [ pkgs.openresolv pkgs.procps ]; + path = [ + pkgs.openresolv # for configuring DNS in some configs + pkgs.procps # for collecting running services (opt-in feature) + pkgs.glibc # for `getent` to look up user shells + ]; serviceConfig.Environment = [ "PORT=${toString cfg.port}" ''"FLAGS=--tun ${lib.escapeShellArg cfg.interfaceName}"'' ] ++ (lib.optionals (cfg.permitCertUid != null) [ "TS_PERMIT_CERT_UID=${cfg.permitCertUid}" ]); + # Restart tailscaled with a single `systemctl restart` at the + # end of activation, rather than a `stop` followed by a later + # `start`. Activation over Tailscale can hang for tens of + # seconds in the stop+start setup, if the activation script has + # a significant delay between the stop and start phases + # (e.g. script blocked on another unit with a slow shutdown). + # + # Tailscale is aware of the correctness tradeoff involved, and + # already makes its upstream systemd unit robust against unit + # version mismatches on restart for compatibility with other + # linux distros. + stopIfChanged = false; }; }; } diff --git a/nixos/modules/services/networking/xl2tpd.nix b/nixos/modules/services/networking/xl2tpd.nix index 7dbe51422d9..9418488c1e9 100644 --- a/nixos/modules/services/networking/xl2tpd.nix +++ b/nixos/modules/services/networking/xl2tpd.nix @@ -116,18 +116,18 @@ with lib; #username xl2tpd password * EOF - chown root.root ppp/chap-secrets + chown root:root ppp/chap-secrets chmod 600 ppp/chap-secrets # The documentation says this file should be present but doesn't explain why and things work even if not there: [ -f l2tp-secrets ] || (echo -n "* * "; ${pkgs.apg}/bin/apg -n 1 -m 32 -x 32 -a 1 -M LCN) > l2tp-secrets - chown root.root l2tp-secrets + chown root:root l2tp-secrets chmod 600 l2tp-secrets popd > /dev/null mkdir -p /run/xl2tpd - chown root.root /run/xl2tpd + chown root:root /run/xl2tpd chmod 700 /run/xl2tpd ''; diff --git a/nixos/modules/services/security/kanidm.nix b/nixos/modules/services/security/kanidm.nix new file mode 100644 index 00000000000..a7c51b9a877 --- /dev/null +++ b/nixos/modules/services/security/kanidm.nix @@ -0,0 +1,345 @@ +{ config, lib, options, pkgs, ... }: +let + cfg = config.services.kanidm; + settingsFormat = pkgs.formats.toml { }; + # Remove null values, so we can document optional values that don't end up in the generated TOML file. + filterConfig = lib.converge (lib.filterAttrsRecursive (_: v: v != null)); + serverConfigFile = settingsFormat.generate "server.toml" (filterConfig cfg.serverSettings); + clientConfigFile = settingsFormat.generate "kanidm-config.toml" (filterConfig cfg.clientSettings); + unixConfigFile = settingsFormat.generate "kanidm-unixd.toml" (filterConfig cfg.unixSettings); + + defaultServiceConfig = { + BindReadOnlyPaths = [ + "/nix/store" + "-/etc/resolv.conf" + "-/etc/nsswitch.conf" + "-/etc/hosts" + "-/etc/localtime" + ]; + CapabilityBoundingSet = ""; + # ProtectClock= adds DeviceAllow=char-rtc r + DeviceAllow = ""; + # Implies ProtectSystem=strict, which re-mounts all paths + # DynamicUser = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateNetwork = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectHome = true; + ProtectHostname = true; + # Would re-mount paths ignored by temporary root + #ProtectSystem = "strict"; + ProtectControlGroups = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged @resources @setuid @keyring" ]; + # Does not work well with the temporary root + #UMask = "0066"; + }; + +in +{ + options.services.kanidm = { + enableClient = lib.mkEnableOption "the Kanidm client"; + enableServer = lib.mkEnableOption "the Kanidm server"; + enablePam = lib.mkEnableOption "the Kanidm PAM and NSS integration."; + + serverSettings = lib.mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options = { + bindaddress = lib.mkOption { + description = "Address/port combination the webserver binds to."; + example = "[::1]:8443"; + type = lib.types.str; + }; + # Should be optional but toml does not accept null + ldapbindaddress = lib.mkOption { + description = '' + Address and port the LDAP server is bound to. Setting this to <literal>null</literal> disables the LDAP interface. + ''; + example = "[::1]:636"; + default = null; + type = lib.types.nullOr lib.types.str; + }; + origin = lib.mkOption { + description = "The origin of your Kanidm instance. Must have https as protocol."; + example = "https://idm.example.org"; + type = lib.types.strMatching "^https://.*"; + }; + domain = lib.mkOption { + description = '' + The <literal>domain</literal> that Kanidm manages. Must be below or equal to the domain + specified in <literal>serverSettings.origin</literal>. + This can be left at <literal>null</literal>, only if your instance has the role <literal>ReadOnlyReplica</literal>. + While it is possible to change the domain later on, it requires extra steps! + Please consider the warnings and execute the steps described + <link xlink:href="https://kanidm.github.io/kanidm/stable/administrivia.html#rename-the-domain">in the documentation</link>. + ''; + example = "example.org"; + default = null; + type = lib.types.nullOr lib.types.str; + }; + db_path = lib.mkOption { + description = "Path to Kanidm database."; + default = "/var/lib/kanidm/kanidm.db"; + readOnly = true; + type = lib.types.path; + }; + log_level = lib.mkOption { + description = "Log level of the server."; + default = "default"; + type = lib.types.enum [ "default" "verbose" "perfbasic" "perffull" ]; + }; + role = lib.mkOption { + description = "The role of this server. This affects the replication relationship and thereby available features."; + default = "WriteReplica"; + type = lib.types.enum [ "WriteReplica" "WriteReplicaNoUI" "ReadOnlyReplica" ]; + }; + }; + }; + default = { }; + description = '' + Settings for Kanidm, see + <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/server_configuration.md">the documentation</link> + and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/server.toml">example configuration</link> + for possible values. + ''; + }; + + clientSettings = lib.mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options.uri = lib.mkOption { + description = "Address of the Kanidm server."; + example = "http://127.0.0.1:8080"; + type = lib.types.str; + }; + }; + description = '' + Configure Kanidm clients, needed for the PAM daemon. See + <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/client_tools.md#kanidm-configuration">the documentation</link> + and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/config">example configuration</link> + for possible values. + ''; + }; + + unixSettings = lib.mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options.pam_allowed_login_groups = lib.mkOption { + description = "Kanidm groups that are allowed to login using PAM."; + example = "my_pam_group"; + type = lib.types.listOf lib.types.str; + }; + }; + description = '' + Configure Kanidm unix daemon. + See <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/pam_and_nsswitch.md#the-unix-daemon">the documentation</link> + and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/unixd">example configuration</link> + for possible values. + ''; + }; + }; + + config = lib.mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) { + assertions = + [ + { + assertion = !cfg.enableServer || ((cfg.serverSettings.tls_chain or null) == null) || (!lib.isStorePath cfg.serverSettings.tls_chain); + message = '' + <option>services.kanidm.serverSettings.tls_chain</option> points to + a file in the Nix store. You should use a quoted absolute path to + prevent this. + ''; + } + { + assertion = !cfg.enableServer || ((cfg.serverSettings.tls_key or null) == null) || (!lib.isStorePath cfg.serverSettings.tls_key); + message = '' + <option>services.kanidm.serverSettings.tls_key</option> points to + a file in the Nix store. You should use a quoted absolute path to + prevent this. + ''; + } + { + assertion = !cfg.enableClient || options.services.kanidm.clientSettings.isDefined; + message = '' + <option>services.kanidm.clientSettings</option> needs to be configured + if the client is enabled. + ''; + } + { + assertion = !cfg.enablePam || options.services.kanidm.clientSettings.isDefined; + message = '' + <option>services.kanidm.clientSettings</option> needs to be configured + for the PAM daemon to connect to the Kanidm server. + ''; + } + { + assertion = !cfg.enableServer || (cfg.serverSettings.domain == null + -> cfg.serverSettings.role == "WriteReplica" || cfg.serverSettings.role == "WriteReplicaNoUI"); + message = '' + <option>services.kanidm.serverSettings.domain</option> can only be set if this instance + is not a ReadOnlyReplica. Otherwise the db would inherit it from + the instance it follows. + ''; + } + ]; + + environment.systemPackages = lib.mkIf cfg.enableClient [ pkgs.kanidm ]; + + systemd.services.kanidm = lib.mkIf cfg.enableServer { + description = "kanidm identity management daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = defaultServiceConfig // { + StateDirectory = "kanidm"; + StateDirectoryMode = "0700"; + ExecStart = "${pkgs.kanidm}/bin/kanidmd server -c ${serverConfigFile}"; + User = "kanidm"; + Group = "kanidm"; + + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + # This would otherwise override the CAP_NET_BIND_SERVICE capability. + PrivateUsers = false; + # Port needs to be exposed to the host network + PrivateNetwork = false; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + TemporaryFileSystem = "/:ro"; + }; + environment.RUST_LOG = "info"; + }; + + systemd.services.kanidm-unixd = lib.mkIf cfg.enablePam { + description = "Kanidm PAM daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + restartTriggers = [ unixConfigFile clientConfigFile ]; + serviceConfig = defaultServiceConfig // { + CacheDirectory = "kanidm-unixd"; + CacheDirectoryMode = "0700"; + RuntimeDirectory = "kanidm-unixd"; + ExecStart = "${pkgs.kanidm}/bin/kanidm_unixd"; + User = "kanidm-unixd"; + Group = "kanidm-unixd"; + + BindReadOnlyPaths = [ + "/nix/store" + "-/etc/resolv.conf" + "-/etc/nsswitch.conf" + "-/etc/hosts" + "-/etc/localtime" + "-/etc/kanidm" + "-/etc/static/kanidm" + ]; + BindPaths = [ + # To create the socket + "/run/kanidm-unixd:/var/run/kanidm-unixd" + ]; + # Needs to connect to kanidmd + PrivateNetwork = false; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + TemporaryFileSystem = "/:ro"; + }; + environment.RUST_LOG = "info"; + }; + + systemd.services.kanidm-unixd-tasks = lib.mkIf cfg.enablePam { + description = "Kanidm PAM home management daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "kanidm-unixd.service" ]; + partOf = [ "kanidm-unixd.service" ]; + restartTriggers = [ unixConfigFile clientConfigFile ]; + serviceConfig = { + ExecStart = "${pkgs.kanidm}/bin/kanidm_unixd_tasks"; + + BindReadOnlyPaths = [ + "/nix/store" + "-/etc/resolv.conf" + "-/etc/nsswitch.conf" + "-/etc/hosts" + "-/etc/localtime" + "-/etc/kanidm" + "-/etc/static/kanidm" + ]; + BindPaths = [ + # To manage home directories + "/home" + # To connect to kanidm-unixd + "/run/kanidm-unixd:/var/run/kanidm-unixd" + ]; + # CAP_DAC_OVERRIDE is needed to ignore ownership of unixd socket + CapabilityBoundingSet = [ "CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_DAC_READ_SEARCH" ]; + IPAddressDeny = "any"; + # Need access to users + PrivateUsers = false; + # Need access to home directories + ProtectHome = false; + RestrictAddressFamilies = [ "AF_UNIX" ]; + TemporaryFileSystem = "/:ro"; + }; + environment.RUST_LOG = "info"; + }; + + # These paths are hardcoded + environment.etc = lib.mkMerge [ + (lib.mkIf options.services.kanidm.clientSettings.isDefined { + "kanidm/config".source = clientConfigFile; + }) + (lib.mkIf cfg.enablePam { + "kanidm/unixd".source = unixConfigFile; + }) + ]; + + system.nssModules = lib.mkIf cfg.enablePam [ pkgs.kanidm ]; + + system.nssDatabases.group = lib.optional cfg.enablePam "kanidm"; + system.nssDatabases.passwd = lib.optional cfg.enablePam "kanidm"; + + users.groups = lib.mkMerge [ + (lib.mkIf cfg.enableServer { + kanidm = { }; + }) + (lib.mkIf cfg.enablePam { + kanidm-unixd = { }; + }) + ]; + users.users = lib.mkMerge [ + (lib.mkIf cfg.enableServer { + kanidm = { + description = "Kanidm server"; + isSystemUser = true; + group = "kanidm"; + packages = with pkgs; [ kanidm ]; + }; + }) + (lib.mkIf cfg.enablePam { + kanidm-unixd = { + description = "Kanidm PAM daemon"; + isSystemUser = true; + group = "kanidm-unixd"; + }; + }) + ]; + }; + + meta.maintainers = with lib.maintainers; [ erictapen Flakebi ]; + meta.buildDocsInSandbox = false; +} diff --git a/nixos/modules/services/security/sshguard.nix b/nixos/modules/services/security/sshguard.nix index 53bd9efa5ac..3be0a8c700b 100644 --- a/nixos/modules/services/security/sshguard.nix +++ b/nixos/modules/services/security/sshguard.nix @@ -17,7 +17,7 @@ let else "sshg-fw-ipset"; in pkgs.writeText "sshguard.conf" '' BACKEND="${pkgs.sshguard}/libexec/${backend}" - LOGREADER="LANG=C ${pkgs.systemd}/bin/journalctl ${args}" + LOGREADER="LANG=C ${config.systemd.package}/bin/journalctl ${args}" ''; in { diff --git a/nixos/modules/services/wayland/cage.nix b/nixos/modules/services/wayland/cage.nix index a32b81a916f..b818f5c463a 100644 --- a/nixos/modules/services/wayland/cage.nix +++ b/nixos/modules/services/wayland/cage.nix @@ -88,7 +88,7 @@ in { account required pam_unix.so session required pam_unix.so session required pam_env.so conffile=/etc/pam/environment readenv=0 - session required ${pkgs.systemd}/lib/security/pam_systemd.so + session required ${config.systemd.package}/lib/security/pam_systemd.so ''; hardware.opengl.enable = mkDefault true; diff --git a/nixos/modules/services/web-apps/restya-board.nix b/nixos/modules/services/web-apps/restya-board.nix index 4b36cc8754c..0bfa2368787 100644 --- a/nixos/modules/services/web-apps/restya-board.nix +++ b/nixos/modules/services/web-apps/restya-board.nix @@ -294,7 +294,7 @@ in ln -sf "${cfg.dataDir}/client/img" "${runDir}/client/img" chmod g+w "${runDir}/tmp/cache" - chown -R "${cfg.user}"."${cfg.group}" "${runDir}" + chown -R "${cfg.user}":"${cfg.group}" "${runDir}" mkdir -m 0750 -p "${cfg.dataDir}" @@ -302,9 +302,9 @@ in mkdir -m 0750 -p "${cfg.dataDir}/client/img" cp -r "${pkgs.restya-board}/media/"* "${cfg.dataDir}/media" cp -r "${pkgs.restya-board}/client/img/"* "${cfg.dataDir}/client/img" - chown "${cfg.user}"."${cfg.group}" "${cfg.dataDir}" - chown -R "${cfg.user}"."${cfg.group}" "${cfg.dataDir}/media" - chown -R "${cfg.user}"."${cfg.group}" "${cfg.dataDir}/client/img" + chown "${cfg.user}":"${cfg.group}" "${cfg.dataDir}" + chown -R "${cfg.user}":"${cfg.group}" "${cfg.dataDir}/media" + chown -R "${cfg.user}":"${cfg.group}" "${cfg.dataDir}/client/img" ${optionalString (cfg.database.host == null) '' if ! [ -e "${cfg.dataDir}/.db-initialized" ]; then diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix index 8247a7e381c..f48eac21bd8 100644 --- a/nixos/modules/services/x11/desktop-managers/default.nix +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -18,7 +18,7 @@ in # determines the default: later modules (if enabled) are preferred. # E.g., if Plasma 5 is enabled, it supersedes xterm. imports = [ - ./none.nix ./xterm.nix ./xfce.nix ./plasma5.nix ./lumina.nix + ./none.nix ./xterm.nix ./phosh.nix ./xfce.nix ./plasma5.nix ./lumina.nix ./lxqt.nix ./enlightenment.nix ./gnome.nix ./retroarch.nix ./kodi.nix ./mate.nix ./pantheon.nix ./surf-display.nix ./cde.nix ./cinnamon.nix diff --git a/nixos/modules/programs/phosh.nix b/nixos/modules/services/x11/desktop-managers/phosh.nix index ad875616ac9..4bf78fa16e7 100644 --- a/nixos/modules/programs/phosh.nix +++ b/nixos/modules/services/x11/desktop-managers/phosh.nix @@ -3,7 +3,7 @@ with lib; let - cfg = config.programs.phosh; + cfg = config.services.xserver.desktopManager.phosh; # Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop oskItem = pkgs.makeDesktopItem { @@ -118,12 +118,39 @@ let [cursor] theme = ${phoc.cursorTheme} ''; -in { +in + +{ options = { - programs.phosh = { - enable = mkEnableOption '' - Whether to enable, Phosh, related packages and default configurations. - ''; + services.xserver.desktopManager.phosh = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the Phone Shell."; + }; + + package = mkOption { + type = types.package; + default = pkgs.phosh; + defaultText = literalExpression "pkgs.phosh"; + example = literalExpression "pkgs.phosh"; + description = '' + Package that should be used for Phosh. + ''; + }; + + user = mkOption { + description = "The user to run the Phosh service."; + type = types.str; + example = "alice"; + }; + + group = mkOption { + description = "The group to run the Phosh service."; + type = types.str; + example = "users"; + }; + phocConfig = mkOption { description = '' Configurations for the Phoc compositor. @@ -135,14 +162,42 @@ in { }; config = mkIf cfg.enable { + systemd.defaultUnit = "graphical.target"; + # Inspired by https://gitlab.gnome.org/World/Phosh/phosh/-/blob/main/data/phosh.service + systemd.services.phosh = { + wantedBy = [ "graphical.target" ]; + serviceConfig = { + ExecStart = "${cfg.package}/bin/phosh"; + User = cfg.user; + Group = cfg.group; + PAMName = "login"; + WorkingDirectory = "~"; + Restart = "always"; + + TTYPath = "/dev/tty7"; + TTYReset = "yes"; + TTYVHangup = "yes"; + TTYVTDisallocate = "yes"; + + # Fail to start if not controlling the tty. + StandardInput = "tty-fail"; + StandardOutput = "journal"; + StandardError = "journal"; + + # Log this user with utmp, letting it show up with commands 'w' and 'who'. + UtmpIdentifier = "tty7"; + UtmpMode = "user"; + }; + }; + environment.systemPackages = [ pkgs.phoc - pkgs.phosh + cfg.package pkgs.squeekboard oskItem ]; - systemd.packages = [ pkgs.phosh ]; + systemd.packages = [ cfg.package ]; programs.feedbackd.enable = true; @@ -152,7 +207,7 @@ in { services.gnome.core-shell.enable = true; services.gnome.core-os-services.enable = true; - services.xserver.displayManager.sessionPackages = [ pkgs.phosh ]; + services.xserver.displayManager.sessionPackages = [ cfg.package ]; environment.etc."phosh/phoc.ini".source = if builtins.isPath cfg.phocConfig then cfg.phocConfig diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 70ae6b8978d..4941d13c810 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -298,7 +298,7 @@ in session required pam_succeed_if.so audit quiet_success user = gdm session required pam_env.so conffile=/etc/pam/environment readenv=0 - session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${config.systemd.package}/lib/security/pam_systemd.so session optional pam_keyinit.so force revoke session optional pam_permit.so ''; diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 27dfed3cc14..302c8fe0d91 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -287,7 +287,7 @@ in session required pam_succeed_if.so audit quiet_success user = lightdm session required pam_env.so conffile=/etc/pam/environment readenv=0 - session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${config.systemd.package}/lib/security/pam_systemd.so session optional pam_keyinit.so force revoke session optional pam_permit.so ''; diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix index 529a086381f..c44f24002e0 100644 --- a/nixos/modules/services/x11/display-managers/sddm.nix +++ b/nixos/modules/services/x11/display-managers/sddm.nix @@ -231,7 +231,7 @@ in session required pam_succeed_if.so audit quiet_success user = sddm session required pam_env.so conffile=/etc/pam/environment readenv=0 - session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${config.systemd.package}/lib/security/pam_systemd.so session optional pam_keyinit.so force revoke session optional pam_permit.so ''; diff --git a/nixos/modules/system/boot/modprobe.nix b/nixos/modules/system/boot/modprobe.nix index e683d181729..21be18ef866 100644 --- a/nixos/modules/system/boot/modprobe.nix +++ b/nixos/modules/system/boot/modprobe.nix @@ -52,7 +52,7 @@ with lib; ''; environment.etc."modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases; - environment.etc."modprobe.d/systemd.conf".source = "${pkgs.systemd}/lib/modprobe.d/systemd.conf"; + environment.etc."modprobe.d/systemd.conf".source = "${config.systemd.package}/lib/modprobe.d/systemd.conf"; environment.systemPackages = [ pkgs.kmod ]; diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index d1a6f46bfc4..0336930b3ab 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -779,6 +779,7 @@ let "RouteDenyList" "RouteAllowList" "DHCPv6Client" + "RouteMetric" ]) (assertValueOneOf "UseDNS" boolValues) (assertValueOneOf "UseDomains" (boolValues ++ ["route"])) diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix index 78ae8e9d20b..8b57cae3c40 100644 --- a/nixos/modules/system/boot/plymouth.nix +++ b/nixos/modules/system/boot/plymouth.nix @@ -4,7 +4,10 @@ with lib; let - inherit (pkgs) plymouth nixos-icons; + inherit (pkgs) nixos-icons; + plymouth = pkgs.plymouth.override { + systemd = config.boot.initrd.systemd.package; + }; cfg = config.boot.plymouth; opt = options.boot.plymouth; @@ -143,7 +146,88 @@ in systemd.services.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; systemd.paths.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; - boot.initrd.extraUtilsCommands = '' + boot.initrd.systemd = { + extraBin.plymouth = "${plymouth}/bin/plymouth"; # for the recovery shell + storePaths = [ + "${lib.getBin config.boot.initrd.systemd.package}/bin/systemd-tty-ask-password-agent" + "${plymouth}/bin/plymouthd" + "${plymouth}/sbin/plymouthd" + ]; + packages = [ plymouth ]; # systemd units + contents = { + # Files + "/etc/plymouth/plymouthd.conf".source = configFile; + "/etc/plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults"; + "/etc/plymouth/logo.png".source = cfg.logo; + # Directories + "/etc/plymouth/plugins".source = pkgs.runCommand "plymouth-initrd-plugins" {} '' + # Check if the actual requested theme is here + if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then + echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" + exit 1 + fi + + moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)" + + mkdir -p $out/renderers + # module might come from a theme + cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out + cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/renderers + ''; + "/etc/plymouth/themes".source = pkgs.runCommand "plymouth-initrd-themes" {} '' + # Check if the actual requested theme is here + if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then + echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" + exit 1 + fi + + mkdir $out + cp -r ${themesEnv}/share/plymouth/themes/${cfg.theme} $out + # Copy more themes if the theme depends on others + for theme in $(grep -hRo '/etc/plymouth/themes/.*$' ${themesEnv} | xargs -n1 basename); do + if [[ -d "${themesEnv}/theme" ]]; then + cp -r "${themesEnv}/theme" $out + fi + done + ''; + + # Fonts + "/etc/plymouth/fonts".source = pkgs.runCommand "plymouth-initrd-fonts" {} '' + mkdir -p $out + cp ${cfg.font} $out + ''; + "/etc/fonts/fonts.conf".text = '' + <?xml version="1.0"?> + <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> + <fontconfig> + <dir>/etc/plymouth/fonts</dir> + </fontconfig> + ''; + }; + # Properly enable units. These are the units that arch copies + services = { + plymouth-halt.wantedBy = [ "halt.target" ]; + plymouth-kexec.wantedBy = [ "kexec.target" ]; + plymouth-poweroff.wantedBy = [ "poweroff.target" ]; + plymouth-quit-wait.wantedBy = [ "multi-user.target" ]; + plymouth-quit.wantedBy = [ "multi-user.target" ]; + plymouth-read-write.wantedBy = [ "sysinit.target" ]; + plymouth-reboot.wantedBy = [ "reboot.target" ]; + plymouth-start.wantedBy = [ "initrd-switch-root.target" "sysinit.target" ]; + plymouth-switch-root-initramfs.wantedBy = [ "halt.target" "kexec.target" "plymouth-switch-root-initramfs.service" "poweroff.target" "reboot.target" ]; + plymouth-switch-root.wantedBy = [ "initrd-switch-root.target" ]; + }; + }; + + # Insert required udev rules. We take stage 2 systemd because the udev + # rules are only generated when building with logind. + boot.initrd.services.udev.packages = [ (pkgs.runCommand "initrd-plymouth-udev-rules" {} '' + mkdir -p $out/etc/udev/rules.d + cp ${config.systemd.package.out}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out/etc/udev/rules.d + sed -i '/loginctl/d' $out/etc/udev/rules.d/71-seat.rules + '') ]; + + boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${plymouth}/bin/plymouth copy_bin_and_libs ${plymouth}/bin/plymouthd @@ -198,18 +282,18 @@ in EOF ''; - boot.initrd.extraUtilsCommandsTest = '' + boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.enable) '' $out/bin/plymouthd --help >/dev/null $out/bin/plymouth --help >/dev/null ''; - boot.initrd.extraUdevRulesCommands = '' + boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.enable) '' cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out sed -i '/loginctl/d' $out/71-seat.rules ''; # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen. - boot.initrd.preLVMCommands = mkAfter '' + boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.enable) (mkAfter '' mkdir -p /etc/plymouth mkdir -p /run/plymouth ln -s ${configFile} /etc/plymouth/plymouthd.conf @@ -221,16 +305,16 @@ in plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session plymouth show-splash - ''; + ''); - boot.initrd.postMountCommands = '' + boot.initrd.postMountCommands = mkIf (!config.boot.initrd.enable) '' plymouth update-root-fs --new-root-dir="$targetRoot" ''; # `mkBefore` to ensure that any custom prompts would be visible. - boot.initrd.preFailCommands = mkBefore '' + boot.initrd.preFailCommands = mkIf (!config.boot.initrd.enable) (mkBefore '' plymouth quit --wait - ''; + ''); }; diff --git a/nixos/modules/system/boot/systemd/nspawn.nix b/nixos/modules/system/boot/systemd/nspawn.nix index bf9995d03cc..da03c60db52 100644 --- a/nixos/modules/system/boot/systemd/nspawn.nix +++ b/nixos/modules/system/boot/systemd/nspawn.nix @@ -16,7 +16,7 @@ let "LimitNOFILE" "LimitAS" "LimitNPROC" "LimitMEMLOCK" "LimitLOCKS" "LimitSIGPENDING" "LimitMSGQUEUE" "LimitNICE" "LimitRTPRIO" "LimitRTTIME" "OOMScoreAdjust" "CPUAffinity" "Hostname" "ResolvConf" "Timezone" - "LinkJournal" + "LinkJournal" "Ephemeral" "AmbientCapability" ]) (assertValueOneOf "Boot" boolValues) (assertValueOneOf "ProcessTwo" boolValues) @@ -26,11 +26,13 @@ let checkFiles = checkUnitConfig "Files" [ (assertOnlyFields [ "ReadOnly" "Volatile" "Bind" "BindReadOnly" "TemporaryFileSystem" - "Overlay" "OverlayReadOnly" "PrivateUsersChown" + "Overlay" "OverlayReadOnly" "PrivateUsersChown" "BindUser" + "Inaccessible" "PrivateUserOwnership" ]) (assertValueOneOf "ReadOnly" boolValues) (assertValueOneOf "Volatile" (boolValues ++ [ "state" ])) (assertValueOneOf "PrivateUsersChown" boolValues) + (assertValueOneOf "PrivateUserOwnership" [ "off" "chown" "map" "auto" ]) ]; checkNetwork = checkUnitConfig "Network" [ diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix index d00dc761d6e..21a25cbfa96 100644 --- a/nixos/modules/tasks/auto-upgrade.nix +++ b/nixos/modules/tasks/auto-upgrade.nix @@ -190,7 +190,7 @@ in { nixos-rebuild = "${config.system.build.nixos-rebuild}/bin/nixos-rebuild"; date = "${pkgs.coreutils}/bin/date"; readlink = "${pkgs.coreutils}/bin/readlink"; - shutdown = "${pkgs.systemd}/bin/shutdown"; + shutdown = "${config.systemd.package}/bin/shutdown"; upgradeFlag = optional (cfg.channel == null) "--upgrade"; in if cfg.allowReboot then '' ${nixos-rebuild} boot ${toString (cfg.flags ++ upgradeFlag)} diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 5eca68798d5..c8bbfe9769b 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -58,6 +58,13 @@ let # latter case it makes one last attempt at importing, allowing the system to # (eventually) boot even with a degraded pool. importLib = {zpoolCmd, awkCmd, cfgZfs}: '' + for o in $(cat /proc/cmdline); do + case $o in + zfs_force|zfs_force=1|zfs_force=y) + ZFS_FORCE="-f" + ;; + esac + done poolReady() { pool="$1" state="$("${zpoolCmd}" import 2>/dev/null | "${awkCmd}" "/pool: $pool/ { found = 1 }; /state:/ { if (found == 1) { print \$2; exit } }; END { if (found == 0) { print \"MISSING\" } }")" @@ -78,6 +85,95 @@ let } ''; + getPoolFilesystems = pool: + filter (x: x.fsType == "zfs" && (fsToPool x) == pool) config.system.build.fileSystems; + + getPoolMounts = prefix: pool: + let + # Remove the "/" suffix because even though most mountpoints + # won't have it, the "/" mountpoint will, and we can't have the + # trailing slash in "/sysroot/" in stage 1. + mountPoint = fs: escapeSystemdPath (prefix + (lib.removeSuffix "/" fs.mountPoint)); + in + map (x: "${mountPoint x}.mount") (getPoolFilesystems pool); + + getKeyLocations = pool: + if isBool cfgZfs.requestEncryptionCredentials + then "${cfgZfs.package}/sbin/zfs list -rHo name,keylocation,keystatus ${pool}" + else "${cfgZfs.package}/sbin/zfs list -Ho name,keylocation,keystatus ${toString (filter (x: datasetToPool x == pool) cfgZfs.requestEncryptionCredentials)}"; + + createImportService = { pool, systemd, force, prefix ? "" }: + nameValuePair "zfs-import-${pool}" { + description = "Import ZFS pool \"${pool}\""; + # we need systemd-udev-settle to ensure devices are available + # In the future, hopefully someone will complete this: + # https://github.com/zfsonlinux/zfs/pull/4943 + requires = [ "systemd-udev-settle.service" ]; + after = [ + "systemd-udev-settle.service" + "systemd-modules-load.service" + "systemd-ask-password-console.service" + ]; + wantedBy = (getPoolMounts prefix pool) ++ [ "local-fs.target" ]; + before = (getPoolMounts prefix pool) ++ [ "local-fs.target" ]; + unitConfig = { + DefaultDependencies = "no"; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + environment.ZFS_FORCE = optionalString force "-f"; + script = (importLib { + # See comments at importLib definition. + zpoolCmd = "${cfgZfs.package}/sbin/zpool"; + awkCmd = "${pkgs.gawk}/bin/awk"; + inherit cfgZfs; + }) + '' + poolImported "${pool}" && exit + echo -n "importing ZFS pool \"${pool}\"..." + # Loop across the import until it succeeds, because the devices needed may not be discovered yet. + for trial in `seq 1 60`; do + poolReady "${pool}" && poolImport "${pool}" && break + sleep 1 + done + poolImported "${pool}" || poolImport "${pool}" # Try one last time, e.g. to import a degraded pool. + if poolImported "${pool}"; then + ${optionalString (if isBool cfgZfs.requestEncryptionCredentials + then cfgZfs.requestEncryptionCredentials + else cfgZfs.requestEncryptionCredentials != []) '' + ${getKeyLocations pool} | while IFS=$'\t' read ds kl ks; do + { + if [[ "$ks" != unavailable ]]; then + continue + fi + case "$kl" in + none ) + ;; + prompt ) + tries=3 + success=false + while [[ $success != true ]] && [[ $tries -gt 0 ]]; do + ${systemd}/bin/systemd-ask-password "Enter key for $ds:" | ${cfgZfs.package}/sbin/zfs load-key "$ds" \ + && success=true \ + || tries=$((tries - 1)) + done + [[ $success = true ]] + ;; + * ) + ${cfgZfs.package}/sbin/zfs load-key "$ds" + ;; + esac + } < /dev/null # To protect while read ds kl in case anything reads stdin + done + ''} + echo "Successfully imported ${pool}" + else + exit 1 + fi + ''; + }; + zedConf = generators.toKeyValue { mkKeyValue = generators.mkKeyValueDefault { mkValueString = v: @@ -428,14 +524,6 @@ in ''; postDeviceCommands = concatStringsSep "\n" (['' ZFS_FORCE="${optionalString cfgZfs.forceImportRoot "-f"}" - - for o in $(cat /proc/cmdline); do - case $o in - zfs_force|zfs_force=1) - ZFS_FORCE="-f" - ;; - esac - done ''] ++ [(importLib { # See comments at importLib definition. zpoolCmd = "zpool"; @@ -464,6 +552,21 @@ in zfs load-key ${fs} '') cfgZfs.requestEncryptionCredentials} '') rootPools)); + + # Systemd in stage 1 + systemd = { + packages = [cfgZfs.package]; + services = listToAttrs (map (pool: createImportService { + inherit pool; + systemd = config.boot.initrd.systemd.package; + force = cfgZfs.forceImportRoot; + prefix = "/sysroot"; + }) rootPools); + extraBin = { + # zpool and zfs are already in thanks to fsPackages + awk = "${pkgs.gawk}/bin/awk"; + }; + }; }; systemd.shutdownRamfs.contents."/etc/systemd/system-shutdown/zpool".source = pkgs.writeShellScript "zpool-sync-shutdown" '' @@ -521,79 +624,11 @@ in systemd.packages = [ cfgZfs.package ]; systemd.services = let - getPoolFilesystems = pool: - filter (x: x.fsType == "zfs" && (fsToPool x) == pool) config.system.build.fileSystems; - - getPoolMounts = pool: - let - mountPoint = fs: escapeSystemdPath fs.mountPoint; - in - map (x: "${mountPoint x}.mount") (getPoolFilesystems pool); - - createImportService = pool: - nameValuePair "zfs-import-${pool}" { - description = "Import ZFS pool \"${pool}\""; - # we need systemd-udev-settle until https://github.com/zfsonlinux/zfs/pull/4943 is merged - requires = [ "systemd-udev-settle.service" ]; - after = [ - "systemd-udev-settle.service" - "systemd-modules-load.service" - "systemd-ask-password-console.service" - ]; - wantedBy = (getPoolMounts pool) ++ [ "local-fs.target" ]; - before = (getPoolMounts pool) ++ [ "local-fs.target" ]; - unitConfig = { - DefaultDependencies = "no"; - }; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - }; - environment.ZFS_FORCE = optionalString cfgZfs.forceImportAll "-f"; - script = (importLib { - # See comments at importLib definition. - zpoolCmd = "${cfgZfs.package}/sbin/zpool"; - awkCmd = "${pkgs.gawk}/bin/awk"; - inherit cfgZfs; - }) + '' - poolImported "${pool}" && exit - echo -n "importing ZFS pool \"${pool}\"..." - # Loop across the import until it succeeds, because the devices needed may not be discovered yet. - for trial in `seq 1 60`; do - poolReady "${pool}" && poolImport "${pool}" && break - sleep 1 - done - poolImported "${pool}" || poolImport "${pool}" # Try one last time, e.g. to import a degraded pool. - if poolImported "${pool}"; then - ${optionalString (if isBool cfgZfs.requestEncryptionCredentials - then cfgZfs.requestEncryptionCredentials - else cfgZfs.requestEncryptionCredentials != []) '' - ${cfgZfs.package}/sbin/zfs list -rHo name,keylocation ${pool} | while IFS=$'\t' read ds kl; do - { - ${optionalString (!isBool cfgZfs.requestEncryptionCredentials) '' - if ! echo '${concatStringsSep "\n" cfgZfs.requestEncryptionCredentials}' | grep -qFx "$ds"; then - continue - fi - ''} - case "$kl" in - none ) - ;; - prompt ) - ${config.systemd.package}/bin/systemd-ask-password "Enter key for $ds:" | ${cfgZfs.package}/sbin/zfs load-key "$ds" - ;; - * ) - ${cfgZfs.package}/sbin/zfs load-key "$ds" - ;; - esac - } < /dev/null # To protect while read ds kl in case anything reads stdin - done - ''} - echo "Successfully imported ${pool}" - else - exit 1 - fi - ''; - }; + createImportService' = pool: createImportService { + inherit pool; + systemd = config.systemd.package; + force = cfgZfs.forceImportAll; + }; # This forces a sync of any ZFS pools prior to poweroff, even if they're set # to sync=disabled. @@ -619,7 +654,7 @@ in wantedBy = [ "zfs.target" ]; }; - in listToAttrs (map createImportService dataPools ++ + in listToAttrs (map createImportService' dataPools ++ map createSyncService allPools ++ map createZfsService [ "zfs-mount" "zfs-share" "zfs-zed" ]); diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 8654539b662..110e84494a3 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -43,12 +43,6 @@ in } { assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null; message = "networking.defaultGateway6.interface is not supported by networkd."; - } { - assertion = cfg.useDHCP == false; - message = '' - networking.useDHCP is not supported by networkd. - Please use per interface configuration and set the global option to false. - ''; } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: { assertion = !rstp; message = "networking.bridges.${n}.rstp is not supported by networkd."; @@ -80,6 +74,42 @@ in in mkMerge [ { enable = true; } + (mkIf cfg.useDHCP { + networks."99-ethernet-default-dhcp" = lib.mkIf cfg.useDHCP { + # We want to match physical ethernet interfaces as commonly + # found on laptops, desktops and servers, to provide an + # "out-of-the-box" setup that works for common cases. This + # heuristic isn't perfect (it could match interfaces with + # custom names that _happen_ to start with en or eth), but + # should be good enough to make the common case easy and can + # be overridden on a case-by-case basis using + # higher-priority networks or by disabling useDHCP. + + # Type=ether matches veth interfaces as well, and this is + # more likely to result in interfaces being configured to + # use DHCP when they shouldn't. + + # We set RequiredForOnline to false, because it's fairly + # common for such devices to have multiple interfaces and + # only one of them to be connected (e.g. a laptop with + # ethernet and WiFi interfaces). Maybe one day networkd will + # support "any"-style RequiredForOnline... + matchConfig.Name = ["en*" "eth*"]; + DHCP = "yes"; + linkConfig.RequiredForOnline = lib.mkDefault false; + }; + networks."99-wireless-client-dhcp" = lib.mkIf cfg.useDHCP { + # Like above, but this is much more likely to be correct. + matchConfig.WLANInterfaceType = "station"; + DHCP = "yes"; + linkConfig.RequiredForOnline = lib.mkDefault false; + # We also set the route metric to one more than the default + # of 1024, so that Ethernet is preferred if both are + # available. + dhcpV4Config.RouteMetric = 1025; + ipv6AcceptRAConfig.RouteMetric = 1025; + }; + }) (mkMerge (forEach interfaces (i: { netdevs = mkIf i.virtual ({ "40-${i.name}" = { diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index d09e9b99248..d56159f1596 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -1254,11 +1254,6 @@ in Whether to use DHCP to obtain an IP address and other configuration for all network interfaces that are not manually configured. - - Using this option is highly discouraged and also incompatible with - <option>networking.useNetworkd</option>. Please use - <option>networking.interfaces.<name>.useDHCP</option> instead - and set this to false. ''; }; diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 81541477b9e..4ab2578eb81 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -129,6 +129,9 @@ in # Make sure we use the Guest Agent from the QEMU package for testing # to reduce the closure size required for the tests. services.qemuGuest.package = pkgs.qemu_test.ga; + + # Squelch warning about unset system.stateVersion + system.stateVersion = lib.mkDefault lib.trivial.release; }; } diff --git a/nixos/modules/virtualisation/amazon-init.nix b/nixos/modules/virtualisation/amazon-init.nix index 4f2f8df90eb..9c2adb90bfd 100644 --- a/nixos/modules/virtualisation/amazon-init.nix +++ b/nixos/modules/virtualisation/amazon-init.nix @@ -11,7 +11,7 @@ let echo "attempting to fetch configuration from EC2 user data..." export HOME=/root - export PATH=${pkgs.lib.makeBinPath [ config.nix.package pkgs.systemd pkgs.gnugrep pkgs.git pkgs.gnutar pkgs.gzip pkgs.gnused pkgs.xz config.system.build.nixos-rebuild]}:$PATH + export PATH=${pkgs.lib.makeBinPath [ config.nix.package config.systemd.package pkgs.gnugrep pkgs.git pkgs.gnutar pkgs.gzip pkgs.gnused pkgs.xz config.system.build.nixos-rebuild]}:$PATH export NIX_PATH=nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels userData=/etc/ec2-metadata/user-data diff --git a/nixos/modules/virtualisation/digital-ocean-init.nix b/nixos/modules/virtualisation/digital-ocean-init.nix index 4339d91de16..df30104b7d7 100644 --- a/nixos/modules/virtualisation/digital-ocean-init.nix +++ b/nixos/modules/virtualisation/digital-ocean-init.nix @@ -46,7 +46,7 @@ in { RemainAfterExit = true; }; restartIfChanged = false; - path = [ pkgs.jq pkgs.gnused pkgs.gnugrep pkgs.systemd config.nix.package config.system.build.nixos-rebuild ]; + path = [ pkgs.jq pkgs.gnused pkgs.gnugrep config.systemd.package config.nix.package config.system.build.nixos-rebuild ]; environment = { HOME = "/root"; NIX_PATH = concatStringsSep ":" [ diff --git a/nixos/modules/virtualisation/proxmox-lxc.nix b/nixos/modules/virtualisation/proxmox-lxc.nix index 3913b474afb..9b9f99e5b81 100644 --- a/nixos/modules/virtualisation/proxmox-lxc.nix +++ b/nixos/modules/virtualisation/proxmox-lxc.nix @@ -20,6 +20,15 @@ with lib; configuration from proxmox. ''; }; + manageHostName = mkOption { + type = types.bool; + default = false; + description = '' + Whether to manage hostname through nix options + When false, the hostname is picked up from /etc/hostname + populated by proxmox. + ''; + }; }; config = @@ -50,6 +59,8 @@ with lib; useDHCP = false; useHostResolvConf = false; useNetworkd = true; + # pick up hostname from /etc/hostname generated by proxmox + hostName = mkIf (!cfg.manageHostName) (mkForce ""); }; services.openssh = { diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index dda1c41f969..0c085b64efa 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -253,6 +253,7 @@ in k3s-single-node = handleTest ./k3s-single-node.nix {}; k3s-single-node-docker = handleTest ./k3s-single-node-docker.nix {}; kafka = handleTest ./kafka.nix {}; + kanidm = handleTest ./kanidm.nix {}; kbd-setfont-decompress = handleTest ./kbd-setfont-decompress.nix {}; kbd-update-search-paths-patch = handleTest ./kbd-update-search-paths-patch.nix {}; kea = handleTest ./kea.nix {}; diff --git a/nixos/tests/installed-tests/default.nix b/nixos/tests/installed-tests/default.nix index fd16b481168..c6fb37cfe58 100644 --- a/nixos/tests/installed-tests/default.nix +++ b/nixos/tests/installed-tests/default.nix @@ -106,6 +106,5 @@ in malcontent = callInstalledTest ./malcontent.nix {}; ostree = callInstalledTest ./ostree.nix {}; pipewire = callInstalledTest ./pipewire.nix {}; - power-profiles-daemon = callInstalledTest ./power-profiles-daemon.nix {}; xdg-desktop-portal = callInstalledTest ./xdg-desktop-portal.nix {}; } diff --git a/nixos/tests/installed-tests/power-profiles-daemon.nix b/nixos/tests/installed-tests/power-profiles-daemon.nix deleted file mode 100644 index 43629a0155d..00000000000 --- a/nixos/tests/installed-tests/power-profiles-daemon.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ pkgs, lib, makeInstalledTest, ... }: - -makeInstalledTest { - tested = pkgs.power-profiles-daemon; - - testConfig = { - services.power-profiles-daemon.enable = true; - }; -} diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix index a8b418626e6..d02387ee80e 100644 --- a/nixos/tests/installer-systemd-stage-1.nix +++ b/nixos/tests/installer-systemd-stage-1.nix @@ -27,7 +27,7 @@ simpleUefiGrubSpecialisation simpleUefiSystemdBoot # swraid - # zfsroot + zfsroot ; } diff --git a/nixos/tests/kanidm.nix b/nixos/tests/kanidm.nix new file mode 100644 index 00000000000..d34f680f522 --- /dev/null +++ b/nixos/tests/kanidm.nix @@ -0,0 +1,75 @@ +import ./make-test-python.nix ({ pkgs, ... }: + let + certs = import ./common/acme/server/snakeoil-certs.nix; + serverDomain = certs.domain; + in + { + name = "kanidm"; + meta.maintainers = with pkgs.lib.maintainers; [ erictapen Flakebi ]; + + nodes.server = { config, pkgs, lib, ... }: { + services.kanidm = { + enableServer = true; + serverSettings = { + origin = "https://${serverDomain}"; + domain = serverDomain; + bindaddress = "[::1]:8443"; + ldapbindaddress = "[::1]:636"; + }; + }; + + services.nginx = { + enable = true; + recommendedProxySettings = true; + virtualHosts."${serverDomain}" = { + forceSSL = true; + sslCertificate = certs."${serverDomain}".cert; + sslCertificateKey = certs."${serverDomain}".key; + locations."/".proxyPass = "http://[::1]:8443"; + }; + }; + + security.pki.certificateFiles = [ certs.ca.cert ]; + + networking.hosts."::1" = [ serverDomain ]; + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + users.users.kanidm.shell = pkgs.bashInteractive; + + environment.systemPackages = with pkgs; [ kanidm openldap ripgrep ]; + }; + + nodes.client = { pkgs, nodes, ... }: { + services.kanidm = { + enableClient = true; + clientSettings = { + uri = "https://${serverDomain}"; + }; + }; + + networking.hosts."${nodes.server.config.networking.primaryIPAddress}" = [ serverDomain ]; + + security.pki.certificateFiles = [ certs.ca.cert ]; + }; + + testScript = { nodes, ... }: + let + ldapBaseDN = builtins.concatStringsSep "," (map (s: "dc=" + s) (pkgs.lib.splitString "." serverDomain)); + + # We need access to the config file in the test script. + filteredConfig = pkgs.lib.converge + (pkgs.lib.filterAttrsRecursive (_: v: v != null)) + nodes.server.config.services.kanidm.serverSettings; + serverConfigFile = (pkgs.formats.toml { }).generate "server.toml" filteredConfig; + + in + '' + start_all() + server.wait_for_unit("kanidm.service") + server.wait_until_succeeds("curl -sf https://${serverDomain} | grep Kanidm") + server.wait_until_succeeds("ldapsearch -H ldap://[::1]:636 -b '${ldapBaseDN}' -x '(name=test)'") + client.wait_until_succeeds("kanidm login -D anonymous && kanidm self whoami | grep anonymous@${serverDomain}") + (rv, result) = server.execute("kanidmd recover_account -d quiet -c ${serverConfigFile} -n admin 2>&1 | rg -o '[A-Za-z0-9]{48}'") + assert rv == 0 + ''; + }) diff --git a/nixos/tests/kernel-generic.nix b/nixos/tests/kernel-generic.nix index f34d5d60794..1e60198abdd 100644 --- a/nixos/tests/kernel-generic.nix +++ b/nixos/tests/kernel-generic.nix @@ -30,6 +30,7 @@ let linux_5_4_hardened linux_5_10_hardened linux_5_15_hardened + linux_5_17_hardened linux_testing; }; diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index a1150097a09..2cc1e9b0942 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -139,6 +139,26 @@ let client.wait_until_succeeds("ping -c 1 192.168.3.1") ''; }; + dhcpDefault = { + name = "useDHCP-by-default"; + nodes.router = router; + nodes.client = { lib, ... }: { + # Disable test driver default config + networking.interfaces = lib.mkForce {}; + networking.useNetworkd = networkd; + virtualisation.vlans = [ 1 ]; + }; + testScript = '' + start_all() + client.wait_for_unit("multi-user.target") + client.wait_until_succeeds("ip addr show dev eth1 | grep '192.168.1'") + client.shell_interact() + client.succeed("ping -c 1 192.168.1.1") + router.succeed("ping -c 1 192.168.1.1") + router.succeed("ping -c 1 192.168.1.2") + client.succeed("ping -c 1 192.168.1.2") + ''; + }; dhcpSimple = { name = "SimpleDHCP"; nodes.router = router; diff --git a/nixos/tests/pleroma.nix b/nixos/tests/pleroma.nix index 90a9a251104..8998716243a 100644 --- a/nixos/tests/pleroma.nix +++ b/nixos/tests/pleroma.nix @@ -158,7 +158,9 @@ import ./make-test-python.nix ({ pkgs, ... }: # Waiting for pleroma to be up. timeout 5m bash -c 'while [[ "$(curl -s -o /dev/null -w '%{http_code}' https://pleroma.nixos.test/api/v1/instance)" != "200" ]]; do sleep 2; done' - pleroma_ctl user new jamy jamy@nixos.test --password 'jamy-password' --moderator --admin -y + # Toremove the RELEASE_COOKIE bit when https://github.com/NixOS/nixpkgs/issues/166229 gets fixed. + RELEASE_COOKIE="/var/lib/pleroma/.cookie" \ + pleroma_ctl user new jamy jamy@nixos.test --password 'jamy-password' --moderator --admin -y ''; tls-cert = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } '' diff --git a/nixos/tests/systemd-nspawn.nix b/nixos/tests/systemd-nspawn.nix index 5bf55060d2e..c2cb92d1130 100644 --- a/nixos/tests/systemd-nspawn.nix +++ b/nixos/tests/systemd-nspawn.nix @@ -25,8 +25,15 @@ let nspawnImages = (pkgs.runCommand "localhost" { buildInputs = [ pkgs.coreutils pkgs.gnupg ]; } '' mkdir -p $out cd $out + + # produce a testimage.raw dd if=/dev/urandom of=$out/testimage.raw bs=$((1024*1024+7)) count=5 - sha256sum testimage.raw > SHA256SUMS + + # produce a testimage2.tar.xz, containing the hello store path + tar cvJpf testimage2.tar.xz ${pkgs.hello} + + # produce signature(s) + sha256sum testimage* > SHA256SUMS export GNUPGHOME="$(mktemp -d)" cp -R ${gpgKeyring}/* $GNUPGHOME gpg --batch --sign --detach-sign --output SHA256SUMS.gpg SHA256SUMS @@ -56,5 +63,9 @@ in { client.succeed( "cmp /var/lib/machines/testimage.raw ${nspawnImages}/testimage.raw" ) + client.succeed("machinectl pull-tar --verify=signature http://server/testimage2.tar.xz") + client.succeed( + "cmp /var/lib/machines/testimage2/${pkgs.hello}/bin/hello ${pkgs.hello}/bin/hello" + ) ''; }) diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index 27093aab96e..4eb402a7d36 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -222,7 +222,7 @@ let machine.execute(ru("VBoxManage controlvm ${name} poweroff")) machine.succeed("rm -rf ${sharePath}") machine.succeed("mkdir -p ${sharePath}") - machine.succeed("chown alice.users ${sharePath}") + machine.succeed("chown alice:users ${sharePath}") def create_vm_${name}(): |