How to Fix SSH Permission denied (publickey) Error in Linux
Resolve the "Permission denied (publickey)" SSH error quickly. Learn how to fix incorrect file permissions, missing keys, and sshd_config issues on Linux.
- Incorrect file permissions on the remote server's ~/.ssh directory (requires 700) or authorized_keys file (requires 600) trigger StrictModes rejection.
- Missing or mismatched public keys between the client's ssh-agent and the remote server's authorized_keys file prevent authentication.
- Legacy RSA keys (ssh-rsa) are deprecated in OpenSSH 8.8+ and will result in silent publickey rejections unless explicitly permitted or upgraded to ED25519.
- Quick fix summary: Run 'ssh -v' to identify the failing key, ensure client keys are loaded via 'ssh-add', and enforce strict ownership and permissions on the remote ~/.ssh directory.
| Method | When to Use | Time | Risk |
|---|---|---|---|
| Fixing Directory/File Permissions | Server logs show 'Authentication refused: bad ownership or modes' | 2 mins | Low |
| Adding Key via ssh-copy-id | Public key is entirely missing from the remote server | 1 min | Low |
| Modifying sshd_config | Server globally rejects public keys or uses custom AuthorizedKeysFile paths | 5 mins | Medium |
| Restoring SELinux Contexts | On RHEL/CentOS when permissions are correct but access is still denied | 3 mins | Low |
Understanding the Error
The user@hostname: Permission denied (publickey) error is a security mechanism enforced by the SSH daemon (sshd). It occurs when the SSH server and client fail to negotiate a mutually acceptable cryptographic key for authentication. Unlike password authentication, which simply checks a string, public key authentication requires the server to verify that the client possesses the private half of a public key listed in the target user's ~/.ssh/authorized_keys file.
When sshd rejects the connection, it drops the connection to prevent brute-force attacks. The underlying root cause almost always falls into one of four categories: incorrect file permissions (triggering StrictModes), missing keys, client-side configuration issues, or server-side security policies (like SELinux or sshd_config directives).
Step 1: Diagnose the Handshake
Before changing configurations, you must identify exactly where the failure occurs. Use verbose mode on the SSH client to trace the authentication steps:
ssh -vvv user@remote_server_ip
Analyze the output for the following critical lines:
debug1: Offering public key: /home/user/.ssh/id_rsa RSA SHA256:...: This confirms your client is attempting to use a specific key.debug1: send_pubkey_test: no mutual signature algorithm: This indicates a modern OpenSSH client rejecting an older RSA key algorithm.debug1: Authentications that can continue: publickey: The server is explicitly demanding a public key and rejecting the ones offered.
If you have root access to the remote server via an out-of-band console, tail the secure log to see the server's perspective:
tail -f /var/log/auth.log # Debian/Ubuntu
tail -f /var/log/secure # RHEL/CentOS/Rocky
Look for errors like Authentication refused: bad ownership or modes for directory /home/user/.ssh.
Step 2: Fix Server-Side File Permissions and Ownership
By default, OpenSSH enforces StrictModes yes. This means if your .ssh directory or authorized_keys file is readable or writable by other users, SSH will silently ignore your keys to protect you from compromised local accounts.
Execute the following commands on the remote server to enforce the correct security posture:
- Fix ownership (ensure the user owns their own files):
sudo chown -R $USER:$USER ~/.ssh - Fix directory permissions (Read/Write/Execute for owner ONLY):
chmod 700 ~/.ssh - Fix file permissions (Read/Write for owner ONLY):
chmod 600 ~/.ssh/authorized_keys
Step 3: Address OpenSSH 8.8+ RSA Deprecation
If you recently upgraded your OS (e.g., to Ubuntu 22.04 or macOS Ventura), OpenSSH 8.8 disabled ssh-rsa signatures using the SHA-1 hash algorithm due to security vulnerabilities. If you are using an old RSA key, the server will reject it.
Best Practice Fix: Generate a new, secure ED25519 key.
ssh-keygen -t ed25519 -C "your_email@example.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_server_ip
Temporary Workaround: If you must use the legacy RSA key (e.g., connecting to a legacy network appliance), edit your client-side ~/.ssh/config:
Host remote_server_ip
PubkeyAcceptedKeyTypes +ssh-rsa
Step 4: Verify sshd_config on the Server
If permissions are correct and keys are modern, the SSH daemon itself might be configured to reject public keys. Check the configuration file on the server:
sudo nano /etc/ssh/sshd_config
Ensure the following directives are set (and not commented out):
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
If you made changes, restart the SSH service:
sudo systemctl restart sshd
Step 5: Resolve SELinux Contexts (RedHat/CentOS)
On SELinux-enforcing systems, if the ~/.ssh directory was copied or moved incorrectly, it might have the wrong security context, making it invisible to the sshd process.
Restore the default SELinux contexts for the SSH directory:
restorecon -Rv ~/.ssh
This command forces SELinux to apply the default labels specified in the system policy to your SSH configuration files.
Frequently Asked Questions
#!/bin/bash
# Diagnostic and remediation script for remote server SSH permissions
# Run this ON THE REMOTE SERVER for the affected user
USER_HOME=$(eval echo ~$USER)
SSH_DIR="$USER_HOME/.ssh"
AUTH_KEYS="$SSH_DIR/authorized_keys"
echo "[+] Fixing SSH permissions for $USER at $USER_HOME"
# 1. Ensure home directory isn't group/world writable
chmod go-w "$USER_HOME"
echo "[-] Set $USER_HOME permissions to block group/world write."
# 2. Create .ssh if missing and set directory permissions
if [ ! -d "$SSH_DIR" ]; then
mkdir -p "$SSH_DIR"
echo "[-] Created $SSH_DIR directory."
fi
chmod 700 "$SSH_DIR"
echo "[-] Set $SSH_DIR permissions to 700 (drwx------)."
# 3. Create authorized_keys if missing and set file permissions
if [ ! -f "$AUTH_KEYS" ]; then
touch "$AUTH_KEYS"
echo "[-] Created $AUTH_KEYS file."
fi
chmod 600 "$AUTH_KEYS"
echo "[-] Set $AUTH_KEYS permissions to 600 (-rw-------)."
# 4. Enforce ownership
chown -R $USER:$USER "$SSH_DIR"
echo "[-] Enforced ownership of $SSH_DIR to $USER:$USER."
# 5. Fix SELinux contexts if applicable (RHEL/CentOS)
if command -v restorecon &> /dev/null; then
restorecon -Rv "$SSH_DIR"
echo "[-] Restored SELinux security contexts for $SSH_DIR."
fi
echo "[+] Remediation complete. Please try authenticating again."Error Medic Editorial
A collective of Senior Site Reliability Engineers and Linux Systems Administrators dedicated to documenting production-grade troubleshooting methodologies.