Every second, thousands of automated bots scan the internet for SSH servers and attempt to log in using common username and password combinations. If your server relies on password authentication, it is only a matter of time before an attacker gets in — or at the very least, fills your logs with thousands of failed attempts and consumes resources.
SSH key authentication eliminates this threat entirely. Instead of a password that can be guessed, SSH keys use public-key cryptography that is mathematically unfeasible to brute-force. This guide walks you through generating keys, deploying them, disabling password authentication, and hardening your SSH configuration for production.
How SSH Key Authentication Works
SSH key authentication uses asymmetric cryptography — a matched pair of keys where one encrypts and only the other can decrypt:
a key pair
goes to server
stays on your machine
a challenge
the challenge
signature = access
The private key never leaves your local machine. The server only needs the public key. Even if someone compromises the server and gets your public key, they cannot use it to authenticate — the private key is required to prove identity.
Think of it like a padlock and a key. You send an open padlock (public key) to the server. The server uses the padlock to lock a box (challenge). Only your unique key (private key) can open it. Anyone can see the padlock, but that does not help them open the box.
Choosing the Right Key Type
SSH supports several key algorithms. Here is a comparison of the most common ones:
| Algorithm | Key Size | Security Level | Speed | Recommendation |
|---|---|---|---|---|
| Ed25519 | 256 bits | Excellent | Fastest | Best choice in 2026 |
| RSA | 3072-4096 bits | Excellent | Slower | Use 4096-bit for legacy compatibility |
| ECDSA | 256-521 bits | Good | Fast | OK, but Ed25519 is better |
| DSA | 1024 bits | Weak | Moderate | Deprecated, do not use |
Ed25519 is the recommended algorithm for all new SSH keys. It offers the best security-to-performance ratio, produces small keys (68 characters for the public key), and is immune to several side-channel attacks that affect other algorithms. The only reason to use RSA is if you need to connect to a very old server (OpenSSH < 6.5, pre-2014) that does not support Ed25519.
Step 1: Generate Your SSH Key Pair
Run this command on your local machine (your laptop or desktop — not the server):
Ed25519 (Recommended)
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/you/.ssh/id_ed25519): [Press Enter for default]
Enter passphrase (empty for no passphrase): [type a strong passphrase]
Enter same passphrase again: [confirm passphrase]
Your identification has been saved in /home/you/.ssh/id_ed25519
Your public key has been saved in /home/you/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:xR4jK9mN2pL5qR8tV1wY4zA6cE0fH3jK7nQ9sU2b yourname@yourlaptop
The key's randomart image is:
+--[ED25519 256]--+
| .o+. |
| .o=o+ |
| . =+B. |
| o.B+o |
| . S+=.+ |
| . o.=.= . |
| +.+.o . |
| ..+.o . |
| E+o. |
+----[SHA256]-----+
RSA 4096-bit (For Legacy Compatibility)
Generating public/private rsa key pair.
Enter file in which to save the key (/home/you/.ssh/id_rsa): [Press Enter]
Enter passphrase: [type passphrase]
A passphrase encrypts your private key on disk. Without it, anyone who gains access to your laptop can use your key to log into all your servers. With a passphrase, the key file is useless without the passphrase. Use SSH agent to avoid typing it repeatedly.
Step 2: View Your Keys
After generation, you will have two files:
-rw------- 1 you you 464 Mar 17 10:30 /home/you/.ssh/id_ed25519
-rw-r--r-- 1 you you 104 Mar 17 10:30 /home/you/.ssh/id_ed25519.pub
# View your public key (this is what goes on the server)
local$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt8J3kX... yourname@yourlaptop
| File | Permissions | Purpose | Share? |
|---|---|---|---|
id_ed25519 | 600 (owner read/write only) | Private key | NEVER share |
id_ed25519.pub | 644 (world readable) | Public key | Safe to share |
Step 3: Deploy the Public Key to Your Server
The easiest way to copy your public key to the server is with ssh-copy-id:
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/you/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s)
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed
[email protected]'s password: ********
Number of key(s) added: 1
Now try logging in: "ssh [email protected]"
Manual Method (if ssh-copy-id is unavailable)
On Windows or systems without ssh-copy-id, you can copy the key manually:
local$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBt8J3kX... yourname@yourlaptop
# SSH into the server and add the key
server$ mkdir -p ~/.ssh && chmod 700 ~/.ssh
server$ nano ~/.ssh/authorized_keys
# Paste the public key on a new line
server$ chmod 600 ~/.ssh/authorized_keys
Step 4: Test Key-Based Login
Before disabling password authentication, verify that your key works:
Enter passphrase for key '/home/you/.ssh/id_ed25519': [your passphrase]
deploy@vps:~$
# If you see a password prompt instead of a passphrase prompt,
# the key is not being used. Check permissions:
deploy@vps:~$ ls -la ~/.ssh/
drwx------ 2 deploy deploy 4096 Mar 17 10:35 .
-rw------- 1 deploy deploy 104 Mar 17 10:35 authorized_keys
Always keep your existing SSH session open when changing SSH settings. Open a new terminal window to test. If key authentication fails and you have already disabled passwords, you will be locked out of your server.
Step 5: Disable Password Authentication
Once you have confirmed key-based login works, disable password authentication on the server:
# Find and change/add these lines:
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
PubkeyAuthentication yes
# Validate config before restarting
deploy@vps:~$ sudo sshd -t
# No output means config is valid
deploy@vps:~$ sudo service sshd restart
Verify the change took effect:
local$ ssh -o PubkeyAuthentication=no [email protected]
[email protected]: Permission denied (publickey).
# Password auth is disabled. Key auth still works:
local$ ssh [email protected]
Enter passphrase for key '/home/you/.ssh/id_ed25519':
deploy@vps:~$ # Connected with key!
Step 6: Full SSH Hardening Configuration
Beyond disabling passwords, there are several additional sshd_config settings that significantly improve security:
# Authentication
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
MaxAuthTries 3
AuthenticationMethods publickey
# Session management
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 30
MaxSessions 5
MaxStartups 10:30:60
# Security restrictions
X11Forwarding no
AllowAgentForwarding no
PermitEmptyPasswords no
PermitUserEnvironment no
# Logging
LogLevel VERBOSE
# Only allow specific users (optional)
AllowUsers deploy admin
Here is what each setting does:
| Setting | Value | Purpose |
|---|---|---|
PermitRootLogin | prohibit-password | Root can login only with keys, never password |
MaxAuthTries | 3 | Disconnect after 3 failed attempts |
ClientAliveInterval | 300 | Send keepalive every 5 minutes |
ClientAliveCountMax | 2 | Disconnect after 2 missed keepalives (10 min idle) |
LoginGraceTime | 30 | 30 seconds to authenticate or disconnect |
MaxStartups | 10:30:60 | Rate limit new connections (starts dropping at 10) |
AllowUsers | deploy admin | Only these users can SSH in |
LogLevel | VERBOSE | Detailed logging for security auditing |
SSH Config File: Managing Multiple Servers
If you manage multiple servers, typing full SSH commands gets tedious. The SSH client config file lets you create shortcuts:
Host web
HostName 203.0.113.50
User deploy
Port 22
IdentityFile ~/.ssh/id_ed25519
Host staging
HostName 198.51.100.10
User ubuntu
Port 2222
IdentityFile ~/.ssh/staging_key
Host db
HostName 10.0.1.50
User admin
ProxyJump web # Jump through web server to reach internal network
# Now you can simply type:
local$ ssh web # Instead of full command with -i flag
local$ ssh staging # Automatically uses port 2222 and staging key
local$ ssh db # Automatically jumps through web server
SSH Agent: Avoid Typing Your Passphrase Repeatedly
If your key has a passphrase (and it should), SSH agent caches the decrypted key in memory so you only type the passphrase once per session:
local$ eval "$(ssh-agent -s)"
Agent pid 12345
# Add your key (type passphrase once)
local$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/you/.ssh/id_ed25519: ********
Identity added: /home/you/.ssh/id_ed25519 (yourname@yourlaptop)
# List loaded keys
local$ ssh-add -l
256 SHA256:xR4jK... yourname@yourlaptop (ED25519)
# Now SSH connections use the cached key - no passphrase prompt!
local$ ssh [email protected]
deploy@vps:~$ # Connected instantly!
On macOS, add
UseKeychain yes and AddKeysToAgent yes to your ~/.ssh/config to automatically store the passphrase in your macOS Keychain. You will only need to type it once — ever.
Adding Two-Factor Authentication (2FA)
For maximum security, you can combine SSH keys with TOTP (Time-based One-Time Password) using Google Authenticator. This means an attacker would need both your private key AND your phone to log in:
server$ sudo apt install -y libpam-google-authenticator
# Run setup for your user
server$ google-authenticator
Do you want authentication tokens to be time-based (y/n)? y
[QR CODE APPEARS - scan with your authenticator app]
Your emergency scratch codes are:
12345678
87654321
...
# Configure PAM
server$ sudo nano /etc/pam.d/sshd
# Add at the top:
auth required pam_google_authenticator.so
# Configure SSH to use both key and TOTP
server$ sudo nano /etc/ssh/sshd_config
AuthenticationMethods publickey,keyboard-interactive
ChallengeResponseAuthentication yes
server$ sudo service sshd restart
Verified
Prompted
Against Phone App
Granted
Security Checklist
Here is the complete SSH security hardening checklist:
Essential (Do These)
- Use Ed25519 keys (not RSA/DSA)
- Add a passphrase to your private key
- Disable password authentication
- Set PermitRootLogin to prohibit-password
- Limit MaxAuthTries to 3
- Install and configure Fail2Ban
Advanced (Highly Recommended)
- Use AllowUsers to restrict SSH users
- Change default SSH port
- Enable 2FA with Google Authenticator
- Use SSH agent forwarding carefully
- Set up SSH config for multiple servers
- Audit authorized_keys files regularly
Panelica SSH Management
Panelica provides comprehensive SSH access control through its web interface, eliminating the need for manual sshd_config editing:
- Per-user SSH access control — enable or disable SSH access for each user independently
- Chroot jails — restrict users to their home directories so they cannot see or access other users' files
- SFTP-only mode — grant file transfer access without shell access for users who only need to upload files
- Configurable shell access — choose between full bash access (chrooted) and restricted SFTP-only mode per user
- Fail2Ban integration — automatic IP banning after failed SSH attempts, manageable through the panel
- 5-layer isolation — SSH access is just one layer; users are also isolated by cgroups, namespaces, PHP-FPM pools, and Unix permissions
Instead of manually editing sshd_config, managing authorized_keys files, and configuring chroot jails, Panelica handles SSH access control through a clean web interface. Each user's SSH access, shell type, and resource limits are configured in a few clicks.