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


22 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