21+ years in hosting · Jaipur, India · INR billing with 18% GST · 24/7 email support
Blog · WebJi® India

SSH Two-Factor Authentication

Quick answer

SSH two-factor authentication adds a one-time code to key-based login. Install libpam-google-authenticator, enrol each user with google-authenticator, add the PAM module to /etc/pam.d/sshd, set KbdInteractiveAuthentication yes and AuthenticationMethods publickey,keyboard-interactive, then test from a second session before closing the first.

For Linux VPS and server admins adding a second factor to SSH without risking a lockout.

✓ In business since 2005
✓ INR + GST billing
✓ 24/7 Email Support — avg reply < 60 min
GuideWebJi®
knowledge
Read time
4 min
Sections
7
Updated
14 Nov 2026
Written by
WebJi® team

What does SSH two-factor authentication add?

SSH two-factor authentication requires a time-based one-time code (TOTP) from an authenticator app in addition to your SSH key, so a stolen laptop or copied private key is no longer enough to log in. The key proves the device; the code proves the person holding the phone.

  • Stops: leaked or copied keys, reused passwords, credential stuffing.
  • Does not stop: a phishing proxy that relays your code in real time — FIDO2 hardware keys do.
  • Works with: Google Authenticator, Aegis, Microsoft Authenticator, 1Password or any TOTP app; the server never contacts Google.

How do you avoid locking yourself out?

Keep your current SSH session open throughout, confirm the provider's web console works, and test every change from a second terminal before closing the first. An existing session survives an sshd restart and can undo a bad edit.

  1. Open the VPS provider's console once to confirm you can log in there.
  2. Make sure a second sudo user exists; see add a sudo user on Ubuntu.
  3. Take a snapshot if your plan offers one.
  4. Have somewhere offline ready to store scratch codes; they are shown only once.

How do you install and enrol Google Authenticator for SSH?

Install the PAM module from your distribution, then run google-authenticator as the user who will log in — not as root — and scan the QR code. The secret is stored in that user's home directory.

# Ubuntu / Debian
sudo apt update
sudo apt install libpam-google-authenticator
# AlmaLinux / Rocky (EPEL)
sudo dnf install epel-release && sudo dnf install google-authenticator qrencode

# Run as the login user
google-authenticator
chmod 600 ~/.google_authenticator

Answer: time-based tokens yes, update the file yes, disallow reuse yes, widen the time window no, rate-limit yes. Save the printed emergency scratch codes offline; each works once.

How do you configure PAM and sshd to require key plus code?

Add the Google Authenticator module to /etc/pam.d/sshd, enable keyboard-interactive authentication in sshd, and set AuthenticationMethods publickey,keyboard-interactive. On Ubuntu and Debian, also comment out the password include, or users are asked for a password after the key.

# /etc/pam.d/sshd
# @include common-auth            <- comment out on Ubuntu/Debian for key + code only
auth required pam_google_authenticator.so

# /etc/ssh/sshd_config (or a file in /etc/ssh/sshd_config.d/)
UsePAM yes
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
PasswordAuthentication no
  1. Enrol every account that logs in by SSH before restarting sshd; users without a secret file will be refused.
  2. Check files in /etc/ssh/sshd_config.d/; a cloud-init file there can override your settings.
  3. Older guides use ChallengeResponseAuthentication, the deprecated name for KbdInteractiveAuthentication.
  4. Validate and restart: sudo sshd -t && sudo systemctl restart ssh (the unit is sshd on RHEL-family systems).
  5. Open a second terminal and log in; you should be asked for a verification code after the key.

How do you confirm two-factor login is enforced?

A successful login should prompt for a code after the key, reject a wrong code, and log both methods. Check the authentication log right after testing.

sudo journalctl -u ssh -n 30 --no-pager      # Ubuntu/Debian (use -u sshd on RHEL)
sudo tail -n 30 /var/log/auth.log            # Ubuntu/Debian
sudo tail -n 30 /var/log/secure              # AlmaLinux/Rocky

Look for Partial publickey followed by Accepted keyboard-interactive/pam. A plain Accepted publickey means the code was not required — usually a missing or misspelled AuthenticationMethods line, or an override in sshd_config.d.

Automated accounts that cannot type a code, such as a backup user, need a scoped exception rather than a weaker global rule:

Match User backup
    AuthenticationMethods publickey

What if you lose the phone with your authenticator app?

Use an emergency scratch code at the verification prompt; if those are gone, log in through the provider's console, move the secret file aside and enrol a new phone. Work from least to most invasive.

  1. Enter one scratch code at the "Verification code" prompt.
  2. Without codes, log in via the provider console or rescue mode.
  3. In the console, set AuthenticationMethods publickey in sshd_config, run sudo sshd -t and restart ssh, so the key alone works again.
  4. Log in over SSH, run google-authenticator to enrol the new phone, and store the new scratch codes.
  5. Restore AuthenticationMethods publickey,keyboard-interactive, validate with sshd -t, restart and test from a second session.

If SSH does not answer at all, follow SSH connection refused on a VPS.

Should you use TOTP codes or a hardware security key?

TOTP is the practical default for most teams; FIDO2 hardware keys are stronger because they resist real-time phishing, and OpenSSH supports them natively with ed25519-sk keys. Many teams give administrators hardware keys and use TOTP for everyone else.

SSH login methods compared
MethodUser needsPhishing resistanceFits
Password onlyNothing extraNoneNot suitable for public servers
Key onlyKey fileGood unless the key is copiedAutomation, most admins
Key plus TOTPKey and phone appStrong against stolen keysProduction VPS, small teams
FIDO2 key (-sk)Hardware key with touchStrongestCritical systems
# Create a hardware-backed SSH key (OpenSSH 8.2+), then add the .pub file to authorized_keys
ssh-keygen -t ed25519-sk -C "admin@example.in"

WebJi® VPS hosting starts at ₹499 a month before 18% GST and includes console access for changes like this; support@webji.services answers 24/7 in Hindi and English, average first reply under 60 minutes.

FAQ

Frequently asked questions

Does SSH 2FA break SFTP or scp?

Interactive clients such as FileZilla and WinSCP prompt for the code and work normally. Scripts and CI jobs cannot type a code, so give them a separate user with a Match User exception that allows key-only login.

Why does it ask for my password and then the code?

On Ubuntu and Debian, @include common-auth in /etc/pam.d/sshd still runs the password step. Comment that line out and keep AuthenticationMethods publickey,keyboard-interactive so the flow becomes key, then code.

Do codes fail if the server clock is wrong?

Yes. TOTP depends on accurate time. Make sure time sync is on with timedatectl, which should show "System clock synchronized: yes". A drift of more than about 30 seconds causes rejected codes.

Does fail2ban still help with 2FA enabled?

Yes. fail2ban blocks IPs after repeated failures, cutting noise and brute-force attempts; 2FA stops a valid key alone from completing a login. Allow-list your office IP in fail2ban before testing.

Last editorial update: 15 November 2026. Prices follow the dated sources on this page; checkout confirms current charges.

WebJi® since 2005

Ready to get started with WebJi®?

Join 12,000+ businesses across India and overseas. INR pricing, 18% GST shown before payment and 24/7 email support in Hindi and English — average first reply under 60 minutes.