Multi-Factor Authentication on Ubuntu

Multi-factor authentication (MFA) requires a second form of verification beyond a password. For Ubuntu SSH access, the most practical MFA method is TOTP (Time-based One-Time Password) using Google Authenticator or any compatible app (Authy, FreeOTP, Bitwarden). After setup, SSH logins require both your SSH key (or password) plus a 6-digit rotating code from your phone.

Why MFA matters for SSH

A compromised SSH private key or password alone is enough to gain access without MFA. With MFA, an attacker also needs physical access to your phone. This is particularly important for servers accessible from the internet, shared jump hosts, and any server with production data.

Installing Google Authenticator

# Install the PAM module
sudo apt update
sudo apt install -y libpam-google-authenticator

# Run setup AS THE USER who will use MFA (not as root)
# This creates ~/.google_authenticator
google-authenticator

google-authenticator prompts

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

[QR code appears here — scan with Google Authenticator app]

Your new secret key is: JBSWY3DPEHPK3PXP
Your verification code is 123456
Your emergency scratch codes are:
  12345678
  87654321
  11111111
  22222222
  33333333

Do you want me to update your "/home/irfan/.google_authenticator" file? (y/n) y
Do you want to disallow multiple uses of the same authentication token? (y/n) y
Do you want to increase the time skew window? (y/n) n
Do you want to enable rate-limiting? (y/n) y

⚠️ WARNING: Save the emergency scratch codes immediately when they appear during setup. These one-time codes are the ONLY way to log in if you lose your phone. Store them in a password manager or a secure offline location. Each code can only be used once. If you lose both your phone and the scratch codes, you need console access to remove ~/.google_authenticator.

Configuring PAM for MFA

# Edit the SSH PAM configuration
sudo nano /etc/pam.d/sshd

Add at the TOP of /etc/pam.d/sshd

# MFA: require Google Authenticator TOTP
auth required pam_google_authenticator.so nullok

# nullok = users without ~/.google_authenticator skip MFA
# Remove nullok once all users have set up MFA

Configuring sshd for MFA

# Edit SSH daemon configuration
sudo nano /etc/ssh/sshd_config

Required sshd_config changes for MFA with password

# Enable challenge-response authentication (required for TOTP)
ChallengeResponseAuthentication yes
# or on Ubuntu 22.04+:
KbdInteractiveAuthentication yes

# Keep this enabled
UsePAM yes
# Reload SSH (test in a second terminal first!)
sudo systemctl reload sshd

# Test login in a NEW terminal
ssh irfan@server
# Verification code: [enter TOTP from app]
# Password: [enter password if using password auth]

MFA with SSH keys (best practice)

The most secure configuration requires BOTH an SSH key AND a TOTP code. Password authentication is disabled entirely. This gives you something you have (SSH key) + something you have (phone).

# sshd_config for SSH key + TOTP (most secure)
sudo nano /etc/ssh/sshd_config

sshd_config for key + TOTP authentication

PubkeyAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive
ChallengeResponseAuthentication yes
UsePAM yes
# In /etc/pam.d/sshd, comment out @include common-auth
# and add only the google-authenticator line:
sudo nano /etc/pam.d/sshd

/etc/pam.d/sshd for key + TOTP

# Comment this out (prevents password prompt after key auth):
# @include common-auth

# Only require TOTP
auth required pam_google_authenticator.so

Troubleshooting MFA

# MFA not prompting at all?
# Check that ChallengeResponseAuthentication yes is set in sshd_config
grep -i "ChallengeResponse\|KbdInteractive" /etc/ssh/sshd_config

# "Permission denied" without being asked for verification code?
# Check /etc/pam.d/sshd has the google-authenticator line
grep google-authenticator /etc/pam.d/sshd

# Code rejected even when correct?
# Time sync issue — check server time
timedatectl
# Sync NTP
sudo systemctl restart systemd-timesyncd

# Check for errors in auth.log
sudo grep "google_authenticator" /var/log/auth.log | tail -10

Conclusion

Google Authenticator TOTP MFA adds a critical second factor to SSH authentication. The best practice configuration uses SSH key + TOTP (not password + TOTP). Save emergency scratch codes before finishing setup or you risk locking yourself out. Use nullok in the PAM config during rollout so users without ~/.google_authenticator are not immediately blocked, then remove nullok once all users complete enrollment. Always keep a console access method available when configuring MFA.

FAQ

Is Multi-Factor Authentication on Ubuntu important for Ubuntu administrators?+

Yes. It supports practical Ubuntu administration because it connects directly to server reliability, security, troubleshooting, or daily operations.

Should I practice this on a live server?+

Use a lab VM first. After you understand the command output and rollback path, apply the workflow carefully on real systems.

What should I do after reading this article?+

Run the practice commands, write down what each one shows, and continue to the next article in the Ubuntu roadmap.

Need help with Ubuntu administration?

Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.

Hire Me for Support