In some cases you'll want to be able to SSH another server, without being prompted for password. For example, when dealing with PostgreSQL replication you'll need to execute a command on another server as postgres
user:
$ ssh -T postgres@OTHERHOST /etc/postgresql/9.5/main/replscripts/disable_postgresql.sh
In such cases you'll want to avoid password prompt for many reasons, i.e.:
- The previous line is part of some script so password prompt would break the script;
-
You don't know
postgres
' UNIX password anyway.
There are few important things to note:
-
In this page I've used
postgres
user, but you can do the same for any other user. -
Majority of commands should be executed impersonating the user we are establishing SSH for (
postgres
in my case). For this reason I'll always include prompts (i.e.postgres@HOST1:~$
) so that you can know on which host, and under which user the command should be executed. -
~/.ssh
refers to.ssh
subdirectory of the user's home directory. It means that it'll refer to a different directory if executed as different user. For this reason every command that includes~/.ssh
has to be executed as user we are configuring SSH for (postgres
in my case).
Create SSH Key
Create SSH key on HOST1 by executing:
root@HOST1:~# sudo -i -u postgres
postgres@HOST1:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa):
Created directory '/var/lib/postgresql/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa.
Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub.
The key fingerprint is:
e3:09:6d:0a:3e:bf:46:39:15:4c:ca:27:a4:1a:f1:4f postgres@HOST1
The key's randomart image is:
+--[ RSA 2048]----+
| . .o. |
| o + .o |
| . o E .. |
| o o +. |
| . . ooS |
| . .+= o |
| o...o |
| o. |
| .o. |
+-----------------+
Explanations:
- The first line starts postgres user impersonation session;
- The second line is key creation command;
- Select empty passphrase.
Copy SSH Key
The next step is to copy the newly created key (~/.ssh/id_rsa.pub
) to HOST2. If you are able to SSH HOST2, you can transfer the key through SSH by executing:
postgres@HOST1:~$ ssh-copy-id postgres@HOST2
But since you'll need postgres
' password at HOST2 for the previous command, chances are that you won't be able to transfer the key this way.
Manually Copy SSH Key
Alternative way to transfer the key is to simply copy key file (~/.ssh/id_rsa.pub
) to HOST2 as you would copy any other file, and then on HOST2 execute (from the directory where you've copied the key file):
root@HOST2:~# sudo -i -u postgres
postgres@HOST2:~$ cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys_Backup
postgres@HOST2:~$ cat id_rsa.pub >> ~/.ssh/authorized_keys
Explanation:
-
The second line creates just-in-case backup of
authorized_keys
file (assuming that the file already exists); -
The third line appends the key to
authorized_keys
file.
Note: it may happen that ~/.ssh
directory does not exists, in which case you should create one before creating authorized_keys
file, and assign permissions appropriately:
postgres@HOST2:~$ mkdir ~/.ssh
postgres@HOST2:~$ chmod 0700 ~/.ssh
Test SSH
Finally you can test SSH by going back to HOST1 and executing something like:
root@HOST1:~# sudo -i -u postgres
postgres@HOST1:~$ postgres@HOST2 ls /tmp
The previous command (although executed at HOST1) will list content of /tmp
directory at HOST2, without asking for password.
Host Authenticity
Although it is true that you can SSH without password this way, there's still one problem: at the first ssh execution against particular host you'll get something like:
The authenticity of host 'host2 (192.168.1.2)' can't be established.
ECDSA key fingerprint is dd:32:1b:ba:36:c4:9c:ee:2e:18:9e:aa:fb:45:91:a7.
Are you sure you want to continue connecting (yes/no)?
After confirming this for the first time, you won't be prompted again for this host. But obviously this confirmation prompt can also break the script. For this reason we'll create / change ~/.ssh/config
:
Host *
StrictHostKeyChecking no
It is also important to set the appropriate permissions to the newly created file, as described in Directory and File Permissions below. After that there won't be any prompts anymore.
The Same Key on Many Hosts
Although the previous procedure will accomplish the task, it might be too complicated in a scenario where we have multiple servers, and we want some user account (i.e. postgres
) to be able to SSH every server form any server. In this case we would have to create the key on each server, then add this key to autorized_keys
file on all other servers. Obviously it would cause countless repetitions of the previous steps, and number of repetitions exponentially grows with number of servers. (This is the problem you may encounter when establishing PostgreSQL HA cluster.)
The complexity can be significantly reduced if you don't create a new key for each host, but use existing one instead. Here's step-by-step guide:
Create SSH Key at the First Host
At the first host (HOST1) you'll create SSH key as described in Create SSH Key section, and create ~/.ssh/config
file as described in Host Authenticity section above.
Create autorized_keys
File
On the same host (HOST1) you'll create authorized_keys
file by executing:
postgres@HOST2:~$ cat id_rsa.pub >> ~/.ssh/authorized_keys
At the moment this line authorizes user to SSH HOST1 from HOST1 (itself), but after copying these files to other servers (the next section) we'll accomplish what we want.
Copy All Files to All Other Hosts
There are four files you'll want to copy (all from ~/.ssh
directory):
-
authorized_keys
-
id_rsa
-
id_rsa.pub
-
config
Since the same key will be used from all other servers, this time besides copying public key file (id_rsa.pub
), we'll also copy private key file (id_rsa
). All the files should be stored ~/.ssh
directory, of course.
After ensuring directory and file permissions as described below, you'll be able to SSH from every host to any other host.
Directory and File Permissions
If you've copied files manually you should adjust ownership and permissions appropriately. Ownership might already been set appropriately, but it won't hurt to ensure:
$ chown postgres:postgres -R ~/.ssh
The next thing to do is to ensure appropriate permissions:
$ chmod 0700 ~/.ssh
$ chmod 0644 ~/.ssh/id_rsa.pub
$ chmod 0644 ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/id_rsa
$ chmod 0600 ~/.ssh/config
Comments
Hello,
you should add "ssh" on this line: postgres@HOST1:~$ ssh postgres@HOST2 ls /tmp
otherwise command not found
Add new comment
Anonymous comments require solving captcha, and waiting for administrator's approval.