Last updated: Wed May 01 2024

SSH Agents

Using ssh or scp with a passworded key file can get annoying because it will prompt every time for the password.

A solution to this is to set up an SSH Agent, which will cache the key in memory for a given amount of time, meaning that you won't be prompted to unlock it during this period. By default, this is until the machine is rebooted, but you can change this below.

Basic Setup

To set this up:

First install openssh, which provides ssh-agent.

# Install openssh
sudo pacman -S openssh

Then configure ssh-agent to run as a user service:

# Run ssh-agent as a user service.
# Note: Do NOT run this as sudo - it is a user level service!
# -----------------------------------------------------------
systemctl --user enable ssh-agent.service
systemctl --user start ssh-agent.service

This creates a socket at $XDG_RUNTIME_DIR/ssh-agent.socket, which is used for communication between ssh/scp and ssh-agent. We need to configure the shell to be aware of this by creating an environment variable.

# Add this to .bashrc/.zshrc/etc
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

And finally, tell ssh/scp to add keys to the agent when you first unlock it.

# In ~/.ssh/config
# ----------------
AddKeysToAgent yes

Cache lifetime

The cache lifetime is defined in the invocation of ssh-agent.

Unfortunately, the invocation is hidden inside the ssh-agent.service file, and is not configurable.

So, in order to change this, we need to override this service with a slightly customised one.

(Note: this is currently untested as I am happy with the default)

First disable and stop the existing service:

systemctl --user disable ssh-agent.service
systemctl --user stop ssh-agent.service

Then create a custom service at ~/.config/systemd/user/ssh-agent-timeout.service

# ~/.config/systemd/user/ssh-agent-timeout.service
# ------------

# Requires SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" to be set in environment
[Unit]
ConditionEnvironment=!SSH_AGENT_PID
Description=OpenSSH key agent
Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1)

[Service]
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK -t 1h
PassEnvironment=SSH_AGENT_PID
SuccessExitStatus=2
Type=simple

[Install]
WantedBy=default.target

All we've added here is -t 1h on the ExecStart line, which tells the agent to cache keys for 1 hour.

See man ssh_config#TIME_FORMATS for more details on time formats for more fine grained control.

Finally, start and enable the new service

systemctl --user enable ssh-agent-timeout.service
systemctl --user start ssh-agent-timeout.service