<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayan Hussain</title>
    <description>The latest articles on DEV Community by Ayan Hussain (@ayanhacks).</description>
    <link>https://dev.to/ayanhacks</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4145344%2F36d8bf96-6804-471f-bebb-7ed4c7105a61.jpg</url>
      <title>DEV Community: Ayan Hussain</title>
      <link>https://dev.to/ayanhacks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayanhacks"/>
    <language>en</language>
    <item>
      <title>SSH Permission Denied (publickey): causes and fixes</title>
      <dc:creator>Ayan Hussain</dc:creator>
      <pubDate>Sun, 27 Sep 2026 10:28:54 +0000</pubDate>
      <link>https://dev.to/ayanhacks/ssh-permission-denied-publickey-causes-and-fixes-536o</link>
      <guid>https://dev.to/ayanhacks/ssh-permission-denied-publickey-causes-and-fixes-536o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://sshdock.com/blog/ssh-permission-denied-publickey" rel="noopener noreferrer"&gt;sshdock.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Permission denied (publickey)&lt;/code&gt; means you successfully connected to the server over the network, but the server rejected your authentication. You are past the firewall. The SSH daemon is running. The problem is specifically that the server refused to accept your key.&lt;/p&gt;

&lt;p&gt;This is different from &lt;code&gt;Connection refused&lt;/code&gt; (SSH not running or firewall blocking port 22) and &lt;code&gt;Connection timed out&lt;/code&gt; (server unreachable). Permission denied means the network is fine — it is the authentication step that failed.&lt;/p&gt;

&lt;p&gt;Here is how to find and fix the actual cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the server is actually checking
&lt;/h2&gt;

&lt;p&gt;Before diving into fixes, here is what the server verifies when you connect with a key:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; exist on the server for your user?&lt;/li&gt;
&lt;li&gt;Does it contain a line that matches your public key?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;~/.ssh/&lt;/code&gt; set to permission &lt;code&gt;700&lt;/code&gt; (not group or world writable)?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; set to &lt;code&gt;600&lt;/code&gt; (not group or world writable)?&lt;/li&gt;
&lt;li&gt;Is the private key the correct pair for one of those public keys?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The server silently ignores &lt;code&gt;authorized_keys&lt;/code&gt; if any permission check fails, and falls back to password auth (or rejects entirely). This is the most common source of confusion — the file exists with the right key, but wrong permissions means the server never reads it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Run SSH with verbose output
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;-vvv&lt;/code&gt; to your command first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-vvv&lt;/span&gt; user@your-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for lines like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="k"&gt;debug1&lt;/span&gt;: Offering public key: /home/you/.ssh/id_ed25519 ED25519
&lt;span class="k"&gt;debug1&lt;/span&gt;: Authentications that can continue: publickey
&lt;span class="k"&gt;debug1&lt;/span&gt;: No more authentication methods to try.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it says "Offering public key" but then moves on without success, the server received your key and rejected it. If it says "No identities found", your SSH agent is empty — skip to Step 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Check authorized_keys on the server
&lt;/h2&gt;

&lt;p&gt;If you have console access or password login, check the file and its permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; ~/.ssh/
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/authorized_keys
&lt;span class="nb"&gt;stat&lt;/span&gt; ~/.ssh/
&lt;span class="nb"&gt;stat&lt;/span&gt; ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Permissions must be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.ssh/          → 700  (drwx------)
authorized_keys  → 600  (-rw-------)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix them if wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;700 ~/.ssh
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also verify ownership:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; ~ | &lt;span class="nb"&gt;grep&lt;/span&gt; .ssh
&lt;span class="c"&gt;# Should be owned by your user, not root&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; youruser:youruser ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Verify you are using the right key
&lt;/h2&gt;

&lt;p&gt;Check what keys are loaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.ssh/
ssh-add &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the agent is empty or missing your key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or specify the key file explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/my-specific-key.pem user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare your local public key to what is in &lt;code&gt;authorized_keys&lt;/code&gt; on the server. A common mistake: the key pair was separated — the private and public keys are from different generations and do not match.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add the public key to the server
&lt;/h2&gt;

&lt;p&gt;The most common scenario for new servers — you forgot to copy the public key.&lt;/p&gt;

