sodcalculator

10 Tech How-To

Secure a Linux VPS with Two-Factor Authentication

Guide 10-38257 · Updated · Step by step

This guide walks you through adding a second layer of authentication to your Linux VPS, so a stolen password alone won’t let an attacker in. You’ll set up time-based one-time passwords (TOTP) using a standard authenticator app, and optionally hardware keys. You’ll need root or sudo access to your VPS and an authenticator app on your phone (like Google Authenticator, Authy, or Aegis).

What You’ll Need

  • A Linux VPS (Ubuntu, Debian, CentOS, or similar) with SSH access.
  • Root or sudo privileges.
  • A smartphone with an authenticator app installed (Google Authenticator, Authy, Aegis, etc.).
  • Optional: A hardware security key (YubiKey, etc.) if you want to use U2F.

Step-by-Step

  1. Update your system – Log in to your VPS via SSH and run the package manager update. For Ubuntu/Debian: sudo apt update && sudo apt upgrade -y. For CentOS/RHEL: sudo yum update -y. This ensures you have the latest security patches.
  2. Install the PAM module for TOTP – The most common is libpam-google-authenticator (Ubuntu/Debian) or google-authenticator (CentOS/RHEL). Run:
    • Ubuntu/Debian: sudo apt install libpam-google-authenticator -y
    • CentOS/RHEL: sudo yum install google-authenticator -y
  3. Configure the authenticator for your user – Run google-authenticator as the user you want to protect (e.g., your main user, not root). Answer the prompts:
    • “Do you want authentication tokens to be time-based?” – y
    • It will display a QR code and a secret key. Open your authenticator app and scan the QR code.
    • For the emergency scratch codes, write them down and store them safely.
    • Answer the remaining questions: “Update your .google_authenticator file?” – y; “Disallow multiple uses?” – y; “Increase time skew?” – n (or y if your server clock drifts); “Enable rate limiting?” – y.
  4. Configure SSH to use PAM – Edit the SSH daemon config: sudo nano /etc/ssh/sshd_config. Find the line ChallengeResponseAuthentication and set it to yes (on older systems) or KbdInteractiveAuthentication to yes (on newer ones). Also ensure UsePAM is set to yes (it usually is). Save and exit.
  5. Edit the PAM SSH configuration – Open /etc/pam.d/sshd with sudo. Add the following line at the top (before any other auth lines):
    auth required pam_google_authenticator.so

    If you want to allow fallback to password when no TOTP is set up (not recommended), use auth sufficient pam_google_authenticator.so instead. Save and exit.

  6. Restart SSH – Run sudo systemctl restart sshd (or ssh on some systems). Be careful: if you make a mistake, you might lock yourself out. Keep your current SSH session open and test in a new terminal window.
  7. Test the login – Open a new terminal and try to SSH to your VPS. You should be prompted for your password, then for the verification code from your authenticator app. Enter both correctly, and you’re in.
  8. Optional: Set up U2F hardware keys – If you have a YubiKey, you can install libpam-u2f (Ubuntu/Debian) and configure it. Run pamu2fcfg to generate a configuration line, then add it to /etc/pam.d/sshd along with the TOTP line. This is more advanced; only do this if you’re comfortable.

Common Mistakes

  • Locking yourself out – The most common issue. Always keep your current SSH session open and test in a second session before closing it.
  • Editing the wrong PAM file – You must edit /etc/pam.d/sshd, not /etc/pam.d/login or /etc/pam.d/common-auth (unless you want TOTP for console logins too, which is fine but separate).
  • Clock skew – TOTP codes are time-based. If your server’s clock is off by more than a minute, codes won’t work. Use NTP to sync time: sudo timedatectl set-ntp true.
  • Not saving scratch codes – If you lose your phone, you’ll be locked out unless you have the scratch codes. Store them offline.
  • Using the wrong SSH config option – On newer OpenSSH versions, ChallengeResponseAuthentication is deprecated; use KbdInteractiveAuthentication.

Tips

  • Back up your secret key – When you run google-authenticator, it prints a secret key. Save it in a password manager or a secure file. This lets you re-add the account to a new phone without re-running the setup.
  • Use a dedicated user – Disable root SSH login (PermitRootLogin no) and use a regular user with sudo. This reduces the impact of a compromised root account.
  • Rate limiting – The rate limiting option in google-authenticator helps prevent brute-force attempts. Keep it enabled.
  • Consider key-based SSH instead of passwords – SSH keys are more secure than passwords. Combine them with TOTP for defense in depth.
  • Test in a non-production environment first – If this is a production server, consider setting up a test VM to practice the steps.

Troubleshooting

  • You’re locked out – If you closed all sessions and can’t get in, use your VPS provider’s web console (like VNC) to log in. Then revert the changes: remove the line from /etc/pam.d/sshd and restart SSH.
  • Codes aren’t accepted – Check your server’s time with date. If it’s off, sync with NTP. Also ensure your phone’s time is set to automatic.
  • SSH still asks only for password – Make sure you edited the correct PAM file and that UsePAM is enabled. Also check the SSH config for any AuthenticationMethods line that might override PAM.
  • PAM errors in logs – Check /var/log/auth.log (or /var/log/secure on CentOS) for errors like “pam_google_authenticator.so: unable to open”. This usually means the module isn’t installed or the path is wrong.
  • QR code doesn’t scan – If you can’t scan the QR code, manually enter the secret key in your authenticator app. It’s shown in the terminal output.

Frequently Asked Questions

Can I use 2FA for all users, not just one?

Yes. Each user must run google-authenticator themselves. The PAM line applies to all users, so each user needs their own secret file.

What if I lose my phone?

Use one of the scratch codes generated during setup. If you lost those too, you’ll need to log in via the provider’s console and remove the PAM line temporarily, then reconfigure.

Does this work with SSH keys?

Yes. You can combine SSH keys with TOTP. The PAM module will ask for the code even if you authenticate with a key, depending on your SSH config.

Can I use this for other services like SFTP?

Yes, SFTP uses the same SSH daemon, so it will also require the TOTP code. Other services like web login would need separate configuration.

Is TOTP the same as 2FA?

TOTP is a type of 2FA. It uses something you have (your phone) and something you know (your password). It’s a common implementation of 2FA.

Do I need to do this for the root user too?

It’s highly recommended, but if you disable root SSH login, you don’t need to set it up for root. Focus on your regular user with sudo privileges.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →