Skip to main content

SSH Keys: Secure Passwordless Login to VPS

Security · 01.08.2025 · 5 min read
Illustration for “SSH Keys: Secure Passwordless Login to VPS”

SSH keys use public-key cryptography. You have two files: a private key (kept by you) and a public key (placed on the server). No password is ever sent over the network.

Generating keys (Linux / Mac)

# Modern Ed25519 algorithm (recommended)
ssh-keygen -t ed25519 -C "your@email.com"

# Or RSA-4096 for compatibility
ssh-keygen -t rsa -b 4096 -C "your@email.com"

# The keys are saved to ~/.ssh/
# ~/.ssh/id_ed25519      ← private (do NOT share with ANYONE)
# ~/.ssh/id_ed25519.pub  ← public (can be placed anywhere)

Adding the key to the server

# Automatically (the easiest way)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip

# Or manually:
cat ~/.ssh/id_ed25519.pub | ssh user@server-ip   "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Generating keys on Windows (PuTTYgen)

  1. Download PuTTYgen from the official PuTTY site
  2. Select EdDSA or RSA (4096 bits)
  3. Click Generate and move the mouse
  4. Save the private key (Save private key)
  5. Copy the public key from the text field at the top
  6. Add it to ~/.ssh/authorized_keys on the server

Disabling password login

⚠️ Only do this after confirming key-based login works! Otherwise you'll lose access to the server.
sudo nano /etc/ssh/sshd_config

# Change or add:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password

sudo systemctl restart sshd
✅ After setting up SSH keys, password brute-force attacks become pointless — the server simply won't accept a password.

Common SSH errors explained

Most key-related problems fall into five errors. The exact text tells you where to look.

  • Permission denied (publickey) — the server accepted the connection, but none of the offered keys matched. Causes: wrong key file, the key was never added to the right user's authorized_keys, or ssh-agent is offering the wrong key.
  • Too many authentication failures — the client tried more keys than the server's MaxAuthTries allows before it got to the right one. Point to the key explicitly: ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 user@server-ip.
  • WARNING: UNPROTECTED PRIVATE KEY FILE! — the private key file's permissions are wider than 600, so ssh refuses to read it. Fix with chmod 600 ~/.ssh/id_ed25519.
  • Agent admitted failure to sign using the key — the key is registered in ssh-agent, but the actual file on disk was deleted, renamed, or is no longer readable.
  • REMOTE HOST IDENTIFICATION HAS CHANGED — the server's fingerprint in ~/.ssh/known_hosts no longer matches the current one. If the server wasn't reinstalled and the IP wasn't reassigned to another host, stop and investigate instead of deleting the line right away.

Ed25519, RSA, and ECDSA: which algorithm to pick

The key type is set with the -t flag at generation time. The difference is more than a name.

AlgorithmKey lengthOperation speedCompatibility
Ed25519256 bits (fixed)HighOpenSSH 6.5+ (2014 and later)
RSA-40964096 bitsModerate when signingWorks everywhere, including old systems and panels
RSA-20482048 bitsHighMinimum acceptable length, use only under server constraints
ECDSA256-521 bitsHighWidely supported, but cryptographers recommend avoiding it due to the NIST curves used

For new servers and your own workstations, use Ed25519 — shorter, faster, and more resistant to weak randomness during generation. Keep RSA-4096 for legacy hardware that doesn't understand Ed25519.

When SSH keys are not the right fit

Keys are not a universal solution for every case.

  • A shared service account with no filesystem access to ~/.ssh, reachable only through a web panel — access there relies on a password or a panel token, not an SSH key.
  • One-off access for a contractor for 10-15 minutes — issuing a temporary password and rotating it right after is simpler than creating a key and then reliably wiping it from authorized_keys.
  • A device with no secure storage for the private key, such as a shared terminal in a coworking space — a key left there compromises every server it was added to.
  • A fleet of dozens of servers with no bastion host or centralized key management — when an employee leaves, someone has to manually clean authorized_keys on every machine, and one server will almost certainly be forgotten.

Verifying that password login is actually disabled

The sshd_config file may contain a directive overridden by another file pulled in via Include, so check what the daemon actually applied, not the text of the file.

# Shows the effective sshd configuration, not the file contents
sudo sshd -T | grep -i passwordauthentication

# Explicitly request password authentication — the server must refuse
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password user@server-ip

# Confirm the last login actually used a key
sudo grep "Accepted" /var/log/auth.log | tail -5

If the first command prints passwordauthentication no, the second command fails with an access error, and the log shows an Accepted publickey line — password login is disabled for real, not just in the configuration file.

Was this article helpful?
← Back to Knowledge Base Ask Support