users/services: simplify the before/after/wantedBy criteria, to match s6 concepts
This commit is contained in:
parent
c5c37e79ac
commit
16ca71188f
|
@ -87,7 +87,7 @@ in
|
|||
|
||||
services.abaddon = {
|
||||
description = "unofficial Discord chat client";
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
command = "abaddon";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -118,9 +118,7 @@ in
|
|||
|
||||
services.bonsaid = {
|
||||
description = "bonsai: programmable input dispatcher";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
|
||||
partOf = [ "graphical-session" ];
|
||||
command = "bonsaid -t ${cfg.config.configFile}";
|
||||
cleanupCommand = "rm -f $XDG_RUNTIME_DIR/bonsai";
|
||||
};
|
||||
|
|
|
@ -44,7 +44,7 @@ in
|
|||
services.gnome-calls = {
|
||||
# TODO: prevent gnome-calls from daemonizing when started manually
|
||||
description = "gnome-calls daemon to monitor incoming SIP calls";
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
# add --verbose for more debugging
|
||||
command = "env G_MESSAGES_DEBUG=all gnome-calls --daemon";
|
||||
};
|
||||
|
|
|
@ -27,10 +27,7 @@
|
|||
|
||||
services.conky = {
|
||||
description = "conky dynamic desktop background";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ]; # propagate stop/restart signal from graphical-session to this unit
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
|
||||
partOf = [ "graphical-session" ];
|
||||
command = "conky";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -34,8 +34,7 @@ in
|
|||
|
||||
services.dconf = {
|
||||
description = "dconf configuration database/server";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
command = "${lib.getLib cfg.package}/libexec/dconf-service";
|
||||
};
|
||||
|
||||
|
|
|
@ -68,9 +68,7 @@ in
|
|||
|
||||
services.dino = {
|
||||
description = "dino XMPP client";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
|
||||
# audio buffering; see: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#pipewire-buffering-explained>
|
||||
# dino defaults to 10ms mic buffer, which causes underruns, which Dino handles *very* poorly
|
||||
|
|
|
@ -57,8 +57,7 @@ in
|
|||
|
||||
services.dissent = {
|
||||
description = "dissent Discord client";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
command = "dissent";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -97,9 +97,7 @@
|
|||
|
||||
services.fcitx5 = {
|
||||
description = "fcitx5: input method (IME) for emoji/internationalization";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
|
||||
partOf = [ "graphical-session" ];
|
||||
command = "fcitx5";
|
||||
};
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ in
|
|||
|
||||
services.feedbackd = {
|
||||
description = "feedbackd audio/vibration/led controller";
|
||||
wantedBy = [ "default.target" ]; #< should technically be `sound.target`, but that doesn't seem to get auto-started?
|
||||
partOf = [ "sound" ];
|
||||
command = lib.concatStringsSep " " ([
|
||||
"env"
|
||||
"G_MESSAGES_DEBUG=all"
|
||||
|
|
|
@ -68,9 +68,7 @@ in
|
|||
|
||||
services.fractal = {
|
||||
description = "fractal Matrix client";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
|
||||
# env "G_MESSAGES_DEBUG=all"
|
||||
command = "fractal";
|
||||
|
|
|
@ -87,9 +87,7 @@ in
|
|||
|
||||
services.geary = {
|
||||
description = "geary email client";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
command = "geary";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
fs.".local/share/keyrings/default" = {
|
||||
file.text = "Default_keyring.keyring"; #< no trailing newline
|
||||
# wantedBy = [ config.sane.fs."${config.sane.persist.stores.private.origin}".unit ];
|
||||
wantedBeforeBy = [ #< don't create this as part of `multi-user.target`
|
||||
"gnome-keyring.service" # TODO: sane.programs should declare this dependency for us
|
||||
];
|
||||
# wantedBeforeBy = [ #< don't create this as part of `multi-user.target`
|
||||
# "gnome-keyring.service" # TODO: sane.programs should declare this dependency for us
|
||||
# ];
|
||||
};
|
||||
# N.B.: certain keyring names have special significance
|
||||
# `login.keyring` is forcibly encrypted to the user's password, so that pam gnome-keyring can unlock it on login.
|
||||
|
@ -41,15 +41,14 @@
|
|||
lock-after=false
|
||||
'';
|
||||
# wantedBy = [ config.sane.fs."${config.sane.persist.stores.private.origin}".unit ];
|
||||
wantedBeforeBy = [ #< don't create this as part of `multi-user.target`
|
||||
"gnome-keyring.service"
|
||||
];
|
||||
# wantedBeforeBy = [ #< don't create this as part of `multi-user.target`
|
||||
# "gnome-keyring.service"
|
||||
# ];
|
||||
};
|
||||
|
||||
services.gnome-keyring = {
|
||||
description = "gnome-keyring-daemon: secret provider";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
command = let
|
||||
gkr-start = pkgs.writeShellScriptBin "gnome-keyring-daemon-start" ''
|
||||
mkdir -m 0700 -p $XDG_RUNTIME_DIR/keyring
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
# on environment.packages, but then logs are blackholed.
|
||||
services.mako = {
|
||||
description = "mako desktop notification daemon";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
command = "${config.sane.programs.mako.package}/bin/mako";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -27,7 +27,7 @@ in
|
|||
|
||||
services.ntfy-sub = {
|
||||
description = "listen for push-notifications";
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "default" ];
|
||||
command = let
|
||||
sub = pkgs.writeShellScriptBin "ntfy-sub" ''
|
||||
topic=$(cat ~/.config/ntfy-sh/topic)
|
||||
|
|
|
@ -30,8 +30,7 @@ in
|
|||
|
||||
services.pipewire = {
|
||||
description = "pipewire: multimedia service";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "sound" ];
|
||||
# env PIPEWIRE_LOG_SYSTEMD=false"
|
||||
# env PIPEWIRE_DEBUG"*:3,mod.raop*:5,pw.rtsp-client*:5"
|
||||
command = "pipewire";
|
||||
|
@ -43,8 +42,8 @@ in
|
|||
};
|
||||
services.pipewire-pulse = {
|
||||
description = "pipewire-pulse: Pipewire compatibility layer for PulseAudio clients";
|
||||
after = [ "pipewire.service" ];
|
||||
wantedBy = [ "pipewire.service" ];
|
||||
depends = [ "pipewire" ];
|
||||
partOf = [ "sound" ];
|
||||
command = "pipewire-pulse";
|
||||
pollReadyCommand = pkgs.writeShellScript "pipewire-pulse-wait-started" ''
|
||||
[ -e "$XDG_RUNTIME_DIR/pulse/native" ] && \
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
services.playerctld = {
|
||||
description = "playerctl daemon to keep track of which MPRIS players were recently active";
|
||||
documentation = [ "https://github.com/altdesktop/playerctl/issues/161" ];
|
||||
wantedBy = [ "default.target" ]; #< TODO: maybe better to zero `wantedBy` here and have the specific consumers (e.g. swaync) explicitly depend on this.
|
||||
partOf = [ "default" ]; #< TODO: maybe better to zero `wantedBy` here and have the specific consumers (e.g. swaync) explicitly depend on this.
|
||||
command = "playerctld";
|
||||
# serviceConfig.BusName = "org.mpris.MediaPlayer2.Player";
|
||||
};
|
||||
|
|
|
@ -46,9 +46,8 @@ in
|
|||
|
||||
services.signal-desktop = {
|
||||
description = "signal-desktop Signal Messenger client";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
# depends = [ "graphical-session" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
|
||||
# for some reason the --ozone-platform-hint=auto flag fails when signal-desktop is launched from a service
|
||||
command = "env NIXOS_OZONE_WL=1 signal-desktop";
|
||||
|
|
|
@ -31,7 +31,7 @@ in
|
|||
|
||||
services.sway-autoscaler = {
|
||||
description = "adjust global desktop scale to match the activate application";
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
command = lib.escapeShellArgs [
|
||||
"env"
|
||||
"SWAY_DEFAULT_SCALE=${builtins.toString cfg.config.defaultScale}"
|
||||
|
|
|
@ -253,7 +253,7 @@ in
|
|||
|
||||
services.sway = {
|
||||
description = "sway: tiling wayland desktop environment";
|
||||
wantedBy = [ "default.target" ];
|
||||
partOf = [ "default" ];
|
||||
command = "sway";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -54,8 +54,7 @@ in
|
|||
|
||||
services.swayidle = {
|
||||
description = "swayidle: perform actions when sway session is idle";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
command = lib.escapeShellArgs (
|
||||
[
|
||||
|
|
|
@ -471,12 +471,8 @@ in
|
|||
# swaync ships its own service, but i want to add `environment` variables and flags for easier debugging.
|
||||
# seems that's not possible without defining an entire nix-native service (i.e. this).
|
||||
description = "swaynotificationcenter (swaync) desktop notification daemon";
|
||||
after = [
|
||||
"graphical-session.target"
|
||||
"pipewire-pulse.service" #< TODO: else it will NEVER see the pulse socket in its sandbox
|
||||
];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
depends = [ "sound" ]; #< TODO: else it will NEVER see the pulse socket in its sandbox
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
command = "env G_MESSAGES_DEBUG=all swaync";
|
||||
# serviceConfig.BusName = "org.freedesktop.Notifications";
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
|
||||
services."sysvol" = {
|
||||
description = "sysvol: volume monitor/notifier";
|
||||
after = [ "graphical-session.target" "pipewire-pulse.service" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
depends = [ "sound" ]; #< specifically wireplumber-pulse
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# options:
|
||||
# -p {0,1,2,3} to attach to top/right/bottom/left screen edge
|
||||
|
|
|
@ -115,9 +115,7 @@ in
|
|||
|
||||
services.waybar = {
|
||||
description = "swaybar graphical header bar/tray for sway";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# env G_MESSAGES_DEBUG=all
|
||||
command = "waybar";
|
||||
|
|
|
@ -31,9 +31,8 @@
|
|||
|
||||
services.wireplumber = {
|
||||
description = "wireplumber: pipewire Multimedia Service Session Manager";
|
||||
after = [ "pipewire.service" ];
|
||||
bindsTo = [ "pipewire.service" ];
|
||||
wantedBy = [ "pipewire.service" ];
|
||||
depends = [ "pipewire" ];
|
||||
partOf = [ "sound" ];
|
||||
command = "wireplumber";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
services.wvkbd = {
|
||||
description = "wvkbd: wayland virtual keyboard";
|
||||
after = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
# depends = [ "graphical-session" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
command = lib.escapeShellArgs [
|
||||
"env"
|
||||
# --hidden: send SIGUSR2 to unhide
|
||||
|
|
|
@ -41,9 +41,8 @@ in
|
|||
|
||||
services.xdg-desktop-portal-gtk = {
|
||||
description = "xdg-desktop-portal-gtk backend (provides graphical dialogs for xdg-desktop-portal)";
|
||||
after = [ "graphical-session.target" ];
|
||||
before = [ "xdg-desktop-portal.service" ];
|
||||
wantedBy = [ "xdg-desktop-portal.service" ];
|
||||
# depends = [ "graphical-session" ];
|
||||
dependencyOf = [ "xdg-desktop-portal" ];
|
||||
|
||||
command = "${cfg.package}/libexec/xdg-desktop-portal-gtk";
|
||||
serviceConfig.BusName = "org.freedesktop.impl.portal.desktop.gtk";
|
||||
|
|
|
@ -26,9 +26,8 @@ in
|
|||
|
||||
services.xdg-desktop-portal-wlr = {
|
||||
description = "xdg-desktop-portal-wlr backend (provides screenshot functionality for xdg-desktop-portal)";
|
||||
after = [ "graphical-session.target" ];
|
||||
before = [ "xdg-desktop-portal.service" ];
|
||||
wantedBy = [ "xdg-desktop-portal.service" ];
|
||||
# depends = [ "graphical-session" ];
|
||||
dependencyOf = [ "xdg-desktop-portal" ];
|
||||
|
||||
command = "${cfg.package}/libexec/xdg-desktop-portal-wlr";
|
||||
serviceConfig.BusName = "org.freedesktop.impl.portal.desktop.wlr";
|
||||
|
|
|
@ -54,9 +54,7 @@ in
|
|||
|
||||
services.xdg-desktop-portal = {
|
||||
description = "xdg-desktop-portal freedesktop.org portal (URI opener, file chooser, etc)";
|
||||
after = [ "graphical-session.target" ];
|
||||
# partOf = [ "graphical-session.target" ];
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session" ];
|
||||
|
||||
# tracking issue for having xdg-desktop-portal locate portals via more standard directories, obviating this var:
|
||||
# - <https://github.com/flatpak/xdg-desktop-portal/issues/603>
|
||||
|
@ -76,9 +74,8 @@ in
|
|||
# xdg-desktop-portal would *usually* dbus-activate this.
|
||||
# this service might not strictly be necssary. xdg-desktop-portal does warn if it's not present, though.
|
||||
description = "xdg-permission-store: lets xdg-desktop-portal know which handlers are 'safe'";
|
||||
after = [ "graphical-session.target" ];
|
||||
before = [ "xdg-desktop-portal.service" ];
|
||||
wantedBy = [ "xdg-desktop-portal.service" ];
|
||||
# after = [ "graphical-session" ];
|
||||
dependencyOf = [ "xdg-desktop-portal" ];
|
||||
|
||||
command = lib.concatStringsSep " " [
|
||||
"env"
|
||||
|
|
|
@ -16,25 +16,21 @@ let
|
|||
references and links for where to find documentation about this service.
|
||||
'';
|
||||
};
|
||||
after = mkOption {
|
||||
depends = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
bindsTo = mkOption {
|
||||
dependencyOf = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
before = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
wantedBy = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
wants = mkOption {
|
||||
partOf = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
"bundles" to which this service belongs.
|
||||
e.g. `partOf = [ "default" ];` describes services which should be started "by default".
|
||||
'';
|
||||
};
|
||||
|
||||
command = mkOption {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
let
|
||||
logBase = "$HOME/.local/state/s6/logs";
|
||||
maybe = cond: value: if cond then value else null;
|
||||
normalizeName = name: lib.removeSuffix ".service" (lib.removeSuffix ".target" name);
|
||||
|
||||
# create a derivation whose output is the on-disk representation of some attrset.
|
||||
# @path: /foo/bar/...
|
||||
|
@ -56,22 +55,19 @@ let
|
|||
|
||||
# infers the service type from the arguments and creates an attrset usable by `fsToDerivation`.
|
||||
# also configures the service for logging, if applicable.
|
||||
serviceToFs = { name, run, finish, depends }: let
|
||||
name' = normalizeName name;
|
||||
serviceToFs = { name, run, finish, depends, contents }: let
|
||||
type = if run != null then "longrun" else "bundle";
|
||||
logger = serviceToFs' {
|
||||
name = "logger:${name'}";
|
||||
consumerFor = name';
|
||||
run = ''exec s6-log -- T p'${name'}:' "${logBase}/${name'}"'';
|
||||
name = "logger:${name}";
|
||||
consumerFor = name;
|
||||
run = ''exec s6-log -- T p'${name}:' "${logBase}/${name}"'';
|
||||
type = "longrun";
|
||||
};
|
||||
in (serviceToFs' {
|
||||
inherit type run finish;
|
||||
name = name';
|
||||
# TODO: a bundle can have dependencies too!
|
||||
depends = lib.optionals (type == "longrun") depends;
|
||||
contents = maybe (type == "bundle") depends;
|
||||
producerFor = maybe (type == "longrun") "logger:${name'}";
|
||||
inherit name type run finish;
|
||||
depends = depends;
|
||||
contents = maybe (type == "bundle") contents;
|
||||
producerFor = maybe (type == "longrun") "logger:${name}";
|
||||
}) // (lib.optionalAttrs (type == "longrun") logger);
|
||||
|
||||
serviceToFs'= {
|
||||
|
@ -97,11 +93,11 @@ let
|
|||
${run} 2>&1
|
||||
'';
|
||||
"contents".text = maybe (contents != null) (
|
||||
lib.concatStringsSep "\n" (builtins.map normalizeName contents)
|
||||
lib.concatStringsSep "\n" contents
|
||||
);
|
||||
# TODO: a bundle can also have dependencies
|
||||
"dependencies.d".dir = lib.genAttrs
|
||||
(builtins.map normalizeName depends)
|
||||
depends
|
||||
(dep: { text = ""; })
|
||||
;
|
||||
"consumer-for".text = maybe (consumerFor != null) consumerFor;
|
||||
|
@ -155,8 +151,11 @@ let
|
|||
inherit name;
|
||||
run = service.command;
|
||||
finish = service.cleanupCommand;
|
||||
depends = service.wants ++ builtins.attrNames (
|
||||
lib.filterAttrs (_: cfg: lib.elem name cfg.wantedBy || lib.elem "${name}.service" cfg.wantedBy) services
|
||||
depends = service.depends ++ builtins.attrNames (
|
||||
lib.filterAttrs (_: cfg: lib.elem name cfg.dependencyOf) services
|
||||
);
|
||||
contents = builtins.attrNames (
|
||||
lib.filterAttrs (_: cfg: lib.elem name cfg.partOf) services
|
||||
);
|
||||
})
|
||||
services
|
||||
|
@ -164,19 +163,28 @@ let
|
|||
|
||||
# in the systemd service management, these targets are implicitly defined and used
|
||||
# to accomplish something like run-levels, or service groups.
|
||||
# map them onto s6 "bundles". their contents are determined via reverse dependency mapping (`wantedBy` of every other service).
|
||||
# map them onto s6 "bundles". their contents are determined via finding every other service which declares itself to be `partOf` this one.
|
||||
implicitServices = {
|
||||
"default.target" = {
|
||||
"default" = {
|
||||
command = null;
|
||||
cleanupCommand = null;
|
||||
wants = [];
|
||||
wantedBy = [];
|
||||
depends = [];
|
||||
dependencyOf = [];
|
||||
partOf = [];
|
||||
};
|
||||
"graphical-session.target" = {
|
||||
"graphical-session" = {
|
||||
command = null;
|
||||
cleanupCommand = null;
|
||||
wants = [];
|
||||
wantedBy = [];
|
||||
depends = [];
|
||||
dependencyOf = [];
|
||||
partOf = [];
|
||||
};
|
||||
"sound" = {
|
||||
command = null;
|
||||
cleanupCommand = null;
|
||||
depends = [];
|
||||
dependencyOf = [];
|
||||
partOf = [ "default" ];
|
||||
};
|
||||
};
|
||||
in
|
||||
|
|
Loading…
Reference in New Issue