Skip to Content

3 ways to fix SSH Permission denied (publickey)

When you receive the error message “SSH Permission denied (publickey)”, it means that there is a problem with the authentication process using a public key. This is because the server is not able to recognize the key.

  1. The public key is not added to the authorized_keys file on the instance.
  2. Incorrect permissions on the authorized_keys file.
  3. Incorrect permissions on the .ssh directory on the instance.
  4. The public key is not in the correct format.

 

In this article,  we will dive into this issue and see how to troubleshoot it.

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 key 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 of SSH command 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: v01@openssh.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.

 

use correct SSH 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 also specify a key file in ssh command.
  • To specify a specific key file, you can use the -i option followed by the path to the key file. For example:
    ssh -i /path/to/keyfile user@example.com
    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:
    Host example.com
          IdentityFile /path/to/keyfile

 

Use correct username in ssh command

Using the correct username in the SSH command is essential to avoid the “Permission denied (publickey)” error.

  • The SSH key-based authentication relies on the association between the private key on the client side and the corresponding public key stored in the ~/.ssh/authorized_keys file on the remote server.
  • When you attempt to establish an SSH connection, the server checks if the provided username has a matching public key in the authorized_keys file in their home directory.
  • Each user on the remote server has their own authorized_keys file, which contains their authorized public keys. When you specify a username in the SSH command, the server knows which authorized_keys file to look into for the matching public key.
  • If you use the wrong username, the server searches for the corresponding authorized_keys file associated with that username. If the username does not exist or if the public key is not present in that user’s authorized_keys file, the server denies access, resulting in the “Permission denied (publickey)” error.

 

Check SSH key file permission on client side

If you are using ssh key authentication, verify that you have these permissions to the .ssh folder in your home directory:

chmod 700 ~/.ssh
chmod 644 ~/.ssh/*.pub
chmod 600 ~/.ssh/id_rsa (or any other files that have your private keys stored in them)
chmod 644 ~/.ssh/known_hosts (contains hosts that you’ve connected to via SSH)

To check the key file’s permissions on the client side in Linux or macOS:

  1. Open a terminal and navigate to the SSH key directory: cd ~/.ssh/
  2. List files and their permissions: ls -l
  3. Ensure the private key (id_rsa) has permissions 600 (-rw——-) and the public key (id_rsa.pub) has permissions 644 (-rw-r–r–).
  4. Adjust permissions if necessary: chmod 600 id_rsa and chmod 644 id_rsa.pub.
  5. Verify permissions: ls -l to confirm the changes.

 

check authorized_keys file permission on remote server

To check the permissions of the authorized_keys file on a remote server:

  1. Use the ssh command with the ls command in a one-liner:
    ssh username@remote_server_ip "ls -l ~/.ssh/authorized_keys"
    
  2. Replace username with the username on the remote server.
  3. Replace remote_server_ip with the IP address or hostname of the remote server.
  4. The output will display the permissions of the authorized_keys file, showing if it has the appropriate security settings for SSH key-based authentication.

 

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.

The authorized_keys file should have strict permissions to ensure that only the user and the server administrator can access it.

The recommended file 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. Connect to the remote server using the ssh command and view the contents of the authorized_keys file:

ssh user@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.

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.

Check SSH login log on remote server

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.

To check the SSH login log on a remote server:

  1. Connect to the remote server using SSH: ssh username@remote_server_ip
  2. View the SSH login log file:
    • For Debian-based systems: sudo less /var/log/auth.log or sudo cat /var/log/auth.log
    • For Red Hat-based systems: sudo less /var/log/secure or sudo cat /var/log/secure
  3. Analyze the log for SSH login attempts and details.
  4. Exit the remote server: Type exit to return to your local machine.

 

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[1234]: 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 should contain the error message “Permission denied (publickey)”.

Daniel Lim

Sunday 10th of December 2023

Thanks for the detailed steps. It works for me. Thanks.