summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-2311.section.md6
-rw-r--r--nixos/lib/test-driver/test_driver/efi.py31
-rw-r--r--nixos/lib/test-driver/test_driver/machine.py28
-rw-r--r--nixos/modules/module-list.nix6
-rw-r--r--nixos/modules/programs/wayland/river.nix59
-rw-r--r--nixos/modules/programs/wayland/sway.nix (renamed from nixos/modules/programs/sway.nix)63
-rw-r--r--nixos/modules/programs/wayland/waybar.nix (renamed from nixos/modules/programs/waybar.nix)0
-rw-r--r--nixos/modules/programs/wayland/wayland-session.nix23
-rw-r--r--nixos/modules/services/misc/etcd.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/cinnamon.nix9
-rw-r--r--nixos/tests/etcd-cluster.nix25
-rw-r--r--nixos/tests/etcd.nix2
12 files changed, 207 insertions, 51 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md
index 69b7aeb64de..ef4465d9ddf 100644
--- a/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -10,12 +10,18 @@
 
 <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
 
+- [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable).
+
 ## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
 
 - The latest version of `clonehero` now stores custom content in `~/.clonehero`. See the [migration instructions](https://clonehero.net/2022/11/29/v23-to-v1-migration-instructions.html). Typically, these content files would exist along side the binary, but the previous build used a wrapper script that would store them in `~/.config/unity3d/srylain Inc_/Clone Hero`.
 
+- `etcd` has been updated to 3.5, you will want to read the [3.3 to 3.4](https://etcd.io/docs/v3.5/upgrades/upgrade_3_4/) and [3.4 to 3.5](https://etcd.io/docs/v3.5/upgrades/upgrade_3_5/) upgrade guides
+
 ## Other Notable Changes {#sec-release-23.11-notable-changes}
 
+- The Cinnamon module now enables XDG desktop integration by default. If you are experiencing collisions related to xdg-desktop-portal-gtk you can safely remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your NixOS configuration.
+
 - A new option was added to the virtualisation module that enables specifying explicitly named network interfaces in QEMU VMs. The existing `virtualisation.vlans` is still supported for cases where the name of the network interface is irrelevant.
 
 - `services.nginx` gained a `defaultListen` option at server-level with support for PROXY protocol listeners, also `proxyProtocol` is now exposed in `services.nginx.virtualHosts.<name>.listen` option. It is now possible to run PROXY listeners and non-PROXY listeners at a server-level, see [#213510](https://github.com/NixOS/nixpkgs/pull/213510/) for more details.
diff --git a/nixos/lib/test-driver/test_driver/efi.py b/nixos/lib/test-driver/test_driver/efi.py
new file mode 100644
index 00000000000..05d5d85e395
--- /dev/null
+++ b/nixos/lib/test-driver/test_driver/efi.py
@@ -0,0 +1,31 @@
+from enum import IntEnum
+
+class EfiVariableAttributes(IntEnum):
+    NonVolatile = 0x01
+    BootServiceAccess = 0x02
+    RuntimeAccess = 0x04
+    HardwareErrorRecord = 0x08
+    AuthenticatedWriteAccess = 0x10
+    TimeBasedAuthenticatedWriteAccess = 0x20
+    AppendWrite = 0x40
+    EnhancedAuthenticatedAccess = 0x80
+
+class EfiVariable:
+    """
+        An EFI variable represented by its attributes and raw value in bytes.
+        Generally, the value is not encoded in UTF-8, but UCS-2 or UTF-16-LE.
+    """
+    attributes: EfiVariableAttributes
+    value: bytes
+
+    def __init__(self, value: bytes, attributes: bytes):
+        self.value = value
+        self.attributes = EfiVariableAttributes(attributes)
+
+    def value_as_null_terminated_string(self, encoding: str = 'utf-16-le'):
+        """
+            Most often, variables are encoded with a null-terminated \x00.
+            This function gives you the string in a default encoding of UTF-16-LE
+            stripped of the null terminator.
+        """
+        return self.value.decode(encoding).rstrip('\x00')
diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py
index 3673271798a..ec36c05cbbb 100644
--- a/nixos/lib/test-driver/test_driver/machine.py
+++ b/nixos/lib/test-driver/test_driver/machine.py
@@ -17,6 +17,7 @@ import tempfile
 import threading
 import time
 
+from test_driver.efi import EfiVariable
 from test_driver.logger import rootlog
 
 CHAR_TO_KEY = {
@@ -1034,6 +1035,33 @@ class Machine:
         """
         self.send_monitor_command(f"hostfwd_add tcp::{host_port}-:{guest_port}")
 
+    def running_under_uefi(self) -> bool:
+        """
+        Returns True if the current environment is running under UEFI, False otherwise.
+        This is achieved by inspecting by the existence of /sys/firmware/efi.
+        """
+        rc, _ = self.execute("test -d /sys/firmware/efi")
+        return (rc == 0)
+
+
+    def read_efi_variable_from_sysfs(self, guid: str, variable_name: str) -> EfiVariable | None:
+        """
+        Read an EFI variable located in efivars sysfs if available.
+        Returns None if the EFI variable does not exist.
+        Raises an assertion error if we are not running under an UEFI environment.
+        """
+        assert self.running_under_uefi(), "This machine is not detected under an UEFI environment"
+        rc, raw_attributes_and_value = self.execute(f"base64 /sys/firmware/efi/efivars/{variable_name}-{guid}")
+        if rc != 0: return None
+        # The return value is a string which is in reality a disguised bytes, we re-encode it properly
+        # using raw_unicode_escape keeping all the escapes properly.
+        # This is not guaranteed to work for all the cases but is good enough for UTF-8/UTF-16 usecases.
+        attributes_and_value = base64.b64decode(raw_attributes_and_value)
+        # First 4 bytes are attributes: https://www.kernel.org/doc/html/latest/filesystems/efivarfs.html
+        attributes = attributes_and_value[:4]
+        value = attributes_and_value[4:]
+        return EfiVariable(value=value, attributes=attributes)
+
     def block(self) -> None:
         """Make the machine unreachable by shutting down eth1 (the multicast
         interface used to talk to the other VMs).  We keep eth0 up so that
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 0efc948f402..10d5edce315 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -241,7 +241,6 @@
   ./programs/starship.nix
   ./programs/steam.nix
   ./programs/streamdeck-ui.nix
-  ./programs/sway.nix
   ./programs/sysdig.nix
   ./programs/system-config-printer.nix
   ./programs/systemtap.nix
@@ -256,7 +255,9 @@
   ./programs/usbtop.nix
   ./programs/vim.nix
   ./programs/wavemon.nix
-  ./programs/waybar.nix
+  ./programs/wayland/river.nix
+  ./programs/wayland/sway.nix
+  ./programs/wayland/waybar.nix
   ./programs/weylus.nix
   ./programs/wireshark.nix
   ./programs/xastir.nix
@@ -1310,7 +1311,6 @@
   ./services/x11/window-managers/default.nix
   ./services/x11/window-managers/fluxbox.nix
   ./services/x11/window-managers/icewm.nix
-  ./services/x11/window-managers/bspwm.nix
   ./services/x11/window-managers/katriawm.nix
   ./services/x11/window-managers/metacity.nix
   ./services/x11/window-managers/nimdow.nix
diff --git a/nixos/modules/programs/wayland/river.nix b/nixos/modules/programs/wayland/river.nix
new file mode 100644
index 00000000000..20a786ba3c6
--- /dev/null
+++ b/nixos/modules/programs/wayland/river.nix
@@ -0,0 +1,59 @@
+{
+  config,
+  pkgs,
+  lib,
+  ...
+}:
+with lib; let
+  cfg = config.programs.river;
+in {
+  options.programs.river = {
+    enable = mkEnableOption (lib.mdDoc "river, a dynamic tiling Wayland compositor");
+
+    package = mkOption {
+      type = with types; nullOr package;
+      default = pkgs.river;
+      defaultText = literalExpression "pkgs.river";
+      description = lib.mdDoc ''
+        River package to use.
+        Set to `null` to not add any River package to your path.
+        This should be done if you want to use the Home Manager River module to install River.
+      '';
+    };
+
+    extraPackages = mkOption {
+      type = with types; listOf package;
+      default = with pkgs; [
+        swaylock
+        foot
+        dmenu
+      ];
+      defaultText = literalExpression ''
+        with pkgs; [ swaylock foot dmenu ];
+      '';
+      example = literalExpression ''
+        with pkgs; [
+          termite rofi light
+        ]
+      '';
+      description = lib.mdDoc ''
+        Extra packages to be installed system wide. See
+        [Common X11 apps used on i3 with Wayland alternatives](https://github.com/swaywm/sway/wiki/i3-Migration-Guide#common-x11-apps-used-on-i3-with-wayland-alternatives)
+        for a list of useful software.
+      '';
+    };
+  };
+
+  config =
+    mkIf cfg.enable (mkMerge [
+      {
+        environment.systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+
+        # To make a river session available if a display manager like SDDM is enabled:
+        programs.xwayland.enable = mkDefault true;
+      }
+      (import ./wayland-session.nix { inherit lib pkgs; })
+    ]);
+
+  meta.maintainers = with lib.maintainers; [ GaetanLepage ];
+}
diff --git a/nixos/modules/programs/sway.nix b/nixos/modules/programs/wayland/sway.nix
index 3b2e69bd37c..c699c21bd10 100644
--- a/nixos/modules/programs/sway.nix
+++ b/nixos/modules/programs/wayland/sway.nix
@@ -123,41 +123,36 @@ in {
 
   };
 
-  config = mkIf cfg.enable {
-    assertions = [
+  config = mkIf cfg.enable
+    (mkMerge [
       {
-        assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
-        message = ''
-          The extraSessionCommands for Sway will not be run if
-          wrapperFeatures.base is disabled.
-        '';
-      }
-    ];
-    environment = {
-      systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
-      # Needed for the default wallpaper:
-      pathsToLink = optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
-      etc = {
-        "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
-          # Import the most important environment variables into the D-Bus and systemd
-          # user environments (e.g. required for screen sharing and Pinentry prompts):
-          exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
-        '';
-      } // optionalAttrs (cfg.package != null) {
-        "sway/config".source = mkOptionDefault "${cfg.package}/etc/sway/config";
-      };
-    };
-    security.polkit.enable = true;
-    security.pam.services.swaylock = {};
-    hardware.opengl.enable = mkDefault true;
-    fonts.enableDefaultFonts = mkDefault true;
-    programs.dconf.enable = mkDefault true;
-    # To make a Sway session available if a display manager like SDDM is enabled:
-    services.xserver.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ];
-    programs.xwayland.enable = mkDefault true;
-    # For screen sharing (this option only has an effect with xdg.portal.enable):
-    xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-wlr ];
-  };
+        assertions = [
+          {
+            assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
+            message = ''
+              The extraSessionCommands for Sway will not be run if
+              wrapperFeatures.base is disabled.
+            '';
+          }
+        ];
+        environment = {
+          systemPackages = optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
+          # Needed for the default wallpaper:
+          pathsToLink = optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
+          etc = {
+            "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
+              # Import the most important environment variables into the D-Bus and systemd
+              # user environments (e.g. required for screen sharing and Pinentry prompts):
+              exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
+            '';
+          } // optionalAttrs (cfg.package != null) {
+            "sway/config".source = mkOptionDefault "${cfg.package}/etc/sway/config";
+          };
+        };
+        # To make a Sway session available if a display manager like SDDM is enabled:
+        services.xserver.displayManager.sessionPackages = optionals (cfg.package != null) [ cfg.package ]; }
+      (import ./wayland-session.nix { inherit lib pkgs; })
+    ]);
 
   meta.maintainers = with lib.maintainers; [ primeos colemickens ];
 }
