aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-06-05 11:06:00 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-06-05 11:06:00 +0100
commitcd050f0bdfea14f031e4a671a366c77d4f62b19d (patch)
treed205b7c9ecbc5ff347a211c96b17ae504de4ae03
parentb159599ece4d6889f8199fb0d079548823671677 (diff)
downloaddotfiles-cd050f0bdfea14f031e4a671a366c77d4f62b19d.tar.gz
dotfiles-cd050f0bdfea14f031e4a671a366c77d4f62b19d.tar.bz2
dotfiles-cd050f0bdfea14f031e4a671a366c77d4f62b19d.zip
fix(systemd): use absolute %h/.nix-profile/bin paths in user units
The previous environment.d fix was insufficient: even with the nix profile on the --user manager's PATH (confirmed via `systemctl --user show-environment`), bare-name ExecStart= still fails 203/EXEC. systemd's --user manager does not resolve a bare ExecStart binary against the imported/environment.d PATH. Invoke each unit's main binary by absolute path %h/.nix-profile/bin/<name> (waybar, swayidle, swayrd, inhibridge, wl-paste, wob). %h expands to $HOME at unit load. Secondary lookups those binaries/scripts perform (cliphist, swaymsg, playerctl) still rely on PATH, which environment.d provides — so that file stays, with its comment corrected to reflect this split.
-rw-r--r--dot_config/environment.d/10-nix-profile-path.conf32
-rw-r--r--dot_config/systemd/user/cliphist-image.service2
-rw-r--r--dot_config/systemd/user/cliphist-text.service2
-rw-r--r--dot_config/systemd/user/inhibridge.service2
-rw-r--r--dot_config/systemd/user/swayidle.service2
-rw-r--r--dot_config/systemd/user/swayrd.service2
-rw-r--r--dot_config/systemd/user/waybar.service2
-rw-r--r--dot_config/systemd/user/wob.service2
-rw-r--r--nix/host.nix8
9 files changed, 28 insertions, 26 deletions
diff --git a/dot_config/environment.d/10-nix-profile-path.conf b/dot_config/environment.d/10-nix-profile-path.conf
index 2e396d7..61d6402 100644
--- a/dot_config/environment.d/10-nix-profile-path.conf
+++ b/dot_config/environment.d/10-nix-profile-path.conf
@@ -1,22 +1,20 @@
# Prepend the Nix home-profile (and ~/.local/bin) to the systemd *user*
-# manager's PATH at manager startup, before any unit in sway-session.target
-# launches.
+# manager's environment PATH, so it is inherited by every service process.
#
-# Why this exists: most user-leaf tools (waybar, swayidle, swayr, mako,
-# cliphist, inhibridge, wob, …) were migrated from pacman (/usr/bin) to the
-# Nix home profile (~/.nix-profile/bin) and their .service units reference
-# them by *bare* name, relying on $PATH resolution (see nix/host.nix). The
-# systemd user manager does NOT source ~/.zprofile, so without this its PATH
-# is only /usr/local/bin:/usr/bin:/bin and every bare-name ExecStart fails
-# with status=203/EXEC.
+# Scope of this file: it fixes PATH for *child-process* lookups made BY the
+# services — e.g. wl-paste spawning `cliphist store`, swayidle running
+# `swaymsg`/`playerctl`, and helper scripts (display-watcher.sh,
+# on-battery-suspend) that call nix tools by bare name. The systemd user
+# manager does NOT source ~/.zprofile, so without this its PATH is only
+# /usr/local/bin:/usr/bin:/bin and those bare-name lookups fail.
#
-# The sway config also runs `systemctl --user import-environment PATH`, but
-# that is a fire-and-forget `exec` that races with
-# `systemctl --user start sway-session.target`; if the start wins, the units
-# launch with the default PATH. environment.d is read deterministically at
-# manager start (before any unit), so it closes that race independently of
-# the live session.
+# It does NOT fix systemd's own ExecStart= binary resolution: systemd's
+# --user manager does not resolve a bare ExecStart name against this
+# (imported/environment.d) PATH, so those would still fail 203/EXEC. For
+# that reason the units under dot_config/systemd/user/ invoke their main
+# binary by absolute path (%h/.nix-profile/bin/<name>); this file only
+# covers the secondary PATH lookups those binaries/scripts perform.
#
-# Note: environment.d is only re-read on a fresh user manager (login/boot) or
-# after `systemctl --user daemon-reexec`; it is not picked up mid-session.
+# Note: environment.d is only re-read on a fresh user manager (login/boot)
+# or after `systemctl --user daemon-reexec`; it is not picked up mid-session.
PATH=${HOME}/.nix-profile/bin:${HOME}/.local/bin:${PATH}
diff --git a/dot_config/systemd/user/cliphist-image.service b/dot_config/systemd/user/cliphist-image.service
index 059695b..8d9e995 100644
--- a/dot_config/systemd/user/cliphist-image.service
+++ b/dot_config/systemd/user/cliphist-image.service
@@ -6,7 +6,7 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
-ExecStart=wl-paste --type image --watch cliphist store
+ExecStart=%h/.nix-profile/bin/wl-paste --type image --watch cliphist store
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/systemd/user/cliphist-text.service b/dot_config/systemd/user/cliphist-text.service
index 5ff00f5..8aef8b3 100644
--- a/dot_config/systemd/user/cliphist-text.service
+++ b/dot_config/systemd/user/cliphist-text.service
@@ -6,7 +6,7 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
-ExecStart=wl-paste --type text --watch cliphist store
+ExecStart=%h/.nix-profile/bin/wl-paste --type text --watch cliphist store
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/systemd/user/inhibridge.service b/dot_config/systemd/user/inhibridge.service
index 0b36b35..a361ad9 100644
--- a/dot_config/systemd/user/inhibridge.service
+++ b/dot_config/systemd/user/inhibridge.service
@@ -7,7 +7,7 @@ ConditionEnvironment=DBUS_SESSION_BUS_ADDRESS
[Service]
Type=simple
-ExecStart=inhibridge
+ExecStart=%h/.nix-profile/bin/inhibridge
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/systemd/user/swayidle.service b/dot_config/systemd/user/swayidle.service
index d5b9cf1..bd0dca5 100644
--- a/dot_config/systemd/user/swayidle.service
+++ b/dot_config/systemd/user/swayidle.service
@@ -6,7 +6,7 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
-ExecStart=swayidle -w \
+ExecStart=%h/.nix-profile/bin/swayidle -w \
timeout 300 'swaymsg "output * power off"' \
resume 'swaymsg "output * power on"' \
timeout 330 'swaylock -f -e -c 000000' \
diff --git a/dot_config/systemd/user/swayrd.service b/dot_config/systemd/user/swayrd.service
index c718fe5..2e299e9 100644
--- a/dot_config/systemd/user/swayrd.service
+++ b/dot_config/systemd/user/swayrd.service
@@ -7,7 +7,7 @@ ConditionEnvironment=SWAYSOCK
[Service]
Type=simple
-ExecStart=swayrd
+ExecStart=%h/.nix-profile/bin/swayrd
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/systemd/user/waybar.service b/dot_config/systemd/user/waybar.service
index 919bc9b..e8686b1 100644
--- a/dot_config/systemd/user/waybar.service
+++ b/dot_config/systemd/user/waybar.service
@@ -6,7 +6,7 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
-ExecStart=waybar
+ExecStart=%h/.nix-profile/bin/waybar
ExecReload=/bin/kill -SIGUSR2 $MAINPID
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/systemd/user/wob.service b/dot_config/systemd/user/wob.service
index c132501..d9c0869 100644
--- a/dot_config/systemd/user/wob.service
+++ b/dot_config/systemd/user/wob.service
@@ -7,7 +7,7 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
ExecStartPre=/usr/bin/sh -c 'rm -f "$XDG_RUNTIME_DIR/wob.sock" && mkfifo "$XDG_RUNTIME_DIR/wob.sock"'
-ExecStart=/usr/bin/sh -c 'exec tail -f "$XDG_RUNTIME_DIR/wob.sock" | wob'
+ExecStart=/usr/bin/sh -c 'exec tail -f "$XDG_RUNTIME_DIR/wob.sock" | %h/.nix-profile/bin/wob'
ExecStopPost=/usr/bin/rm -f %t/wob.sock
Restart=on-failure
RestartSec=2s
diff --git a/nix/host.nix b/nix/host.nix
index 9b594b8..ecaf464 100644
--- a/nix/host.nix
+++ b/nix/host.nix
@@ -66,8 +66,12 @@ in
# Pure user-session GUIs/daemons — no system unit, no D-Bus activation
# file under /usr/share/dbus-1, no login-manager session entry. The
# corresponding user-scope systemd units live under
- # dot_config/systemd/user/ and reference these binaries by bare name
- # so $PATH resolves them out of ~/.nix-profile/bin.
+ # dot_config/systemd/user/ and reference these binaries by an absolute
+ # %h/.nix-profile/bin/<name> path. (Bare names do NOT work: systemd's
+ # ExecStart binary resolution does not use the imported/environment.d
+ # PATH of the --user manager, so a bare name fails with 203/EXEC even
+ # though `systemctl --user show-environment` shows the nix profile on
+ # PATH. The %h specifier expands to $HOME at unit-load time.)
waybar
mako
fuzzel