During
keyring
configuration for the Nextcloud client (see the Linux: the Nextcloud client, qtkeychain and the “The name org.freedesktop.secrets was not provided by any .service files” error post) – I decided to clean up the mess in my SSH keys, as I have a lot of them and sometimes authentication became just pain.
In general to make this simpler one can use system-wide storage like gnome-keyring
or KeeyPassXC, but we will speak about them in the next post.
Today, let’s discuss ssh-agent
and how to use it to manage password-protected RSA keys for SSH authentication without such a backends.
Examples below performed on an Arch Linux installation with some additional tests Manjaro Linux with Budgie DE.
ssh-agent
is intended to manage a user’s
Running the agent
Just perform:
For clients, such as ssh-client or git, they need to know the following variables:
SSH_AGENT_PID
: a startedssh-agent
PID, that will be sued for example to kill it withssh-agent -k
SSH_AUTH_SOCK
: a path to a UNIX socket file which will be used to communicate to thessh-agent
from clients (ssh
,git
, etc)
To run an agent without displaying these variables and to apply them – do the next:
There are few various ways to run the agent, we will take a closer look at the Running ssh-agent with multitype terminals part.
Examples
Let’s take an overview of ssh-agent
basic usage.
A key generation
Create a new key:
Options here:
-t
: type, RSA-b
: a key’s length in bits (by default 3072 for RSA)-f
: a path to the key’s file (by default~/.ssh/id_rsa
)-C
: a comment for the key (by default username@hostname)-P
: a key’s password
Checking SSH-key’s password
To check a password for a key you can use thessh-keygen
with -y
to display information about this key, and this will ask you to enter this key’s password:
ssh-copy-id
– copy a key to a remote host
You can copy a key manually, by getting its public part from the test-key.pub file:
And by adding it to the ~/.ssh/authorized_keys
on a target host.
Another way, the recommended one, is to use an ssh-copy-id
utility which will do the same but also will keep an eye on folders/files permissions – the most frequent problem during SSH RSA-based authentification:
Now you can log in using this key:
ssh-add
Okay, so now we do have a password-protected RSA key for SSH authentication.
But during each SSH-login, you’ll have to enter its password again and again and this will be a real pain when using a lot of connections and keys.
To avoid this issue – add a key to the ssh-agent
using ssh-add
.
Check if it is running:
Could not open a connection to your authentication agent
The most common problem is when ssh-add
is not able to connect to an agent:
At first – check if it’s PID is set from the SSH_AGENT_PID
, or by checking the $SSH_AUTH_SOCK
variable as all communication is gone via the socket-file specified by this variable:
Here is it empty, because thessh-agent
was started in another terminal instance (we will speak soon how to handle it).
For now – kill all already running instances:
And run an agent’s instance anew:
We are using the-s
option as not everybody will do the steps above from the exactly bash
shell and eval
to apply the strings from the agent’s output (export SSH_AUTH_SOCK
).
Check again:
And ssh-add
:
All done here.
Adding a key
Run:
Checking keys
Use the -l
option to check which keys are already loaded to an agent’s instance:
Deleting key(s)
Use -d
to delete one key:
And -D
to delete all keys at once:
Automatically adding keys to ssh-agent
To make ssh
(and git
for example) adding used keys to an ssh-agent
without the necessity to run ssh-add
manually you can add the AddKeysToAgent
~/.ssh/config
and specify one of the following options – yes, confirm or ask (см. SSH_ASKPASS
Let’s check – there is nothing added at this moment:
Make a connection, enter a key’s password:
Disconnect, and check keys in the agent now:
On the next connection – the ssh
client will use the key from the agent and will not ask you for the key’s password again:
Running ssh-agent
with multitype terminals
Another big question is what to do when you have few bash-sessions, for example in various terminals’ tabs, as it will not has the $SSH_AUTH_SOCK
variable set and an ssh client will not be able to communicate with an already running ssh-agent
instance.
I.e. when you’ll run ssh-add
in a new terminal – you’ll see the already mentioned “Could not open a connection to your authentication agent” error:
~/.bashrc
There is a few ways to make the initialization of the variables during new bash session initialization, for example, you can add the following to your ~/.bashrc
:
if [ -z "$SSH_AUTH_SOCK" ] ; then eval `ssh-agent -s` ssh-add /home/setevoy/.ssh/test-key fi
But in this case, each bash-sessions will has its own ssh-agent running, which is not a problem but maybe not what you’d like to have.
Another way could be the following code added to the ~/.bashrc
:
ssh-add -l &>/dev/null if [ "$?" == 2 ]; then test -r ~/.ssh-agent-env && \ eval "$(<~/.ssh-agent-env)" >/dev/null ssh-add -l &>/dev/null if [ "$?" == 2 ]; then (umask 066; ssh-agent > ~/.ssh-agent-env) eval "$(<~/.ssh-agent-env)" >/dev/null ssh-add /home/setevoy/.ssh/test-key fi fi
Here (see response codes in the ssh-agent
- try to execute
ssh-add -l
, and redirect output to the/dev/null
- check returned code of the previous command:
- if it is == 2 (error connect to an agent):
- check if
~/.ssh-agent-env
is present and available for reading, read it and pass its output to thebash
- retry
ssh-add -l
- if code still 2:
- create the
~/.ssh-agent-env
file with the 660 permissions (read-write for an owner only) - start
ssh-agent
and redirects its output into the.ssh-agent-env
file - read the
.ssh-agent-env
content and pass it via a pipe to thebash
- run
ssh-add /home/setevoy/.ssh/test-key
- create the
- check if
- if it is == 2 (error connect to an agent):
Not a bad solution, and in this way all our sessions will use the same agent, although some guides suggesting to have different agents for personal and work usage
systemd
Another solution could be to create a dedicated systemd
service by adding a unit file and by running ssh-agent
as a systemd
service, see the
Create a directory if not added yet:
And create a ~/.config/systemd/user/ssh-agent.service
file there:
[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
Next, Wiki told about the ~/.pam_environment
file for variables, but in my current case I have Openbox and usually set variables via .config/openbox/autostart
file:
By the way, recalled about about such a thing as setting default values in BASH – BASH: переменные — передача значений по-умолчанию ${var:-defaultvalue}, замена значений — ${var:+alternatevalue} и сообщений — ${var:?message} (Rus)
Now, stop all agents running:
Check the $XDG_RUNTIME_DIR
For now, set the $SSH_AUTH_SOCK
variable manually:
And run an agent via systemctl --user
:
Check it:
A socket’s variable:
And try ssh-add
:
“It works!” (c)
You can add to autostart now:
~/.xinitrc
One more way you can use is by adding the agent’s start to the~/.xinitrc
.
In this case, when you’ll execute the startx
(for example, as in my case, when I have no any login manager, and X.Org is started manually by entering the startx
in the console) – at first, an agent will be started and the – an Openbox session, see the
Also, as already mentioned at the very beginning of this post, there other implementations for the key’s backends that can be used alongside or instead of the ssh-agent
– kind of “wrappers” that will be or “proxy” requests from an ssh client to an ssh-agent
‘s instance, or will fully replace the ssh-agent itself and will store keys and passwords themselves, but we will speak about them in a following post(s?)..
Similar posts
Also published on