launchd: wait for /nix/store before starting agent (#8609)
On Darwin, launchd may attempt to start agents before the Nix store is mounted and available. This leads to failures when the agent's executable or arguments reside in the Nix store. This change wraps the agent's command in a shell script that uses /bin/wait4path to ensure /nix/store is ready before executing the original program. It also ensures that ProgramArguments are correctly escaped and concatenated.
This commit is contained in:
parent
ef5da06269
commit
eec72f1278
30 changed files with 123 additions and 90 deletions
|
|
@ -43,7 +43,31 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
toAgent = config: pkgs.writeText "${config.Label}.plist" (toPlist { escape = true; } config);
|
||||
# mutateConfig calls /bin/sh with /bin/wait4path to wait for /nix/store before
|
||||
# running the original Program and ProgramArguments. This is intentional to
|
||||
# fix the issue where launchd starts the agent before /nix/store is ready
|
||||
# (before the Nix store is mounted.)
|
||||
mutateConfig =
|
||||
cnf:
|
||||
let
|
||||
args =
|
||||
lib.optional (cnf.Program != null) cnf.Program
|
||||
++ lib.optionals (cnf.ProgramArguments != null) cnf.ProgramArguments;
|
||||
in
|
||||
(removeAttrs cnf [
|
||||
"Program"
|
||||
"ProgramArguments"
|
||||
])
|
||||
// {
|
||||
ProgramArguments = [
|
||||
"/bin/sh"
|
||||
"-c"
|
||||
"/bin/wait4path /nix/store && exec ${lib.escapeShellArgs args}"
|
||||
];
|
||||
};
|
||||
|
||||
toAgent =
|
||||
config: pkgs.writeText "${config.Label}.plist" (toPlist { escape = true; } (mutateConfig config));
|
||||
|
||||
agentPlists = lib.mapAttrs' (n: v: lib.nameValuePair "${v.config.Label}.plist" (toAgent v.config)) (
|
||||
lib.filterAttrs (n: v: v.enable) cfg.agents
|
||||
|
|
|
|||
13
modules/misc/news/2026/01/2026-01-27_21-41-51.nix
Normal file
13
modules/misc/news/2026/01/2026-01-27_21-41-51.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
time = "2026-01-27T21:41:51+00:00";
|
||||
condition = pkgs.stdenv.hostPlatform.isDarwin && config.launchd.enable;
|
||||
message = ''
|
||||
|
||||
The `launchd` module now ensures that the Nix store is mounted and
|
||||
available before starting any agents. This improves reliability on macOS
|
||||
where `launchd` might otherwise attempt to start agents before the Nix
|
||||
store is ready.
|
||||
'';
|
||||
}
|
||||
|
|
@ -17,9 +17,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/some/command</string>
|
||||
<string>--with-arguments</string>
|
||||
<string>foo</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /some/command --with-arguments foo</string>
|
||||
</array>
|
||||
<key>UnrecognizedByHomeManager</key>
|
||||
<string>should make it to the resulting plist</string>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,12 @@
|
|||
<true/>
|
||||
<key>Label</key>
|
||||
<string>org.nix-community.home.aerospace</string>
|
||||
<key>Program</key>
|
||||
<string>/nix/store/00000000000000000000000000000000-aerospace/Applications/AeroSpace.app/Contents/MacOS/AeroSpace</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /nix/store/00000000000000000000000000000000-aerospace/Applications/AeroSpace.app/Contents/MacOS/AeroSpace</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardErrorPath</key>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,9 @@
|
|||
<string>org.nix-community.home.git-maintenance-daily</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@git@/bin/git</string>
|
||||
<string>for-each-repo</string>
|
||||
<string>--keep-going</string>
|
||||
<string>--config=maintenance.repo</string>
|
||||
<string>maintenance</string>
|
||||
<string>run</string>
|
||||
<string>--schedule=daily</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @git@/bin/git for-each-repo --keep-going '--config=maintenance.repo' maintenance run '--schedule=daily'</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,9 @@
|
|||
<string>org.nix-community.home.git-maintenance-hourly</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@git@/bin/git</string>
|
||||
<string>for-each-repo</string>
|
||||
<string>--keep-going</string>
|
||||
<string>--config=maintenance.repo</string>
|
||||
<string>maintenance</string>
|
||||
<string>run</string>
|
||||
<string>--schedule=hourly</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @git@/bin/git for-each-repo --keep-going '--config=maintenance.repo' maintenance run '--schedule=hourly'</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,9 @@
|
|||
<string>org.nix-community.home.git-maintenance-weekly</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@git@/bin/git</string>
|
||||
<string>for-each-repo</string>
|
||||
<string>--keep-going</string>
|
||||
<string>--config=maintenance.repo</string>
|
||||
<string>maintenance</string>
|
||||
<string>run</string>
|
||||
<string>--schedule=weekly</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @git@/bin/git for-each-repo --keep-going '--config=maintenance.repo' maintenance run '--schedule=weekly'</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
<string>org.nix-community.home.nh-clean</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@nh@/bin/nh</string>
|
||||
<string>clean</string>
|
||||
<string>user</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @nh@/bin/nh clean user</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -15,20 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@opencode@/bin/opencode</string>
|
||||
<string>web</string>
|
||||
<string>--hostname</string>
|
||||
<string>0.0.0.0</string>
|
||||
<string>--port</string>
|
||||
<string>4096</string>
|
||||
<string>--mdns</string>
|
||||
<string>--cors</string>
|
||||
<string>https://example.com</string>
|
||||
<string>--cors</string>
|
||||
<string>http://localhost:3000</string>
|
||||
<string>--print-logs</string>
|
||||
<string>--log-level</string>
|
||||
<string>DEBUG</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @opencode@/bin/opencode web --hostname 0.0.0.0 --port 4096 --mdns --cors https://example.com --cors http://localhost:3000 --print-logs --log-level DEBUG</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,12 @@
|
|||
<string>org.nix-community.home.sketchybar</string>
|
||||
<key>ProcessType</key>
|
||||
<string>Interactive</string>
|
||||
<key>Program</key>
|
||||
<string>/nix/store/00000000000000000000000000000000-sketchybar/bin/sketchybar</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /nix/store/00000000000000000000000000000000-sketchybar/bin/sketchybar</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>StandardErrorPath</key>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@borgmatic@/bin/borgmatic</string>
|
||||
<string>--stats</string>
|
||||
<string>--list</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @borgmatic@/bin/borgmatic --stats --list</string>
|
||||
</array>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/home/hm-user/Library/Logs/borgmatic/launchd-stderr.log</string>
|
||||
|
|
|
|||
|
|
@ -13,12 +13,9 @@
|
|||
<string>org.nix-community.home.colima-default</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@colima@/bin/colima</string>
|
||||
<string>start</string>
|
||||
<string>default</string>
|
||||
<string>-f</string>
|
||||
<string>--activate=true</string>
|
||||
<string>--save-config=false</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @colima@/bin/colima start default -f '--activate=true' '--save-config=false'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@
|
|||
<string>org.nix-community.home.emacs</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@emacs@/bin/emacs</string>
|
||||
<string>--fg-daemon</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @emacs@/bin/emacs --fg-daemon</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
<string>org.nix-community.home.espanso</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@espanso@/Applications/Espanso.app/Contents/MacOS/espanso</string>
|
||||
<string>launcher</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @espanso@/Applications/Espanso.app/Contents/MacOS/espanso launcher</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@git-sync@/bin/git-sync</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @git-sync@/bin/git-sync</string>
|
||||
</array>
|
||||
<key>StartInterval</key>
|
||||
<integer>500</integer>
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@gpg@/bin/gpg-agent</string>
|
||||
<string>--supervised</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @gpg@/bin/gpg-agent --supervised</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<false/>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/nix/store/00000000000000000000000000000000-home-manager-auto-expire</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /nix/store/00000000000000000000000000000000-home-manager-auto-expire</string>
|
||||
</array>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/home/hm-user/Library/Logs/home-manager-auto-expire/launchd-stderr.log</string>
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@goimapnotify@/bin/goimapnotify</string>
|
||||
<string>-conf</string>
|
||||
<string>/nix/store/00000000000000000000000000000000-imapnotify-hm-example.com-config.json</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @goimapnotify@/bin/goimapnotify -conf /nix/store/00000000000000000000000000000000-imapnotify-hm-example.com-config.json</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -11,10 +11,9 @@
|
|||
<string>org.nix-community.home.remap-keys</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/bin/hidutil</string>
|
||||
<string>property</string>
|
||||
<string>--set</string>
|
||||
<string>{ "UserKeyMapping": [ { "HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x70000002A } ] }</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /usr/bin/hidutil property --set '{ "UserKeyMapping": [ { "HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x70000002A } ] }'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
<string>org.nix-community.home.nix-gc</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@nix@/bin/nix-collect-garbage</string>
|
||||
<string>--delete-older-than 30d</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @nix@/bin/nix-collect-garbage '--delete-older-than 30d'</string>
|
||||
</array>
|
||||
<key>StartCalendarInterval</key>
|
||||
<array>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@ollama@/bin/ollama</string>
|
||||
<string>serve</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @ollama@/bin/ollama serve</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -15,7 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/nix/store/00000000000000000000000000000000-podman-machine-watchdog-podman-machine-default</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /nix/store/00000000000000000000000000000000-podman-machine-watchdog-podman-machine-default</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/nix/store/00000000000000000000000000000000-podman-machine-watchdog-dev-machine</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec /nix/store/00000000000000000000000000000000-podman-machine-watchdog-dev-machine</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@bash-interactive@/bin/bash</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>@proton-pass-cli@/bin/pass-cli ssh-agent start --socket-path $(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/proton-pass-agent/socket</string>
|
||||
<string>/bin/wait4path /nix/store && exec @bash-interactive@/bin/bash -c '@proton-pass-cli@/bin/pass-cli ssh-agent start --socket-path $(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/proton-pass-agent/socket'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@bash-interactive@/bin/bash</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>@proton-pass-cli@/bin/pass-cli ssh-agent start --socket-path $(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/proton-pass-agent/socket --share-id 123456789 --vault-name MySshKeyVault --refresh-interval 7200 --create-new-identities MySshKeyVault</string>
|
||||
<string>/bin/wait4path /nix/store && exec @bash-interactive@/bin/bash -c '@proton-pass-cli@/bin/pass-cli ssh-agent start --socket-path $(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/proton-pass-agent/socket --share-id 123456789 --vault-name MySshKeyVault --refresh-interval 7200 --create-new-identities MySshKeyVault'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@bash-interactive@/bin/bash</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent"</string>
|
||||
<string>/bin/wait4path /nix/store && exec @bash-interactive@/bin/bash -c '@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent"'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@bash-interactive@/bin/bash</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent" -P '/usr/lib/libpkcs11.so,/usr/lib/other.so'</string>
|
||||
<string>/bin/wait4path /nix/store && exec @bash-interactive@/bin/bash -c '@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent" -P '\''/usr/lib/libpkcs11.so,/usr/lib/other.so'\'''</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@bash-interactive@/bin/bash</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent" -t 1337</string>
|
||||
<string>/bin/wait4path /nix/store && exec @bash-interactive@/bin/bash -c '@openssh@/bin/ssh-agent -D -a "$(@getconf-system_cmds@/bin/getconf DARWIN_USER_TEMP_DIR)/ssh-agent" -t 1337'</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@syncthing-wrapper@</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @syncthing-wrapper@</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
<string>Background</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>@yubikey-agent@/bin/yubikey-agent</string>
|
||||
<string>-l</string>
|
||||
<string>/tmp/yubikey-agent.sock</string>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path /nix/store && exec @yubikey-agent@/bin/yubikey-agent -l /tmp/yubikey-agent.sock</string>
|
||||
</array>
|
||||
<key>Sockets</key>
|
||||
<dict>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue