-
Notifications
You must be signed in to change notification settings - Fork 7
services/turnstiled: init #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4763af1
6f64e18
0baee21
d6520e4
2584e42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # Turnstile | ||
|
|
||
| An experimental module for | ||
| [turnstile](https://github.com/chimera-linux/turnstile). | ||
|
|
||
| Turnstile is a session/login tracker that runs a user level dinit/runit instance | ||
| when a user logs in and closes is safely when they log out. | ||
|
|
||
| This module is subject to extreme changes at any point. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,209 @@ | ||||||||||||||||||||
| { | ||||||||||||||||||||
| config, | ||||||||||||||||||||
| pkgs, | ||||||||||||||||||||
| lib, | ||||||||||||||||||||
| ... | ||||||||||||||||||||
| }: | ||||||||||||||||||||
| let | ||||||||||||||||||||
| cfg = config.services.turnstile; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| package = pkgs.callPackage ./package.nix { | ||||||||||||||||||||
| graphicalMonitor = cfg.dinit.settings.enableGraphicalMonitor; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| in | ||||||||||||||||||||
| { | ||||||||||||||||||||
| options.services.turnstile = { | ||||||||||||||||||||
| enable = lib.mkOption { | ||||||||||||||||||||
| type = lib.types.bool; | ||||||||||||||||||||
| default = false; | ||||||||||||||||||||
| description = '' | ||||||||||||||||||||
| Whether to enable [turnstilel](${cfg.package.meta.homepage}). | ||||||||||||||||||||
| ''; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| package = lib.mkOption { | ||||||||||||||||||||
| type = lib.types.package; | ||||||||||||||||||||
| default = package; | ||||||||||||||||||||
| description = '' | ||||||||||||||||||||
| The package to use for `turnstile`. | ||||||||||||||||||||
| ''; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| systemBootDir = lib.mkOption { | ||||||||||||||||||||
| type = lib.types.path; | ||||||||||||||||||||
| default = "/usr/lib/dinit.d/user/boot.d"; | ||||||||||||||||||||
| description = "Location of boot services used for all users"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| settings = with lib; { | ||||||||||||||||||||
| debug = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "no"; | ||||||||||||||||||||
| description = "Whether or not to enable debug output in turnstile"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| backend = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "dinit" | ||||||||||||||||||||
| "runit" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "dinit"; | ||||||||||||||||||||
| description = "`runit` is not currently supported, but changing this option may break things"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| debug_stderr = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "no"; | ||||||||||||||||||||
| description = "Whether or not to print debug to stderr in addition to stdout"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| linger = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "no"; | ||||||||||||||||||||
| description = "Whether or not the service manager should linger after user logout. Requires ${cfg.settings.manage_rundir} to be enabled"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| rundir_path = mkOption { | ||||||||||||||||||||
| type = types.str; | ||||||||||||||||||||
| default = "/run/user/%u"; | ||||||||||||||||||||
| description = "Where the rundir is for the user. See [turnstile](${cfg.package.meta.homepage}) documentation for available options"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| manage_rundir = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "no"; | ||||||||||||||||||||
| description = "Whether or not `turnstile` should manage the runtime directory"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| }; | ||||||||||||||||||||
| export_dbus_address = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "yes"; | ||||||||||||||||||||
| description = "Whether or not to export the D-Bus session address to the environment of the service manager"; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| login_timeout = mkOption { | ||||||||||||||||||||
| type = types.ints.unsigned; | ||||||||||||||||||||
| default = 60; | ||||||||||||||||||||
| description = "How long the service manager waits on initial processes (in seconds) before giving up."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| root_session = mkOption { | ||||||||||||||||||||
| type = types.enum [ | ||||||||||||||||||||
| "yes" | ||||||||||||||||||||
| "no" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
| default = "no"; | ||||||||||||||||||||
| description = "Whether or not `turnstile` acts for the root user."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| dinit = with lib; { | ||||||||||||||||||||
| enable = mkOption { | ||||||||||||||||||||
| type = types.bool; | ||||||||||||||||||||
| default = true; | ||||||||||||||||||||
| description = "Whether or not to use the dinit backend for `turnstile`."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| settings = with types; { | ||||||||||||||||||||
| # TODO: make this accept a str or a list of strings | ||||||||||||||||||||
| service_dir = mkOption { | ||||||||||||||||||||
| type = str; | ||||||||||||||||||||
| default = "$HOME/.config/dinit.d"; | ||||||||||||||||||||
| description = "Users service dir for `turnstile`'s `dinit` backend. This should include a way to differentiate per user unless all users have identical services."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| boot_dir = mkOption { | ||||||||||||||||||||
| type = types.str; | ||||||||||||||||||||
| default = "${cfg.dinit.settings.service_dir}/boot.d"; | ||||||||||||||||||||
| description = "Users service boot dir for `turnstile`'s `dinit` backend. This should include a way to differentiate per user unless all users have identical services."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| system_boot_dir = mkOption { | ||||||||||||||||||||
| type = types.path; | ||||||||||||||||||||
| default = "/usr/lib/dinit.d/user/boot.d"; | ||||||||||||||||||||
| description = "Systems service boot dir for `turnstile`'s `dinit` backend."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| enableGraphicalMonitor = mkOption { | ||||||||||||||||||||
| type = types.bool; | ||||||||||||||||||||
| default = false; | ||||||||||||||||||||
| description = "Whether or not to monitor environment changes to DISPLAY and WAYLAND_DISPLAY variables. Currently requires manually adding `dinitctl setenv VAR=$VAR`to any startup scripts for your graphical environment to function."; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| config = lib.mkIf cfg.enable { | ||||||||||||||||||||
| environment.systemPackages = [ | ||||||||||||||||||||
| cfg.package | ||||||||||||||||||||
| ] | ||||||||||||||||||||
| ++ lib.lists.optional cfg.dinit.enable (lib.lowPrio pkgs.dinit); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| finit.tmpfiles.rules = [ | ||||||||||||||||||||
| "d ${cfg.dinit.settings.system_boot_dir} 0777" | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| environment.etc = { | ||||||||||||||||||||
| "turnstile/turnstiled.conf".source = | ||||||||||||||||||||
| (pkgs.formats.keyValue { }).generate "turnstiled.conf" | ||||||||||||||||||||
| cfg.settings; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| "turnstile/backend/dinit.conf".text = '' | ||||||||||||||||||||
| boot_dir="${cfg.dinit.settings.boot_dir}" | ||||||||||||||||||||
| system_boot_dir="${cfg.dinit.settings.system_boot_dir}" | ||||||||||||||||||||
| services_dir1="${cfg.dinit.settings.service_dir}" | ||||||||||||||||||||
| services_dir2="/etc/dinit.d/user" | ||||||||||||||||||||
| services_dir3="/usr/local/lib/dinit.d/user" | ||||||||||||||||||||
| services_dir4="/usr/lib/dinit.d/user" | ||||||||||||||||||||
| ''; | ||||||||||||||||||||
|
Comment on lines
+159
to
+166
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
see comments above about adding
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving unresolved because I think I want to change the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as much as i don't like opinionated modules... yes, that is so so so much better 😅 please 🙇♂️ |
||||||||||||||||||||
|
|
||||||||||||||||||||
| "pam.d/turnstiled".text = '' | ||||||||||||||||||||
| auth sufficient pam_rootok.so | ||||||||||||||||||||
| session optional pam_keyinit.so force revoke | ||||||||||||||||||||
| session optional pam_umask.so usergroups umask=022 | ||||||||||||||||||||
| -session optional pam_elogind.so | ||||||||||||||||||||
| session required pam_env.so conffile=/etc/security/pam_env.conf readenv=1 # env (order 10100) | ||||||||||||||||||||
| session required ${cfg.package}/pam/pam_turnstile.so turnstiled | ||||||||||||||||||||
| session required pam_limits.so | ||||||||||||||||||||
| ''; | ||||||||||||||||||||
|
Comment on lines
+168
to
+176
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can move this under
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have done this from the start... changed it. |
||||||||||||||||||||
| }; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| security.pam.services = lib.mkMerge [ | ||||||||||||||||||||
| { | ||||||||||||||||||||
| login.text = lib.mkAfter "session optional ${cfg.package}/pam/pam_turnstile.so"; | ||||||||||||||||||||
| turnstiled.text = '' | ||||||||||||||||||||
| auth sufficient pam_rootok.so | ||||||||||||||||||||
| session optional pam_keyinit.so force revoke | ||||||||||||||||||||
| session optional pam_umask.so usergroups umask=022 | ||||||||||||||||||||
| -session optional pam_elogind.so | ||||||||||||||||||||
| session required pam_env.so conffile=/etc/security/pam_env.conf readenv=1 # env (order 10100) | ||||||||||||||||||||
| session required ${cfg.package}/pam/pam_turnstile.so turnstiled | ||||||||||||||||||||
| session required pam_limits.so | ||||||||||||||||||||
| ''; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| ]; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| finit.services.turnstiled = { | ||||||||||||||||||||
| description = "turnstiled, a user-service manager manager"; | ||||||||||||||||||||
| command = "${cfg.package}/bin/turnstiled"; | ||||||||||||||||||||
| conditions = "service/syslogd/ready"; | ||||||||||||||||||||
| log = true; | ||||||||||||||||||||
| pid = "/run/turnstiled.pid"; | ||||||||||||||||||||
| path = | ||||||||||||||||||||
| with pkgs; | ||||||||||||||||||||
| [ | ||||||||||||||||||||
| cfg.package | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are there multiple programs under |
||||||||||||||||||||
| config.programs.coreutils.package | ||||||||||||||||||||
| ] | ||||||||||||||||||||
| ++ lib.lists.optional cfg.dinit.enable dinit; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| }; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| { | ||
| lib, | ||
| stdenv, | ||
| fetchFromGitHub, | ||
|
aanderse marked this conversation as resolved.
|
||
| pkg-config, | ||
| scdoc, | ||
| meson, | ||
| ninja, | ||
| pam, | ||
| dinit, | ||
| graphicalMonitor ? true, | ||
| }: | ||
|
|
||
| stdenv.mkDerivation (finalAttrs: { | ||
| pname = "turnstile"; | ||
| version = "v0.1.11"; | ||
|
|
||
| src = fetchFromGitHub { | ||
| owner = "chimera-linux"; | ||
| repo = "turnstile"; | ||
| rev = "${finalAttrs.version}"; | ||
| sha256 = "sha256-94J+w0RHxzw7wS70LcpEzMvgevAqAwl0EtiANUmdRYU="; | ||
| }; | ||
|
|
||
| buildInputs = [ | ||
| pkg-config | ||
| scdoc | ||
| meson | ||
| ninja | ||
| pam | ||
|
aanderse marked this conversation as resolved.
|
||
| dinit | ||
| ]; | ||
|
|
||
| # nativeBuildInputs = [ | ||
| # dinit | ||
| # ]; | ||
|
|
||
| postPatch = lib.strings.concatStrings [ | ||
| (lib.strings.optionalString graphicalMonitor '' | ||
| substituteInPlace backend/dinit \ | ||
| --replace-fail '/usr/bin/dinit-monitor' '${lib.getExe' dinit "dinit-monitor"}' | ||
| '') | ||
|
|
||
| '' | ||
| substituteInPlace meson.build \ | ||
| --replace-fail "get_option('prefix'), get_option('sysconfdir'), 'turnstile'" "'/etc', 'turnstile'" | ||
| '' | ||
| ]; | ||
|
|
||
| mesonFlags = [ | ||
| "-Ddefault_backend=dinit" | ||
| "-Ddinit=enabled" | ||
| "-Dstatedir=/var/lib/turnstiled" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't that already the value? if not, sounds like we need to modify |
||
| "-Dpam_moddir=./pam" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is that right? 🤔 |
||
| ]; | ||
|
|
||
| patches = lib.lists.optional (!graphicalMonitor) (./remove_graphical_monitor.diff); | ||
|
|
||
|
aanderse marked this conversation as resolved.
|
||
| meta = with lib; { | ||
| homepage = "https://github.com/chimera-linux/turnstile"; | ||
| description = "This program waits for user logins and then runs the associated user-service manager"; | ||
| license = licenses.bsd2; | ||
| maintainers = with maintainers; [ vitrial ]; | ||
| platforms = platforms.linux; | ||
| mainProgram = "turnstiled"; | ||
| }; | ||
|
|
||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| diff --git a/backend/dinit b/backend/dinit | ||
| index 7bacaac..065d14a 100644 | ||
| --- a/backend/dinit | ||
| +++ b/backend/dinit | ||
| @@ -136,7 +136,7 @@ cat << EOF > "${DINIT_DIR}/graphical.monitor" | ||
| type = process | ||
| depends-on = login.target | ||
| options = pass-cs-fd | ||
| -command = /usr/bin/dinit-monitor -E -c "$0 graphical-notify" WAYLAND_DISPLAY DISPLAY | ||
| +command = /run/current-system/sw/bin/dinit-monitor -E -c "$0 graphical-notify" WAYLAND_DISPLAY DISPLAY | ||
| EOF | ||
|
|
||
| # this is needed for login to proceed | ||
| diff --git a/meson.build b/meson.build | ||
| index aa07c9c..fdf89fa 100644 | ||
| --- a/meson.build | ||
| +++ b/meson.build | ||
| @@ -28,7 +28,7 @@ have_runit = get_option('runit').enabled() | ||
| conf_data = configuration_data() | ||
| conf_data.set_quoted('RUN_PATH', get_option('rundir')) | ||
| conf_data.set_quoted('CONF_PATH', join_paths( | ||
| - get_option('prefix'), get_option('sysconfdir'), 'turnstile' | ||
| + '/etc/', 'turnstile' | ||
| )) | ||
| conf_data.set10('MANAGE_RUNDIR', get_option('manage_rundir')) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| diff --git a/backend/dinit b/backend/dinit | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh boy... this is a tough one, right? do we let assume we let
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turnstile generates these initial units at runtime and I haven't had the time to test if that is for a good reason or just simply how they choose to do it. It might just happen that in a nondeclarative environment its necessary/more convenient. The purpose of removing the graphical ones optionally was simply the annoyance referenced in the option description. You have to add All that to say, I think that if |
||
| index 7bacaac..27ee9b7 100644 | ||
| --- a/backend/dinit | ||
| +++ b/backend/dinit | ||
| @@ -121,8 +121,6 @@ type = internal | ||
| depends-on = system | ||
| waits-for.d = ${boot_dir} | ||
| depends-on = login.target | ||
| -depends-ms = graphical.monitor | ||
| -depends-ms = graphical.target | ||
| EOF | ||
|
|
||
| # this must also succeed | ||
| @@ -131,24 +129,9 @@ type = internal | ||
| waits-for.d = ${system_boot_dir} | ||
| EOF | ||
|
|
||
| -# monitor service to watch for environment changes | ||
| -cat << EOF > "${DINIT_DIR}/graphical.monitor" | ||
| -type = process | ||
| -depends-on = login.target | ||
| -options = pass-cs-fd | ||
| -command = /usr/bin/dinit-monitor -E -c "$0 graphical-notify" WAYLAND_DISPLAY DISPLAY | ||
| -EOF | ||
| - | ||
| # this is needed for login to proceed | ||
| cat << EOF > "${DINIT_DIR}/login.target" | ||
| type = internal | ||
| EOF | ||
|
|
||
| -# this is not necessary to have started for login to proceed | ||
| -cat << EOF > "${DINIT_DIR}/graphical.target" | ||
| -type = triggered | ||
| -depends-on = graphical.monitor | ||
| -depends-on = login.target | ||
| -EOF | ||
| - | ||
| exec dinit --user --ready-fd 3 --services-dir "$DINIT_DIR" "$@" 3>"$DINIT_READY_PIPE" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️