&lt;p&gt;If you have password access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-copy-id user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;ssh-copy-id&lt;/code&gt; is not available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519.pub | ssh user@server &lt;span class="s2"&gt;"mkdir -p ~/.ssh &amp;amp;&amp;amp; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys &amp;amp;&amp;amp; chmod 600 ~/.ssh/authorized_keys"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: AWS EC2 — username and key pair issues
&lt;/h2&gt;

&lt;p&gt;AWS has a few specific gotchas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong username.&lt;/strong&gt; Each AMI uses a different default username:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;AMI&lt;/th&gt;
&lt;th&gt;Username&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Amazon Linux 2 / 2023&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ec2-user&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ubuntu&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debian&lt;/td&gt;
&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CentOS / RHEL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ec2-user&lt;/code&gt; or &lt;code&gt;centos&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fedora&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fedora&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key pair mismatch.&lt;/strong&gt; EC2 instances are configured at launch with one specific key pair. Connecting with any other key will fail regardless of &lt;code&gt;authorized_keys&lt;/code&gt;. The key pair cannot be changed through the console after launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PEM format.&lt;/strong&gt; AWS &lt;code&gt;.pem&lt;/code&gt; files are standard OpenSSH private keys — do not convert them unless you are using PuTTY.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: PasswordAuthentication is disabled
&lt;/h2&gt;

&lt;p&gt;If password auth is disabled and your key fails, there is no fallback. The error looks identical.&lt;/p&gt;

&lt;p&gt;Check the server config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; passwordauthentication /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you locked yourself out but have console access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/PasswordAuthentication no/PasswordAuthentication yes/'&lt;/span&gt; /etc/ssh/sshd_config
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect with your password, fix the key setup, then re-disable password auth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: SELinux (RHEL / CentOS / Amazon Linux)
&lt;/h2&gt;

&lt;p&gt;SELinux can block SSH from reading &lt;code&gt;authorized_keys&lt;/code&gt; even when file permissions look correct. Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ausearch &lt;span class="nt"&gt;-m&lt;/span&gt; avc &lt;span class="nt"&gt;-ts&lt;/span&gt; today | &lt;span class="nb"&gt;grep &lt;/span&gt;ssh
&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/audit/audit.log | &lt;span class="nb"&gt;grep &lt;/span&gt;denied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;restorecon &lt;span class="nt"&gt;-Rv&lt;/span&gt; ~/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is common when &lt;code&gt;.ssh/&lt;/code&gt; was created by copying files manually rather than through &lt;code&gt;ssh-keygen&lt;/code&gt; or &lt;code&gt;ssh-copy-id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Read the server-side logs
&lt;/h2&gt;

&lt;p&gt;The server logs the exact reason for auth failures — far more detail than the client output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/auth.log          &lt;span class="c"&gt;# Ubuntu/Debian&lt;/span&gt;
&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/secure            &lt;span class="c"&gt;# RHEL/CentOS/Amazon Linux&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; sshd &lt;span class="nt"&gt;-f&lt;/span&gt;              &lt;span class="c"&gt;# Systemd systems&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch while making a connection attempt. You will see exactly what failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication refused: bad ownership or modes for directory /home/user/.ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick diagnostic checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Local machine: what key is being offered?&lt;/span&gt;
ssh &lt;span class="nt"&gt;-vvv&lt;/span&gt; user@server 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(Offering|denied|refused|try)"&lt;/span&gt;

&lt;span class="c"&gt;# Keys loaded in agent?&lt;/span&gt;
ssh-add &lt;span class="nt"&gt;-l&lt;/span&gt;

&lt;span class="c"&gt;# Force a specific key:&lt;/span&gt;
ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/correct-key.pem user@server

&lt;span class="c"&gt;# On the server: check if your public key is in authorized_keys&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/authorized_keys | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519.pub | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If you need to SSH from a browser without any local setup, &lt;a href="https://sshdock.com/app" rel="noopener noreferrer"&gt;SSHDock&lt;/a&gt; is a free web-based SSH client that handles RSA and Ed25519 PEM keys directly — no conversion or agent setup needed.&lt;/p&gt;

&lt;p&gt;For a complete key setup walkthrough, see the &lt;a href="https://sshdock.com/blog/ssh-key-authentication-guide" rel="noopener noreferrer"&gt;SSH key authentication guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>linodehackathon</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