diff --git a/nixos/modules/programs/waybar.nix b/nixos/modules/programs/wayland/waybar.nix
index 2c49ae14081..2c49ae14081 100644
--- a/nixos/modules/programs/waybar.nix
+++ b/nixos/modules/programs/wayland/waybar.nix
diff --git a/nixos/modules/programs/wayland/wayland-session.nix b/nixos/modules/programs/wayland/wayland-session.nix
new file mode 100644
index 00000000000..3cbfef4d61d
--- /dev/null
+++ b/nixos/modules/programs/wayland/wayland-session.nix
@@ -0,0 +1,23 @@
+{ lib, pkgs, ... }: with lib; {
+    security = {
+      polkit.enable = true;
+      pam.services.swaylock = {};
+    };
+
+    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultFonts = mkDefault true;
+
+    programs = {
+      dconf.enable = mkDefault true;
+      xwayland.enable = mkDefault true;
+    };
+
+    xdg.portal = {
+      enable = mkDefault true;
+
+      extraPortals = [
+        # For screen sharing
+        pkgs.xdg-desktop-portal-wlr
+      ];
+    };
+}
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index 17a7cca917f..7bc7a949911 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -15,6 +15,8 @@ in {
       type = types.bool;
     };
 
+    package = mkPackageOptionMD pkgs "etcd" { };
+
     name = mkOption {
       description = lib.mdDoc "Etcd unique node name.";
       default = config.networking.hostName;
@@ -187,13 +189,13 @@ in {
 
       serviceConfig = {
         Type = "notify";
-        ExecStart = "${pkgs.etcd}/bin/etcd";
+        ExecStart = "${cfg.package}/bin/etcd";
         User = "etcd";
         LimitNOFILE = 40000;
       };
     };
 
-    environment.systemPackages = [ pkgs.etcd ];
+    environment.systemPackages = [ cfg.package ];
 
     users.users.etcd = {
       isSystemUser = true;
diff --git a/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixos/modules/services/x11/desktop-managers/cinnamon.nix
index 2d8addb0f10..9adbcec7f2f 100644
--- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix
+++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix
@@ -187,6 +187,15 @@ in
       xdg.mime.enable = true;
       xdg.icons.enable = true;
 
+      xdg.portal.enable = true;
+      xdg.portal.extraPortals = [
+        pkgs.xdg-desktop-portal-xapp
+        (pkgs.xdg-desktop-portal-gtk.override {
+          # Do not build portals that we already have.
+          buildPortalsInGnome = false;
+        })
+      ];
+
       # Override GSettings schemas
       environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
 
diff --git a/nixos/tests/etcd-cluster.nix b/nixos/tests/etcd-cluster.nix
index 97b6e63b273..c77c0dd73c2 100644
--- a/nixos/tests/etcd-cluster.nix
+++ b/nixos/tests/etcd-cluster.nix
@@ -53,7 +53,7 @@ import ./make-test-python.nix ({ pkgs, ... } : let
     [ v3_req ]
     basicConstraints = CA:FALSE
     keyUsage = digitalSignature, keyEncipherment
-    extendedKeyUsage = serverAuth
+    extendedKeyUsage = serverAuth, clientAuth
     subjectAltName = @alt_names
     [alt_names]
     DNS.1 = node1
@@ -86,10 +86,13 @@ import ./make-test-python.nix ({ pkgs, ... } : let
     };
 
     environment.variables = {
-      ETCDCTL_CERT_FILE = "${etcd_client_cert}";
-      ETCDCTL_KEY_FILE = "${etcd_client_key}";
-      ETCDCTL_CA_FILE = "${ca_pem}";
-      ETCDCTL_PEERS = "https://127.0.0.1:2379";
+      ETCD_CERT_FILE = "${etcd_client_cert}";
+      ETCD_KEY_FILE = "${etcd_client_key}";
+      ETCD_CA_FILE = "${ca_pem}";
+      ETCDCTL_ENDPOINTS = "https://127.0.0.1:2379";
+      ETCDCTL_CACERT = "${ca_pem}";
+      ETCDCTL_CERT = "${etcd_cert}";
+      ETCDCTL_KEY = "${etcd_key}";
     };
 
     networking.firewall.allowedTCPPorts = [ 2380 ];
@@ -134,21 +137,21 @@ in {
         node2.start()
         node1.wait_for_unit("etcd.service")
         node2.wait_for_unit("etcd.service")
-        node2.wait_until_succeeds("etcdctl cluster-health")
-        node1.succeed("etcdctl set /foo/bar 'Hello world'")
+        node2.wait_until_succeeds("etcdctl endpoint status")
+        node1.succeed("etcdctl put /foo/bar 'Hello world'")
         node2.succeed("etcdctl get /foo/bar | grep 'Hello world'")
 
     with subtest("should add another member"):
-        node1.wait_until_succeeds("etcdctl member add node3 https://node3:2380")
+        node1.wait_until_succeeds("etcdctl member add node3 --peer-urls=https://node3:2380")
         node3.start()
         node3.wait_for_unit("etcd.service")
         node3.wait_until_succeeds("etcdctl member list | grep 'node3'")
-        node3.succeed("etcdctl cluster-health")
+        node3.succeed("etcdctl endpoint status")
 
     with subtest("should survive member crash"):
         node3.crash()
-        node1.succeed("etcdctl cluster-health")
-        node1.succeed("etcdctl set /foo/bar 'Hello degraded world'")
+        node1.succeed("etcdctl endpoint status")
+        node1.succeed("etcdctl put /foo/bar 'Hello degraded world'")
         node1.succeed("etcdctl get /foo/bar | grep 'Hello degraded world'")
   '';
 })
diff --git a/nixos/tests/etcd.nix b/nixos/tests/etcd.nix
index 702bbb668f5..79857778ae1 100644
--- a/nixos/tests/etcd.nix
+++ b/nixos/tests/etcd.nix
@@ -19,7 +19,7 @@ import ./make-test-python.nix ({ pkgs, ... } : {
         node.wait_for_unit("etcd.service")
 
     with subtest("should write and read some values to etcd"):
-        node.succeed("etcdctl set /foo/bar 'Hello world'")
+        node.succeed("etcdctl put /foo/bar 'Hello world'")
         node.succeed("etcdctl get /foo/bar | grep 'Hello world'")
   '';
 })