Set Up Two-Factor Authentication (2FA) for SSH
Password alone is not sufficient to protect your SSH connection. If your password is leaked or compromised through a brute force attack, attackers can gain immediate access to your VPS. Adding 2FA (Two-Factor Authentication) with TOTP (Time-based One-Time Password) ensures that even if a password is compromised, access is impossible without a second authentication device.
Install Google Authenticator PAM
sudo apt update
sudo apt install libpam-google-authenticator -y
# Set up TOTP for the current user
google-authenticator
Answer the prompts as follows:
- Time-based tokens → y
- Update .google_authenticator → y
- Disallow reuse → y
- Permit 30-second clock skew → y
- Rate limiting → y
Save the QR code (scan it with the Google Authenticator app) and all 5 backup codes in a secure location.
Configure PAM for SSH
sudo nano /etc/pam.d/sshd
# Add this line after @include common-auth
auth required pam_google_authenticator.so
sudo nano /etc/ssh/sshd_config
# Edit or add these lines
ChallengeResponseAuthentication yes
# Or in newer SSH versions:
KbdInteractiveAuthentication yes
UsePAM yes
# If you want both SSH key and 2FA:
AuthenticationMethods publickey,keyboard-interactive
# Restart SSH daemon
sudo systemctl restart ssh
# Test in a new terminal (keep the old session open)
ssh user@YOUR_VPS_IP
Allow SSH Key to Bypass 2FA (Optional)
If you want SSH key authentication to skip the 2FA step (more convenient, but less secure):
sudo nano /etc/pam.d/sshd
# Change the line you added to:
auth required pam_google_authenticator.so nullok
sudo nano /etc/ssh/sshd_config
# Set AuthenticationMethods to support both modes
AuthenticationMethods publickey publickey,keyboard-interactive
Match User deploybot block in sshd_config to skip 2FA only for that user.
Verify 2FA is Working Correctly
# Check sshd config syntax
sudo sshd -t
# Check SSH service status
systemctl status ssh
# Test login (should prompt for both password and OTP code)
ssh -v user@YOUR_VPS_IP
# Verify PAM module is loaded
grep google-authenticator /var/log/auth.log | tail -10
/etc/pam.d/sshd and /etc/ssh/sshd_config.
Common Issues & Troubleshooting
SSH Does Not Prompt for Verification Code
ChallengeResponseAuthentication is still set to no, or PAM is not loading the google-authenticator module:
# Check sshd_config
grep -i "ChallengeResponse\|KbdInteractive\|UsePAM" /etc/ssh/sshd_config
# Check PAM
grep -n "google-authenticator" /etc/pam.d/sshd
# Read SSH logs after login attempt
sudo journalctl -u ssh -n 30
Locked Out Despite Entering Correct Code
The VPS time differs from your phone's time by more than 30 seconds. Synchronize NTP first:
# Check server time
date
timedatectl
# Sync NTP
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd
google-authenticator File Missing or Phone Reinstalled
The ~/.google_authenticator file stores the secret key. If it's lost, you must regenerate it:
# Regenerate (scan QR code in the app again)
google-authenticator
# If completely locked out, access via VPS console (KVM)
# Then temporarily disable 2FA for recovery
All Backup Codes Used Up
Generate new backup codes by regenerating google-authenticator, but you must scan the QR code in the app again:
# Edit the file directly to add backup codes (lines starting with 8 digits)
nano ~/.google_authenticator
# Or regenerate everything
google-authenticator -f -t -d -r 3 -R 30 -w 3
Frequently Asked Questions
What's the difference between 2FA and SSH key? Which should I use?
SSH keys protect against brute force very well because they are extremely long, but if your private key is compromised, an attacker gains instant access. 2FA adds another layer of protection that requires a physical device. Ideally, use both together: SSH key + 2FA.
What's the difference between TOTP and HOTP?
TOTP (Time-based OTP) generates a new code every 30 seconds using time as input. HOTP (HMAC-based OTP) uses a counter that increments by 1 with each use. TOTP is more popular because codes expire automatically.
Will I be locked out if my phone is lost?
Yes — if you don't have backup codes, losing your phone means lockout. Solutions: 1) Store backup codes outside your device, 2) Set up 2FA on two devices, 3) Save your secret key (.google_authenticator) in a password manager.