SSH Permission denied (publickey) issue error occurs when you are trying to authenticate using a public key and the server is unable to accept your key.
This could be because the key is not in the authorized_keys file on the server, or because the permissions on the authorized_keys file or ~/.ssh directory are not set correctly.
In this article, I will explain how to troubleshoot this issue and how to fix it in 3 ways.
What is SSH public key authentication in Linux
Public key authentication is a method of securely authenticating a user to a remote computer using a pair of cryptographic keys.
We will need to have a private key stored on our local machine and a corresponding public key stored on the remote server.
The private key will be used by the ssh client to authenticate the connection, and the public key will be used by the ssh server to verify the authenticity of the private key.
When the ssh client runs this command, it will use the private key file specified with the -i flag to authenticate the connection.
The ssh server will use the corresponding public key stored in the ~/.ssh/authorized_keys file to verify the authenticity of the private key.
If the public key matches the private key, the ssh client will be authenticated and a secure shell session will be established.
If the private way is not accepted, you might see a permission denied (publickey) error.
Public key authentication is considered to be more secure than password-based authentication. It is much harder for an attacker to obtain a user’s private key than it is to guess their password.
Enable verbose output on client side
If you are unable to login into remote server, you can try connecting using the -vvvv flag to enable verbose output, which will provide more information about the SSH connection process.
It can be helpful in troubleshooting issues with the connection.
Here’s an example of what the output of the ssh -vvvv command might look like:
OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n 7 Dec 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug2: resolving "example.com" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to example.com [192.0.2.1] port 22.
debug1: Connection established.
debug1: identity file /home/user/.ssh/id_rsa type 0
debug1: key_load_public: No such file or directory
debug1: key_load_public: No such file or directory
debug1: Local version string SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
debug1: match: OpenSSH_7.6p1 Ubuntu-4ubuntu0.3 pat OpenSSH* compat 0x04000000
debug2: fd 3 setting O_NONBLOCK
debug1: Authenticating to example.com:22 as 'user'
debug3: hostkeys_foreach: reading file "/home/user/.ssh/known_hosts"
debug3: record_hostkey: found key type ECDSA in file /home/user/.ssh/known_hosts:1
debug3: load_hostkeys: loaded 1 keys from example.com
debug3: order_hostkeyalgs: prefer hostkeyalgs: email@example.com,firstname.lastname@example.org,email@example.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp
Let us see what happens when you run the ssh -vvvv command:
- The ssh client starts and reads the configuration files in the ~/.ssh directory (e.g., ~/.ssh/config).
- The ssh client attempts to establish a connection to the ssh server using the specified hostname or IP address.
- If the connection is successful, the ssh client and server negotiate a mutually acceptable encryption algorithm and exchange keys to use for encrypting and decrypting data sent over the connection.
- If a password is required to log in to the server, the ssh client prompts the user for the password. If the password is correct, the ssh client logs the user in to the server.
- If the ssh client is able to log in to the server, a secure shell session is established between the client and server, and the user can enter commands on the client that are executed on the server.
Check SSH login log on remote server
We can also check this issue on server side. You can check the logs on the remote host for any messages related to the SSH login attempt.
The logs are usually located in the /var/log/auth.log or /var/log/secure file and can provide more information about the issue.
You can also try connecting to the remote host using a different user or from a different machine to see if the issue is with the user or the specific machine you are using.
Here is an example of an entry in the /var/log/secure file that shows a successful login using the ssh command:
Jan 3 20:23:11 example sshd: Accepted publickey for user from 192.0.2.1 port 54321 ssh2: RSA SHA256:abcdefghijklmnopqrstuvwxyz0123456789
This entry shows that a user was able to login to the system using the ssh command on January 3 at 20:23:11.
The login was accepted using a public key, and the user authenticated from IP address 192.0.2.1 on port 54321 using the RSA algorithm and a SHA256 fingerprint.
If there was an issue with the login, the log entry would contain an error message instead of “Accepted publickey”.
For example, if the user was unable to authenticate using a public key, the log entry might contain the error message “Permission denied (publickey)”.
use correct key file in ssh command
By default, the ssh command will look for the private key file in the ~/.ssh directory on the local machine, and it will use a file called id_rsa if it exists.
If the id_rsa file does not exist, the ssh command will use a file called id_dsa if it exists. We can specify a key file in ssh command.
To specify a specific key file to use with the ssh command, you can use the -i option followed by the path to the key file. For example:
ssh -i /path/to/keyfile firstname.lastname@example.org
This will tell ssh to use the key file located at /path/to/keyfile when connecting to the remote host.
If you want to use a different key file by default, you can specify the path to the key file in your ~/.ssh/config file. For example:
This will tell ssh to use the key file located at /path/to/keyfile whenever you connect to the host example.com.
check authorized_keys file permission on remote server
The authorized_keys file is used to store public keys that are authorized to log in to a server using the ssh command.
When a user tries to log in to a server using ssh, the server checks the authorized_keys file to see if the user is allowed to log in.
If the user’s public key is found in the authorized_keys file, the user is allowed to log in.
The authorized_keys file is usually stored in the ~/.ssh directory of the user’s home directory on the server. It is a plain text file that contains one public key per line.
Public keys are added to the authorized_keys file by the server administrator, or by the user themselves if they have permission to modify the file.
The authorized_keys file should have strict permissions to ensure that only the user and the server administrator can access it.
The recommended permissions for the authorized_keys file are 600 (readable and writable only by the owner).
The ~/.ssh directory should have permissions of 700 (readable, writable, and executable only by the owner).
By default, the ssh daemon (sshd) is configured to look for the authorized_keys file in the ~/.ssh directory of the user’s home directory.
However, the location of the authorized_keys file can be customized in the sshd_config file.
verify public key with authorized_keys file on remote server
To verify that a public key is present in the authorized_keys file on a remote server, you can use the ssh-keygen command on the client machine to extract the public key from the private key file, and then use the ssh command to connect to the remote server and check the contents of the authorized_keys file.
Here’s an example of how you can extract the public key from a private key file and check the authorized_keys file on a remote server:
Extract the public key from the private key file using the ssh-keygen command:
ssh-keygen -y -f /path/to/private_key > public_key
This will generate a file called public_key that contains the public key extracted from the private key file located at /path/to/private_key.
Connect to the remote server using the ssh command and view the contents of the authorized_keys file:
ssh email@example.com "cat ~/.ssh/authorized_keys"
This will connect to the remote host as user and display the contents of the authorized_keys file on the remote host.
Compare the public key extracted from the private key file with the contents of the authorized_keys file.
If the public key is present in the authorized_keys file, then the key is authorized to log in to the server.
You can also use the grep command to search for the public key in the authorized_keys file. For example:
ssh firstname.lastname@example.org "grep '`cat public_key`' ~/.ssh/authorized_keys"
This will search for the contents of the public_key file in the authorized_keys file on the remote host.
If the public key is found, the command will output the matching line from the authorized_keys file. If the public key is not found, the command will not output anything.
If the public key is not in the authorized_keys file, you can copy the key and past it into the file, or use the ssh-copy-id command to automatically add the key to the file.