SSH Key Authentication Failure: Debugging “Permission denied (publickey)” When Setting Up MySQL Tunnel


1 views

When attempting to establish an SSH tunnel between virtual machines for MySQL access, many developers encounter the frustrating "Permission denied (publickey)" error. This typically occurs during the ssh-copy-id process, where the system seems to reject valid credentials.

The reported setup involves:

Host A: Physical Linux machine
VM B: MySQL server (target)
VM C: Client machine (source)

The goal is passwordless authentication from C → A → B for persistent MySQL tunneling.

First, verify your key pair integrity:

# On client machine (C)
ssh-keygen -l -f ~/.ssh/id_rsa
ssh-keygen -l -f ~/.ssh/id_rsa.pub
# Should show matching fingerprints

On Host A, ensure these settings in /etc/ssh/sshd_config:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no  # Temporarily set to yes for debugging
PermitEmptyPasswords no

After changes, restart SSH:

sudo systemctl restart sshd  # For systemd systems
# OR
sudo service ssh restart    # For older systems

Use verbose SSH output to identify failures:

ssh -vvv -i ~/.ssh/id_rsa user@hostA -p port
# Look for these key messages:
# - "Offering public key"
# - "Server accepts key"
# - "Authentication succeeded"

When ssh-copy-id fails, manually append the public key:

# On client (C)
cat ~/.ssh/id_rsa.pub | ssh user@hostA "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Critical permission requirements:

Client (C):
~/.ssh: 700
~/.ssh/id_rsa: 600
~/.ssh/id_rsa.pub: 644

Server (A):
~/.ssh: 700
~/.ssh/authorized_keys: 600

For automatic reconnection, create a systemd service:

[Unit]
Description=MySQL SSH Tunnel
After=network.target

[Service]
User=youruser
ExecStart=/usr/bin/ssh -N -L 3306:localhost:3306 user@hostB -i /home/user/.ssh/id_rsa
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
  • Conflicting keys in multiple authorized_keys files
  • Mismatched key algorithms (RSA vs ED25519)
  • Firewall blocking SSH port
  • SELinux/AppArmor restrictions

Check key usage in auth logs:

# On server (A)
sudo tail -f /var/log/auth.log | grep -i "publickey"
# Look for "Accepted publickey" or "Failed publickey" messages

When attempting to set up passwordless authentication between machine C and machine A (hosting VM B with MySQL), the ssh-copy-id operation fails with:

ssh-copy-id -i id_rsa.pub user@host -p port
Enter passphrase for key '/home/user/.ssh/id_rsa':
Permission denied (publickey).

First, verify your key pair integrity:

# On machine C (source)
ssh-keygen -lf ~/.ssh/id_rsa.pub
ssh-keygen -lf ~/.ssh/id_rsa

# On machine A (destination)
cat ~/.ssh/authorized_keys | while read line; do 
  echo $line | ssh-keygen -lf -; 
done

This helps identify if the public key exists in the destination's authorized_keys with matching fingerprint.

Run in verbose mode to pinpoint the failure:

ssh -vvv -i ~/.ssh/id_rsa user@host -p port

Critical things to check in the output:

  • Which identity file is being offered
  • Server's accepted authentication methods
  • Exact point where authentication fails

On machine A (destination), verify these settings in /etc/ssh/sshd_config:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no # Temporarily set to yes for debugging
ChallengeResponseAuthentication no

Reload SSH daemon after changes:

sudo systemctl restart sshd
# Or for older systems:
sudo /etc/init.d/ssh restart

If ssh-copy-id fails, manually append the key:

# On machine C
cat ~/.ssh/id_rsa.pub | ssh user@host -p port "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Then fix permissions:

ssh user@host -p port "chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys"

Ensure your private key is loaded in the agent:

eval ssh-agent
ssh-add ~/.ssh/id_rsa  # Enter passphrase when prompted
ssh-add -l  # Verify loaded keys
Symptom Possible Cause Solution
Permission denied immediately Server not accepting publickey auth Check sshd_config PubkeyAuthentication
Passphrase prompt then denial Key mismatch or wrong passphrase Verify key fingerprints match
Works with password auth only authorized_keys permissions wrong chmod 600 authorized_keys

Once authentication works, create persistent tunnel:

autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-N -L 3306:localhost:3306 user@host -p port -i ~/.ssh/id_rsa

For systemd service (create /etc/systemd/system/mysql-tunnel.service):

[Unit]
Description=MySQL SSH Tunnel
After=network.target

[Service]
User=youruser
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -L 3306:localhost:3306 user@host -p port -i /home/youruser/.ssh/id_rsa
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target