Technology Encyclopedia Home >How to Set Up Two-Factor Authentication for SSH — TOTP-Based 2FA on Ubuntu

How to Set Up Two-Factor Authentication for SSH — TOTP-Based 2FA on Ubuntu

SSH key authentication is genuinely strong security — cryptographic keys are much harder to compromise than passwords. But I work across multiple machines and occasionally worry about what happens if a private key is ever compromised.

Adding TOTP-based 2FA means an attacker needs both the key file and the current 6-digit code from my authenticator app. The two-factor part isn't about doubting SSH keys — it's about defense in depth.

Important warning before you start: Test 2FA in a second SSH session while keeping your existing session open. If you misconfigure this and get locked out, you'll need console access to fix it. I'll make this explicit in the guide.

I set this up on Tencent Cloud Lighthouse for servers that contain sensitive data. It takes about 10 minutes and works with any TOTP authenticator app. One important practical note specific to Lighthouse: if you configure 2FA incorrectly and lock yourself out of SSH, OrcaTerm (the browser-based terminal in the Lighthouse console) gives you direct server access without SSH authentication. This means you can fix a misconfiguration without needing a rescue boot or support ticket — which makes testing 2FA setups much less risky.


Table of Contents

  1. When 2FA for SSH Makes Sense
  2. Prerequisites
  3. Part 1 — Install Google Authenticator PAM Module
  4. Part 2 — Configure 2FA for Your User
  5. Part 3 — Configure SSH to Require 2FA
  6. Part 4 — Test the Configuration
  7. Part 5 — Require 2FA Only for Password Auth (Key Auth Exempt)
  8. Part 6 — Backup Your 2FA Codes
  9. The Gotcha: Test Before Closing Your Current Session
  10. Recovery: Locked Out Without Your TOTP Device

  • Key Takeaways
  • Use the appropriate Lighthouse application image to skip manual installation steps where available
  • Lighthouse snapshots provide one-click full-server backup before major changes
  • OrcaTerm browser terminal lets you manage the server from any device
  • CBS cloud disk expansion handles growing storage needs without server migration
  • Console-level firewall + UFW = two independent protection layers

