nixos/systemd-lock-handler: init

Changed files
+139 -1
nixos
pkgs
by-name
sy
systemd-lock-handler
+2
nixos/doc/manual/release-notes/rl-2405.section.md
···
- [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. -->
+1
nixos/modules/module-list.nix
···
./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
+47
nixos/modules/services/system/systemd-lock-handler.md
···
+
# 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.
+27
nixos/modules/services/system/systemd-lock-handler.nix
···
+
{ 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;
+
};
+
}
+1
nixos/tests/all-tests.nix
···
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 {};
+56
nixos/tests/systemd-lock-handler.nix
···
+
{ 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()
+
'';
+
}
+5 -1
pkgs/by-name/sy/systemd-lock-handler/package.nix
···
, fetchFromSourcehut
, buildGoModule
, nix-update-script
+
, nixosTests
}:
buildGoModule rec {
···
vendorHash = "sha256-dWzojV3tDA5lLdpAQNC9NaADGyvV7dNOS3x8mfgNNtA=";
-
passthru.updateScript = nix-update-script { };
+
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`