1. Overview

In this tutorial, we’ll look at ssh-agent as a tool for SSH authentication and how we can configure it as a systemd unit. Firstly, we’ll look at ssh-agent itself, then, we’ll set it up as a systemd unit.

Integrating ssh-agent with systemd ensures that the agent starts automatically at boot and is always available when needed. By following these steps, we can ensure that their SSH authentication process is efficient.

2. The ssh-agent

ssh-agent is a program that holds private keys used for public key authentication (SSH). It facilitates single sign-on by storing our private keys and managing authentication on our behalf, so we don’t need to enter our passphrases recurrently when connecting to remote servers.

ssh-agent is part of the OpenSSH suite and acts as a key manager for SSH keys. It runs in the background and maintains a list of private keys. The ssh-agent program uses the SSH_AUTH_SOCK environment variable to communicate with other programs, allowing them to authenticate without directly accessing the private key files.

Let’s consider a case where we have several remote servers we frequently access via SSH. Without ssh-agent, each connection would require us to enter the passphrase for our private key. With ssh-agent, we enter the passphrase once, and the agent handles subsequent authentications.

One of the benefits of using ssh-agent is that it enhances security by reducing the exposure of private keys. Instead of typing our passphrase multiple times, we only need to unlock our key once per session.

Additionally, it keeps the private keys in memory and not in plain text on disk, reducing the risk of key theft.

3. Configuring ssh-agent as a Systemd Unit

systemd is a system and service manager for Linux operating systems. It provides a suite of tools and daemons for managing system processes, services, and their dependencies. As the default init system in many Linux distributions, systemd handles the boot process, manages user sessions, and ensures that services are started, stopped, and maintained in a consistent state.

Some of the key features include parallel service startup, on-demand activation of daemons, and sophisticated process tracking. Its central component is the systemd daemon, which controls various system components that improve efficiency and reliability.

3.1. General ssh-agent Configuration

To start and use ssh-agent as a systemd unit, we need to create a custom service that will manage the lifecycle of the ssh-agent process. This approach ensures that ssh-agent starts automatically at boot and is available to all users.

Firstly, we need to create a service file for ssh-agent. This file will be placed in the /etc/systemd/system directory for a system-wide service or in ~/.config/systemd/username/ for a user-specific service:

$ sudo vi /etc/systemd/system/ssh-agent.service

Following, let’s add the following configuration to the file:

[Unit]
Description=SSH Key Agent For All Users
After=network.target

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

[Install]
WantedBy=default.target

This unit file sets up the ssh-agent.service file to run an SSH key agent for all users, starting after the network is available. The SSH agent is started with a specific socket for communication, and the service type is simple, meaning it’s considered active immediately after starting.

Following, we set the SSH_AUTH_SOCK environment variable to %t/ssh-agent.socket. %t  is a systemd specifier that resolves to a runtime directory.

ExecStart defines the command to start the ssh-agent, /usr/bin/ssh-agent is the ssh-agent binary. The -D flag tells the agent to run in the foreground and lastly, ” -a $SSH_AUTH_SOCK” specifies the socket to use for communication, which is the value of the SSH_AUTH_SOCK.

WantedBy specifies the target under which this service should be enabled.

Subsequently,  for ssh-agent to work properly, we need to set the SSH_AUTH_SOCK environment variable so that any new shell session can find the ssh-agent socket.

Additionally, we need to edit the system-wide configurations. Let’s add the following lines to the PAM environment file:

$ sudo vi /etc/environment
SSH_AUTH_SOCK=/run/user/$(id -u)/ssh-agent.socket

After creating the service file, we need to enable and start the service. Firstly, let’s reload systemd:

$ sudo systemctl daemon-reload

Let’s enable the service to start at boot:

$ sudo systemctl enable ssh-agent.service

Next, let’s start the service and check its status:

$ sudo systemctl start ssh-agent.service
$ sudo systemctl status ssh-agent.service
● ssh-agent.service - SSH Key Agent
     Loaded: loaded (/etc/systemd/system/ssh-agent.service; enabled; preset: >
     Active: active (running) since Sun 2024-07-28 05:59:07 EDT; 12min ago
   Main PID: 755 (ssh-agent)
      Tasks: 1 (limit: 1586)
     Memory: 1.6M (peak: 1.7M)
        CPU: 50ms
     CGroup: /system.slice/ssh-agent.service
             └─755 /usr/bin/ssh-agent -D -a /run/ssh-agent.socket

3.2. Additional Configurations

Once ssh-agent is running, we need to load our SSH keys into it. This can be done either manually or automatically upon login:

$ eval $(ssh-agent)
Agent pid 31761
$ ssh-add ~/.ssh/location_to_key
Enter passphrase for /home/kali/.ssh/mykey:
Identity added: /home/kali/.ssh/mykey (kali@kali)

To automatically load our private key once the ssh-agent is running, we need to edit our shell’s startup files. This will ensure that ssh-agent starts the SSH_AUTH_SOCK  environment variable and sets it to our private key every time we start a new shell session.

Depending on the shell we’re using, we need to edit the corresponding startup file. For bash, we’ll edit ~/.bashrc or ~/.bash_profile ( ~/.zshrc for zsh):

$ vi ~/.bash_profile

Let’s add the following lines:

if [ -z "$SSH_AUTH_SOCK" ]; then
    eval $(ssh-agent -s)
fi

`ssh-add -l > /dev/null 2>&1 || ssh-add ~/.ssh/private_key`

Following, let’s save the file and reboot.

After the computer is up, let’s confirm the ssh-agent is running and the keys were loaded successfully:

$ echo $SSH_AUTH_SOCK
/tmp/ssh-MJJlfwyRVaXb/agent.892

$ ssh-add -l
256 SHA256:IGBASNE75LTFiyOfO1ujC8ZhTLJPQ5h4qN2eun16THM kali@kali (ED25519)

We need to ensure that the permissions on our private keys are set correctly. They should be readable only by the owner:

$ chmod 600 ~/.ssh/private_key

If we encounter issues with the SSH_AUTH_SOCK environment variable, we might need to troubleshoot by checking if the variable is correctly set in all our shell sessions.

Importantly, if the ssh-agent service fails to start, we can check the journal logs for detailed error messages:

$ sudo journalctl -u ssh-agent.service

Lastly, if our SSH key is not loaded automatically, let’s ensure the ~/.bash_profile is sourced properly. We can do this by adding the following line to ~/.bashrc:
By following these steps and ensuring proper configuration, we can successfully start and use ssh-agent as a systemd unit, making SSH key management more seamless and secure.

4. Conclusion

In this tutorial, we’ve looked at ssh-agent and how we can run it as a systemd service. We’ve mentioned that ssh-agent is an essential tool for anyone frequently using SSH as it streamlines the authentication process, improves security, and integrates seamlessly with other tools and services.

Additionally, we looked at how we can utilize systemd features to effectively automate authentication at boot. By leveraging ssh-agent, we can make our SSH-based workflows more efficient and secure.