diff options
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2405.section.md | 2 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/system/systemd-lock-handler.md | 47 | ||||
-rw-r--r-- | nixos/modules/services/system/systemd-lock-handler.nix | 27 | ||||
-rw-r--r-- | nixos/tests/all-tests.nix | 1 | ||||
-rw-r--r-- | nixos/tests/systemd-lock-handler.nix | 56 | ||||
-rw-r--r-- | pkgs/by-name/sy/systemd-lock-handler/package.nix | 51 |
7 files changed, 185 insertions, 0 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index 00d221a60dde0..9c5813904b77e 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -67,6 +67,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m - [RustDesk](https://rustdesk.com), a full-featured open source remote control alternative for self-hosting and security with minimal configuration. Alternative to TeamViewer. +- [systemd-lock-handler](https://git.sr.ht/~whynothugo/systemd-lock-handler/), a bridge between logind D-Bus events and systemd targets. Available as [services.systemd-lock-handler.enable](#opt-services.systemd-lock-handler.enable). + ## Backward Incompatibilities {#sec-release-24.05-incompatibilities} <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 8d02330655603..71498e397cb65 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1236,6 +1236,7 @@ ./services/system/saslauthd.nix ./services/system/self-deploy.nix ./services/system/systembus-notify.nix + ./services/system/systemd-lock-handler.nix ./services/system/uptimed.nix ./services/system/zram-generator.nix ./services/torrent/deluge.nix diff --git a/nixos/modules/services/system/systemd-lock-handler.md b/nixos/modules/services/system/systemd-lock-handler.md new file mode 100644 index 0000000000000..ac9ee00ae4bcc --- /dev/null +++ b/nixos/modules/services/system/systemd-lock-handler.md @@ -0,0 +1,47 @@ +# systemd-lock-handler {#module-services-systemd-lock-handler} + +The `systemd-lock-handler` module provides a service that bridges +D-Bus events from `logind` to user-level systemd targets: + + - `lock.target` started by `loginctl lock-session`, + - `unlock.target` started by `loginctl unlock-session` and + - `sleep.target` started by `systemctl suspend`. + +You can create a user service that starts with any of these targets. + +For example, to create a service for `swaylock`: + +```nix +{ + services.systemd-lock-handler.enable = true; + + systemd.user.services.swaylock = { + description = "Screen locker for Wayland"; + documentation = ["man:swaylock(1)"]; + + # If swaylock exits cleanly, unlock the session: + onSuccess = ["unlock.target"]; + + # When lock.target is stopped, stops this too: + partOf = ["lock.target"]; + + # Delay lock.target until this service is ready: + before = ["lock.target"]; + wantedBy = ["lock.target"]; + + serviceConfig = { + # systemd will consider this service started when swaylock forks... + Type = "forking"; + + # ... and swaylock will fork only after it has locked the screen. + ExecStart = "${lib.getExe pkgs.swaylock} -f"; + + # If swaylock crashes, always restart it immediately: + Restart = "on-failure"; + RestartSec = 0; + }; + }; +} +``` + +See [upstream documentation](https://sr.ht/~whynothugo/systemd-lock-handler) for more information. diff --git a/nixos/modules/services/system/systemd-lock-handler.nix b/nixos/modules/services/system/systemd-lock-handler.nix new file mode 100644 index 0000000000000..1ecb13b75bb3e --- /dev/null +++ b/nixos/modules/services/system/systemd-lock-handler.nix @@ -0,0 +1,27 @@ +{ config +, pkgs +, lib +, ... +}: +let + cfg = config.services.systemd-lock-handler; + inherit (lib) mkIf mkEnableOption mkPackageOption; +in +{ + options.services.systemd-lock-handler = { + enable = mkEnableOption (lib.mdDoc "systemd-lock-handler"); + package = mkPackageOption pkgs "systemd-lock-handler" { }; + }; + + config = mkIf cfg.enable { + systemd.packages = [ cfg.package ]; + + # https://github.com/NixOS/nixpkgs/issues/81138 + systemd.user.services.systemd-lock-handler.wantedBy = [ "default.target" ]; + }; + + meta = { + maintainers = with lib.maintainers; [ liff ]; + doc = ./systemd-lock-handler.md; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 3f9dd173d3bf4..81bd36cf0e345 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -856,6 +856,7 @@ in { systemd-journal = handleTest ./systemd-journal.nix {}; systemd-journal-gateway = handleTest ./systemd-journal-gateway.nix {}; systemd-journal-upload = handleTest ./systemd-journal-upload.nix {}; + systemd-lock-handler = runTestOn ["aarch64-linux" "x86_64-linux"] ./systemd-lock-handler.nix; systemd-machinectl = handleTest ./systemd-machinectl.nix {}; systemd-networkd = handleTest ./systemd-networkd.nix {}; systemd-networkd-dhcpserver = handleTest ./systemd-networkd-dhcpserver.nix {}; diff --git a/nixos/tests/systemd-lock-handler.nix b/nixos/tests/systemd-lock-handler.nix new file mode 100644 index 0000000000000..d6fb8f5459004 --- /dev/null +++ b/nixos/tests/systemd-lock-handler.nix @@ -0,0 +1,56 @@ +{ lib, ... }: { + name = "systemd-lock-handler"; + + meta.maintainers = with lib.maintainers; [ liff ]; + + enableOCR = true; + + nodes.machine = { config, pkgs, lib, ... }: + let + touch = "${lib.getBin pkgs.coreutils}/bin/touch"; + in + { + imports = [ common/wayland-cage.nix ]; + + services.systemd-lock-handler.enable = true; + + systemd.user.services = { + test-lock = { + partOf = [ "lock.target" ]; + onSuccess = [ "unlock.target" ]; + before = [ "lock.target" ]; + wantedBy = [ "lock.target" ]; + serviceConfig.ExecStart = "${touch} /tmp/lock.target.activated"; + }; + test-unlock = { + partOf = [ "unlock.target" ]; + after = [ "unlock.target" ]; + wantedBy = [ "unlock.target" ]; + serviceConfig.ExecStart = "${touch} /tmp/unlock.target.activated"; + }; + test-sleep = { + partOf = [ "sleep.target" ]; + before = [ "sleep.target" ]; + wantedBy = [ "sleep.target" ]; + serviceConfig.ExecStart = "${touch} /tmp/sleep.target.activated"; + }; + }; + }; + + testScript = '' + machine.wait_for_unit('graphical.target') + machine.wait_for_text('alice@machine') + + machine.send_chars('loginctl lock-session\n') + machine.wait_for_file('/tmp/lock.target.activated') + machine.wait_for_file('/tmp/unlock.target.activated') + + machine.send_chars('systemctl suspend\n') + # wait_for_file won’t complete before the machine is asleep, + # so we’ll watch the log instead. + machine.wait_for_console_text('Started test-sleep.service.') + + # The VM is asleep, regular shutdown won’t work. + machine.crash() + ''; +} diff --git a/pkgs/by-name/sy/systemd-lock-handler/package.nix b/pkgs/by-name/sy/systemd-lock-handler/package.nix new file mode 100644 index 0000000000000..04c52dd2df0a0 --- /dev/null +++ b/pkgs/by-name/sy/systemd-lock-handler/package.nix @@ -0,0 +1,51 @@ +{ lib +, fetchFromSourcehut +, buildGoModule +, nix-update-script +, nixosTests +}: + +buildGoModule rec { + pname = "systemd-lock-handler"; + version = "2.4.2"; + + src = fetchFromSourcehut { + owner = "~whynothugo"; + repo = "systemd-lock-handler"; + rev = "v${version}"; + hash = "sha256-sTVAabwWtyvHuDp/+8FKNbfej1x/egoa9z1jLIMJuBg="; + }; + + vendorHash = "sha256-dWzojV3tDA5lLdpAQNC9NaADGyvV7dNOS3x8mfgNNtA="; + + passthru = { + updateScript = nix-update-script { }; + tests = nixosTests.systemd-lock-handler; + }; + + # The Makefile expects to find the binary in the source root. Make + # the one built by `buildGoModule` available so that `make install` + # doesn’t try to build it again. + postBuild = '' + cp -a $GOPATH/bin/* . + ''; + + installPhase = '' + runHook preInstall + + substituteInPlace systemd-lock-handler.service \ + --replace /usr/lib/ $out/lib/ + + make install DESTDIR= PREFIX=$out + + runHook postInstall + ''; + + meta = with lib; { + homepage = "https://git.sr.ht/~whynothugo/systemd-lock-handler"; + description = "Translates systemd-system lock/sleep signals into systemd-user target activations"; + license = licenses.isc; + maintainers = with maintainers; [ liff ]; + platforms = platforms.linux; + }; +} |