Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions nixos/doc/manual/release-notes/rl-2605.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

- [Dawarich](https://dawarich.app/), a self-hostable location history tracker. Available as [services.dawarich](#opt-services.dawarich.enable).

- [Howdy](https://github.com/boltgolt/howdy), a Windows Hello™ style facial authentication program for Linux.

- [linux-enable-ir-emitter](https://github.com/EmixamPP/linux-enable-ir-emitter), a tool used to set up IR cameras, used with Howdy.

- [udp-over-tcp](https://github.com/mullvad/udp-over-tcp), a tunnel for proxying UDP traffic over a TCP stream. Available as `services.udp-over-tcp`.

- [Komodo Periphery](https://github.com/moghtech/komodo), a multi-server Docker and Git deployment agent by Komodo. Available as [services.komodo-periphery](#opt-services.komodo-periphery.enable).
Expand Down
2 changes: 2 additions & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@
./services/misc/languagetool.nix
./services/misc/leaps.nix
./services/misc/lifecycled.nix
./services/misc/linux-enable-ir-emitter.nix
./services/misc/litellm.nix
./services/misc/llama-cpp.nix
./services/misc/local-content-share.nix
Expand Down Expand Up @@ -1488,6 +1489,7 @@
./services/security/hockeypuck.nix
./services/security/hologram-agent.nix
./services/security/hologram-server.nix
./services/security/howdy
./services/security/infnoise.nix
./services/security/intune.nix
./services/security/jitterentropy-rngd.nix
Expand Down
50 changes: 50 additions & 0 deletions nixos/modules/security/pam.nix
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,28 @@ let
'';
};

howdy = {
enable = lib.mkOption {
default = config.security.pam.howdy.enable;
defaultText = lib.literalExpression "config.security.pam.howdy.enable";
type = lib.types.bool;
description = ''
Whether to enable the Howdy PAM module.

If set, users can be authenticated using Howdy, the Windows
Hello™-style facial authentication service.
'';
};
control = lib.mkOption {
default = config.security.pam.howdy.control;
defaultText = lib.literalExpression "config.security.pam.howdy.control";
type = lib.types.str;
description = ''
This option sets the PAM "control" used for this module.
'';
};
};

oathAuth = lib.mkOption {
default = config.security.pam.oath.enable;
defaultText = lib.literalExpression "config.security.pam.oath.enable";
Expand Down Expand Up @@ -951,6 +973,12 @@ let
control = "sufficient";
modulePath = "${config.services.fprintd.package}/lib/security/pam_fprintd.so";
}
{
name = "howdy";
enable = cfg.howdy.enable;
control = cfg.howdy.control;
modulePath = "${config.services.howdy.package}/lib/security/pam_howdy.so";
}
]
++
# Modules in this block require having the password set in PAM_AUTHTOK.
Expand Down Expand Up @@ -1797,6 +1825,28 @@ in
};
};

security.pam.howdy = {
Comment thread
fufexan marked this conversation as resolved.
enable = lib.mkOption {
default = config.services.howdy.enable;
defaultText = lib.literalExpression "config.services.howdy.enable";
type = lib.types.bool;
description = ''
Whether to enable the Howdy PAM module.

If set, users can be authenticated using Howdy, the Windows
Hello™-style facial authentication service.
'';
};
control = lib.mkOption {
default = config.services.howdy.control;
defaultText = lib.literalExpression "config.services.howdy.control";
type = lib.types.str;
description = ''
This option sets the PAM "control" used for this module.
'';
};
};

security.pam.krb5 = {
enable = lib.mkOption {
default = config.security.krb5.enable;
Expand Down
71 changes: 71 additions & 0 deletions nixos/modules/services/misc/linux-enable-ir-emitter.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.linux-enable-ir-emitter;
in
{
options = {
services.linux-enable-ir-emitter = {
enable = lib.mkEnableOption "" // {
description = ''
Whether to enable IR emitter hardware. Designed to be used with the
Howdy facial authentication. After enabling the service, configure
the emitter with `sudo linux-enable-ir-emitter configure`.
'';
};

package = lib.mkPackageOption pkgs "linux-enable-ir-emitter" { } // {
description = ''
Package to use for the Linux Enable IR Emitter service.
'';
};

device = lib.mkOption {
type = lib.types.str;
default = "video2";
description = ''
IR camera device to depend on. For example, for `/dev/video2`
the value would be `video2`. Find this with the command
{command}`realpath /dev/v4l/by-path/<generated-driver-name>`.
'';
};
};
};

config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];

# https://github.com/EmixamPP/linux-enable-ir-emitter/blob/7e3a6527ef2efccabaeefc5a93c792628325a8db/sources/systemd/linux-enable-ir-emitter.service
systemd.services.linux-enable-ir-emitter =
let
targets = [
"suspend.target"
"sleep.target"
"hybrid-sleep.target"
"hibernate.target"
"suspend-then-hibernate.target"
];
in
{
description = "Enable the infrared emitter";
# Added to match
# https://github.com/EmixamPP/linux-enable-ir-emitter/blob/6.1.2/boot_service/systemd/linux-enable-ir-emitter.service
# Prevents the program fail to detect the IR camera until a service
# restart.
preStart = ''
${pkgs.kmod}/bin/modprobe uvcvideo
sleep 1
Comment thread
fufexan marked this conversation as resolved.
'';
Comment thread
fufexan marked this conversation as resolved.
script = "${lib.getExe cfg.package} --verbose run";
serviceConfig.StateDirectory = "linux-enable-ir-emitter";
serviceConfig.LogsDirectory = "linux-enable-ir-emitter";

wantedBy = targets ++ [ "multi-user.target" ];
after = targets ++ [ "dev-${cfg.device}.device" ];
};
};
}
122 changes: 122 additions & 0 deletions nixos/modules/services/security/howdy/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.howdy;
settingsType = pkgs.formats.ini { };

