resources/dev

SSH-Agent via systemd (user service)

Run ssh-agent as a systemd user service with a fixed socket path. Minimal setup — no keychain, gpg-agent, or shell-eval hacks. Needs only openssh + systemd (already present on Arch/EndeavourOS).

Fits a sway session started from ly, since a systemd user session is already running (sway-session.target). The socket path is deterministic, so every consumer just points at the same constant.

1. Agent service

~/.config/systemd/user/ssh-agent.service:

[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

%t = $XDG_RUNTIME_DIR = /run/user/UID. WantedBy=default.target starts it at login, before sway.

2. Enable

systemctl --user enable --now ssh-agent

3. Export the socket for shells

Put this in ~/.zshenv (not .zshrc — that is interactive-only, so GUI-launched processes miss it). .zshenv is sourced for every zsh and before the p10k instant prompt, so no output warning:

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

4. Auto-load keys (no ssh-add)

Top of ~/.ssh/config:

Host *
    AddKeysToAgent yes

First ssh/git connect prompts for the passphrase once in the terminal, then caches the key in the agent for the session. Pure openssh, no wrapper.

5. Verify

New terminal:

ssh-add -l

Empty list ("The agent has no identities") = agent live and socket wired. Could not open a connection to your authentication agent = SSH_AUTH_SOCK not set — recheck step 3.

Optional: GUI apps

Terminal apps (git, nvim, the s ssh selector) are covered by step 3. Only apps launched directly by sway (not via a shell) miss the var. To cover them:

~/.config/environment.d/ssh-auth-sock.conf:

SSH_AUTH_SOCK=${XDG_RUNTIME_DIR}/ssh-agent.socket

And early in the sway config:

exec_always dbus-update-activation-environment SSH_AUTH_SOCK

dbus-update-activation-environment ships with dbus, already installed on any Wayland setup. Skip this unless a GUI git client actually needs the agent.