1{ config, lib, pkgs, ... }:
2
3let
4 cfg = config.boot.initrd.unl0kr;
5in
6{
7 options.boot.initrd.unl0kr = {
8 enable = lib.mkEnableOption "unl0kr in initrd" // {
9 description = ''
10 Whether to enable the unl0kr on-screen keyboard in initrd to unlock LUKS.
11 '';
12 };
13 };
14
15 config = lib.mkIf cfg.enable {
16 meta.maintainers = with lib.maintainers; [ tomfitzhenry ];
17 assertions = [
18 {
19 assertion = cfg.enable -> config.boot.initrd.systemd.enable;
20 message = "boot.initrd.unl0kr is only supported with boot.initrd.systemd.";
21 }
22 ];
23
24 boot.initrd.systemd = {
25 storePaths = with pkgs; [
26 "${pkgs.gnugrep}/bin/grep"
27 libinput
28 xkeyboard_config
29 "${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password"
30 "${pkgs.unl0kr}/bin/unl0kr"
31 ];
32 services = {
33 unl0kr-ask-password = {
34 description = "Forward Password Requests to unl0kr";
35 conflicts = [
36 "emergency.service"
37 "initrd-switch-root.target"
38 "shutdown.target"
39 ];
40 unitConfig.DefaultDependencies = false;
41 after = [
42 "systemd-vconsole-setup.service"
43 "udev.service"
44 ];
45 before = [
46 "shutdown.target"
47 ];
48 script = ''
49 # This script acts as a Password Agent: https://systemd.io/PASSWORD_AGENTS/
50
51 DIR=/run/systemd/ask-password/
52 # If a user has multiple encrypted disks, the requests might come in different times,
53 # so make sure to answer as many requests as we can. Once boot succeeds, other
54 # password agents will be responsible for watching for requests.
55 while [ -d $DIR ] && [ "$(ls -A $DIR/ask.*)" ];
56 do
57 for file in `ls $DIR/ask.*`; do
58 socket="$(cat "$file" | ${pkgs.gnugrep}/bin/grep "Socket=" | cut -d= -f2)"
59 ${pkgs.unl0kr}/bin/unl0kr | ${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password 1 "$socket"
60 done
61 done
62 '';
63 };
64 };
65
66 paths = {
67 unl0kr-ask-password = {
68 description = "Forward Password Requests to unl0kr";
69 conflicts = [
70 "emergency.service"
71 "initrd-switch-root.target"
72 "shutdown.target"
73 ];
74 unitConfig.DefaultDependencies = false;
75 before = [
76 "shutdown.target"
77 "paths.target"
78 "cryptsetup.target"
79 ];
80 wantedBy = [ "sysinit.target" ];
81 pathConfig = {
82 DirectoryNotEmpty = "/run/systemd/ask-password";
83 MakeDirectory = true;
84 };
85 };
86 };
87 };
88 };
89}