When 2FA for SSH Makes Sense {#when}

Scenario 2FA value
SSH key + 2FA Very high security — attacker needs key AND phone
Password auth + 2FA High security — better than password alone
Key auth only Good security — appropriate for most setups
Root login allowed Always add 2FA if you keep this enabled

For most personal servers using SSH keys, 2FA is optional but adds meaningful protection. For servers with sensitive data or that you share access to, 2FA is strongly recommended.


Prerequisites {#prerequisites}

Requirement Notes
Cloud server Tencent Cloud Lighthouse Ubuntu 22.04
A TOTP authenticator app Google Authenticator, Authy, 1Password, Bitwarden, etc.
An active SSH session open Keep it open during configuration (don't close it)

Part 1 — Install Google Authenticator PAM Module {#part-1}

ssh ubuntu@YOUR_SERVER_IP
sudo apt update
sudo apt install -y libpam-google-authenticator

Part 2 — Configure 2FA for Your User {#part-2}

Run the configuration as the user who will use 2FA:

google-authenticator

Answer the questions:

Do you want authentication tokens to be time-based (y/n): y

A QR code and secret key appear. Scan the QR code with your authenticator app now.

Continue with the prompts:

Do you want me to update your "~/.google_authenticator" file? y

Do you want to disallow multiple uses of the same authentication token? y
# Prevents replay attacks

Do you want to increase the time skew window? n
# Unless your server clock is consistently off

Do you want to enable rate-limiting? y
# Limits to 3 login attempts per 30 seconds

The setup generates emergency scratch codes — save these somewhere safe. They let you log in if you lose your phone.


Part 3 — Configure SSH to Require 2FA {#part-3}

Step 1: Configure PAM

sudo nano /etc/pam.d/sshd

Add this line at the top (before other auth lines):

auth required pam_google_authenticator.so

Or to make 2FA optional (only required if configured for a user):

auth required pam_google_authenticator.so nullok

nullok means users without 2FA configured can still log in. Remove nullok to enforce 2FA for all users.

Step 2: Configure SSH daemon

sudo nano /etc/ssh/sshd_config

Update these settings:

# Enable PAM
UsePAM yes

# Enable challenge-response (required for TOTP prompts)
ChallengeResponseAuthentication yes
# Or for newer OpenSSH:
KbdInteractiveAuthentication yes

# Require both public key AND 2FA
AuthenticationMethods publickey,keyboard-interactive
# Or for password + 2FA only:
# AuthenticationMethods password keyboard-interactive
sudo systemctl restart sshd

Part 4 — Test the Configuration {#part-4}

Keep your current SSH session open. Open a new terminal and test:

# In a NEW terminal window
ssh ubuntu@YOUR_SERVER_IP

You should now see two prompts:

  1. Your SSH key passphrase (if your key has one) — or automatic key auth
  2. Verification code: — enter the 6-digit code from your authenticator app

If the login succeeds — 2FA is working.

If it fails, your original session is still open to fix the configuration.


Part 5 — Require 2FA Only for Password Auth (Key Auth Exempt) {#part-5}

Many people prefer: SSH key auth works without 2FA, but if you use password auth, 2FA is required. This is convenient for trusted devices with keys, while still protecting password-based logins.

sudo nano /etc/ssh/sshd_config
# Public key auth: key only (no 2FA)
# Password auth: password + TOTP
AuthenticationMethods publickey keyboard-interactive:pam
sudo nano /etc/pam.d/sshd

Comment out @include common-auth (to prevent double password prompt):

# @include common-auth    ← comment this out
auth required pam_google_authenticator.so
sudo systemctl restart sshd

With this setup:

  • Users with SSH keys connect without a TOTP prompt
  • Users without SSH keys (password auth) must provide password + TOTP

Part 6 — Backup Your 2FA Codes {#part-6}

Your 2FA secret is stored in ~/.google_authenticator. Back it up:

cat ~/.google_authenticator

This file contains:

  • The TOTP secret key
  • Emergency scratch codes
  • Configuration options

Store this file (or just the secret key) in a password manager or secure offline location. If you lose your phone, you can regenerate TOTP codes from the secret key in any TOTP app.


The Gotcha: Test Before Closing Your Current Session {#gotcha}

The most dangerous mistake in 2FA setup: making SSH changes and then closing your terminal before testing. If the configuration is wrong, you lock yourself out.

The rule: always test in a separate terminal window while keeping the original session open.

If you accidentally lock yourself out:

  1. Use Lighthouse OrcaTerm — the console terminal works regardless of SSH configuration
  2. From OrcaTerm, fix the sshd config or PAM config:
    # Revert to no 2FA
    sudo nano /etc/pam.d/sshd
    # Comment out: auth required pam_google_authenticator.so
    sudo systemctl restart sshd
    

Recovery: Locked Out Without Your TOTP Device {#recovery}

If you've lost your phone and need to access the server:

Option 1: Use emergency scratch codes

When you ran google-authenticator, it generated 5 emergency scratch codes. Each works once. If you saved them, use one now.

Option 2: Use Lighthouse OrcaTerm

Access the server directly via the Lighthouse console browser terminal — bypasses SSH entirely.

Once in:

# Temporarily disable 2FA
sudo nano /etc/pam.d/sshd
# Comment out the google-authenticator line

sudo systemctl restart sshd

Reconfigure 2FA with your new phone:

# Re-run setup as your user
google-authenticator
# New QR code will appear

Re-enable 2FA in PAM config.

Option 3: Regenerate from backup secret key

If you backed up the secret key from ~/.google_authenticator, enter it manually into any TOTP app to regenerate codes.

Troubleshooting {#troubleshooting}

Issue Likely Cause Fix
Connection refused Service not running or wrong port Check systemctl status SERVICE and verify firewall rules
Permission denied Wrong file ownership or permissions Check file ownership with ls -la and use chown/chmod to fix
502 Bad Gateway Backend service not running Restart the backend service; check logs with journalctl -u SERVICE
SSL certificate error Certificate expired or domain mismatch Run sudo certbot renew and verify domain DNS points to server IP
Service not starting Config error or missing dependency Check logs with journalctl -u SERVICE -n 50 for specific error
Out of disk space Logs or data accumulation Run df -h to identify usage; clean logs or attach CBS storage
High memory usage Too many processes or memory leak Check with htop; consider upgrading instance plan if consistently high
Firewall blocking traffic Port not open in UFW or Lighthouse console Open port in Lighthouse console firewall AND sudo ufw allow PORT

Frequently Asked Questions {#faq}

Does SSH 2FA conflict with Lighthouse's console-level firewall?
No — they operate at different layers. Lighthouse's console firewall blocks at the network infrastructure level. SSH 2FA operates at the OS level. Both provide independent protection layers.

How do I check if SSH 2FA is working correctly?
Check the service status with sudo systemctl status ssh. Review logs for recent activity. Most security tools have a test or dry-run mode to verify configuration.

What should I do if SSH 2FA blocks a legitimate user or IP?
Most security tools have a whitelist mechanism. Add trusted IPs to the whitelist/ignore list. For Fail2ban, use fail2ban-client set JAIL unbanip IP_ADDRESS.

How often should I review security logs?
For personal servers, a weekly review of auth logs and firewall logs is reasonable. For production or sensitive servers, set up log monitoring with alerts for suspicious patterns (unusually high fail rates, unusual hours).

Should I use all available security measures or just some?
Apply defense in depth: multiple independent layers. SSH key auth + Fail2ban + UFW + Lighthouse firewall + regular updates covers the most common attack vectors without significant complexity.

Secure your server with 2FA:
👉 Tencent Cloud Lighthouse — Console terminal access as a safety net
👉 View current pricing and promotions
👉 Explore all active deals and offers