default_config = {
core = {
detection_notice = false;
timeout_notice = true;
no_confirmation = false;
suppress_unknown = false;
abort_if_ssh = true;
abort_if_lid_closed = true;
disabled = false;
use_cnn = false;
workaround = "off";
};

video = {
certainty = 3.5;
timeout = 4;
device_path = "/dev/video2";
warn_no_device = true;
max_height = 320;
frame_width = -1;
frame_height = -1;
dark_threshold = 60;
recording_plugin = "opencv";
device_format = "v4l2";
force_mjpeg = false;
exposure = -1;
device_fps = -1;
rotate = 0;
};

snapshots = {
save_failed = false;
save_successful = false;
};

rubberstamps = {
enabled = false;
stamp_rules = "nod 5s failsafe min_distance=12";
};

debug = {
end_report = false;
verbose_stamps = false;
gtk_stdout = false;
};
};
in
{
options = {
services.howdy = {
enable = lib.mkEnableOption "" // {
description = ''
Whether to enable Howdy and its PAM module for face recognition. See
`services.linux-enable-ir-emitter` for enabling the IR emitter support.

::: {.caution}
Howdy is not a safe alternative to unlocking with your password. It
can be fooled using a well-printed photo.

Do **not** use it as the sole authentication method for your system.
:::
Comment on lines +66 to +71
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we reconcile this warning with the PAM rule that hardcodes sufficient as the control? If we want other authentication modes to remain enabled, then we should use requisite or required for Howdy.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW @fufexan this comment seems still unresolved. TBH I've never dealt with pam in NixOS so I'm not sure how to help.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I said I'd come back to this and forgot. I'll take a look.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a config option in the howdy module? It would allow choosing which control type to set.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @Majiir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you could add a control option. Look at security.pam.u2f.control as an example. I suggest making required the default, and add the option under pamOpts (where the howdyAuth option is). So you'd have security.pam.services.<service>.howdy.enable and security.pam.services.<service>.howdy.control. If you want, you could default the control option based on an option in services.howdy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the latest commit address this properly?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that addresses the control issue. But the latest commit created another issue which I've added a comment on in my review here.


::: {.note}
By default, the {option}`config.services.howdy.control` option is set
to `"required"`, meaning it will act as a second-factor authentication
in most services. To change this, set the option to `"sufficient"`.
:::
'';
};

package = lib.mkPackageOption pkgs "howdy" { };

control = lib.mkOption {
type = lib.types.str;
default = "required";
description = ''
PAM control flag to use for Howdy.

Sets the {option}`security.pam.howdy.control` option.

Refer to {manpage}`pam.conf(5)` for options.
'';
};

settings = lib.mkOption {
inherit (settingsType) type;
default = default_config;
description = ''
Howdy configuration file. Refer to
<https://github.com/boltgolt/howdy/blob/d3ab99382f88f043d15f15c1450ab69433892a1c/howdy/src/config.ini>
for options.
'';
};
};
};

config = lib.mkMerge [
(lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
environment.etc."howdy/config.ini".source = settingsType.generate "howdy-config.ini" cfg.settings;
assertions = [
{
assertion = !(builtins.elem "v4l2loopback" config.boot.kernelModules);
message = "Adding 'v4l2loopback' to `boot.kernelModules` causes Howdy to no longer work. Consider adding 'v4l2loopback' to `boot.extraModulePackages` instead.";
}
];
})
{
services.howdy.settings = lib.mapAttrsRecursive (name: lib.mkDefault) default_config;
}
];
}
Loading
Loading