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
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
postgresuser, but you can do the same for any other user.
- Majority of commands should be executed impersonating the user we are establishing SSH for (
postgresin 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.
.sshsubdirectory 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
~/.sshhas to be executed as user we are configuring SSH for (
postgresin 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. | +-----------------+
- 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
- The second line creates just-in-case backup of
authorized_keysfile (assuming that the file already exists);
- The third line appends the key to
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
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.
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
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
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
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