How to Setup Two-Factor Authentication For SSH In Linux
Password-only SSH authentication is one of the most common — and most dangerous — security gaps in Linux server management. Attackers armed with credential lists and automated scripts can hammer your SSH port indefinitely. If your password is the only thing standing between them and root access, your environment is one breach away from a serious incident.
Two-factor authentication (2FA) via Google Authenticator eliminates that single point of failure. Even if an attacker gets your password, they still need the time-based one-time code from your phone — a six-digit number that expires every 30 seconds. No code, no access.
In this guide, we walk through every step needed to configure SSH 2FA on both Debian-based systems (Ubuntu, Linux Mint) and RHEL-based systems (Rocky Linux, AlmaLinux, Fedora, CentOS Stream) — no third-party services, no subscriptions, no reboots required.
Quick Win: This is one of the most impactful SSH hardening steps you can implement — typically under 15 minutes from start to finish.
Why Restricting SSH to Password-Only Login Is a Risk
Before jumping into the configuration, it is worth understanding what is actually at stake when SSH runs without 2FA enabled:
- Brute-Force Exposure — Any internet-facing SSH port is constantly targeted by automated credential-stuffing tools that run 24/7.
- Credential Leak Risk — Passwords get reused, phished, or exposed in data breaches. One leaked credential can compromise your entire server.
- Lateral Movement — Once an attacker gains SSH access, they have a foothold for privilege escalation and moving deeper into your network.
- Compliance Gaps — Many frameworks (HIPAA, PCI-DSS, ISO 27001) explicitly require multi-factor authentication for remote access to sensitive systems.
- Insider Threat Reduction — 2FA limits the blast radius if an employee account is compromised or misused, since physical device access is also required.
- Audit Trail Improvement — Enforcing 2FA strengthens access controls and supports the principle of least-privilege access logging.
Security Note: In regulated environments (HIPAA, PCI-DSS, ISO 27001), multi-factor authentication for remote access is often a hard compliance requirement, not an optional improvement.
Key Highlights
What This Setup Does
- Adds a time-based one-time password (TOTP) layer on top of your SSH password login
- Works on all major Linux distributions — both Debian-based and RHEL-based systems
- Tokens refresh every 30 seconds, rendering intercepted codes useless almost instantly
- Applies per-user — you can roll this out selectively without affecting all accounts at once
- Compatible with Android, iOS, and desktop TOTP apps (no hardware token required)
- No reboot needed — a single service restart applies the changes immediately
- Emergency scratch codes provide offline backup access if your phone is unavailable
Step-by-Step: Configuring SSH Two-Factor Authentication
Step 1 — Install the Google Authenticator PAM Module
Open your Linux server and install the required PAM library. The package name differs by distribution family.
On Ubuntu / Debian / Linux Mint:
sudo apt install libpam-google-authenticator -y
On RHEL / Rocky Linux / AlmaLinux / Fedora (EPEL required):
sudo dnf install epel-release -y
sudo dnf install google-authenticator qrencode-libs -y
Tip: On RHEL-based systems, the EPEL repository must be enabled first. The qrencode-libs package enables QR code display in the terminal for easy smartphone scanning.
Step 2 — Generate Your Secret Key
Run the setup command as the user you want to protect — not as root, unless you are specifically securing the root account:
google-authenticator
You will be walked through a short series of interactive prompts. Answer y (yes) to each question. When complete, you will receive:
- A secret key — this links your server to your authenticator app
- A set of emergency scratch codes — single-use backup codes if your phone is unavailable
- A QR code URL — you can paste this into a browser to scan it with your phone
Example output (your keys will be unique):
Your new secret key is: CYZF2YF7HFGX55ZEPQYLHOO
Your emergency scratch codes are:
83714291
53083200
80975623
57217008
77496339
Important: Write down your emergency scratch codes and store them offline (password manager or printed copy). Each code is single-use. If you lose your phone without a backup, these codes are your only way back in.
Step 3 — Configure PAM to Require 2FA for SSH
Open the SSH PAM configuration file:
sudo nano /etc/pam.d/sshd
Add the following line at the top of the file, before any other auth lines:
auth required pam_google_authenticator.so nullok
SELinux Users: If SELinux is enforcing on your system (common on RHEL/Rocky), move the authenticator file to your ~/.ssh/ directory and update the PAM line with the full path:
auth required pam_google_authenticator.so
secret=/home/${USER}/.ssh/.google_authenticator nullok
Step 4 — Update the SSH Daemon Configuration
Open the SSH server configuration file:
sudo nano /etc/ssh/sshd_config
Ensure the following two settings are present and enabled:
UsePAM yes
ChallengeResponseAuthentication yes
For maximum security — requiring both an SSH key and a 2FA code — add this optional line:
AuthenticationMethods publickey,keyboard-interactive
Save the file, then restart the SSH service to apply your changes:
sudo systemctl restart sshd
Step 5 — Link Your Authenticator App
On your smartphone, open Google Authenticator (or any TOTP-compatible app such as Authy, KeePassXC, or the Firefox Authenticator add-on). Tap + and choose Enter a setup key. Type in the secret key generated in Step 2, and give the account a recognizable name.
Your app will now display a rolling 6-digit verification code that refreshes every 30 seconds. The next time you connect via SSH, you will be prompted for this code before your password is accepted:
Using keyboard-interactive authentication.
Verification code:
Using keyboard-interactive authentication.
Password:
Last login: Mon Apr 06 2026 from 10.0.0.1
Verifying the Policy is Applied
After configuring 2FA, confirm it is working before assuming everything is fine. Here are three reliable verification methods:
- Direct SSH Test — Open a new terminal session (do not close your current one) and SSH into your server. You should be prompted for a verification code before your password.
- gpresult Equivalent — On the server, check /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL) for entries confirming PAM google_authenticator is being invoked.
- Refused Code Test — Deliberately enter a wrong verification code. The login should fail immediately without proceeding to the password prompt.
Important: Always keep your current SSH session open while testing 2FA from a separate terminal. If something goes wrong and you are locked out, your active session is your recovery path.
Conclusion
Enabling two-factor authentication for SSH is one of the highest-value security improvements you can make to a Linux server — and it requires no special hardware, no paid services, and no significant downtime. By installing the Google Authenticator PAM module, generating a per-user secret key, and making two small changes to your SSH and PAM configuration files, you have effectively made brute-force and credential-stuffing attacks against your SSH port close to useless.
The Google Authenticator PAM module, combined with proper SSH daemon configuration, means that even a fully compromised password gives an attacker nothing. That rolling 30-second code is the second factor that keeps your server protected even when passwords fail.







