List of Articles Icon

Knowledge Base

Guides and answers for your VPS, the client area, and billing

Two-factor authentication for SSH (TOTP on Ubuntu/Debian)

What this is

Requiring a six-digit authenticator code at SSH login, the same TOTP apps (Google Authenticator, Authy, 1Password) you use for your account's 2FA, enforced by the server through libpam-google-authenticator.

First, the honest positioning, because this upgrade is often oversold:

  • If you still allow password logins, TOTP is a genuinely big upgrade: a leaked or guessed password stops being enough. (Though the bigger upgrade remains switching to keys, and our network already blunts password brute-force.)
  • If you're already key-only, a passphrase-protected key is effectively two factors (the key file + the passphrase), so TOTP adds a third, mostly protecting against a stolen, unlocked key. Worth it for high-stakes boxes and compliance checklists; optional for a hobby server.

The strong combination this guide builds: key + code (publickey,keyboard-interactive), something you have, something you know, something that rotates.

Setup

Everything below on Ubuntu/Debian; same module on RHEL-family via the google-authenticator package (EPEL).

1. Install the PAM module:

apt install libpam-google-authenticator

2. Enroll the login user. As the user who logs in over SSH (not necessarily root), run:

google-authenticator

Answer y to time-based tokens, scan the QR with your authenticator app, and save the emergency scratch codes somewhere safe off the server, they are your login of last resort if the phone is gone. The sensible defaults for the remaining prompts: update the file (y), disallow token reuse (y), and enable rate limiting (y).

3. Tell PAM to require the code. Add to the top section of /etc/pam.d/sshd:

auth required pam_google_authenticator.so

(For a gradual rollout, auth required pam_google_authenticator.so nullok lets users who haven't enrolled yet log in without a code, remove nullok once everyone's enrolled.)

4. Tell SSH to ask. In /etc/ssh/sshd_config:

KbdInteractiveAuthentication yes

(older configs call it ChallengeResponseAuthentication), and set the policy with AuthenticationMethods:

  • Key plus code (recommended): AuthenticationMethods publickey,keyboard-interactive
  • Password plus code: AuthenticationMethods password,keyboard-interactive (make sure PasswordAuthentication yes in this case)

5. Restart and test, without closing your session:

systemctl restart ssh

Then, from a second terminal, log in fresh: key (or password) first, then Verification code: prompts for the app's six digits.

The anti-lockout discipline

PAM misconfiguration is the classic way to lock yourself out of SSH entirely, so the rules from every firewall and key guide apply doubly: keep your working session open until a second terminal proves the new flow, keep the scratch codes off-server, and know the safety net, the Console in your client area doesn't authenticate through SSH or PAM's sshd stack, so even a fully botched config is a fix-it-from-the-console incident, not a rebuild.

Operational notes

  • TOTP lives and dies by the clock. Codes are time-based; if the server's clock drifts, valid codes get rejected. Verify timedatectl shows System clock synchronized: yes (systemd-timesyncd handles it by default), before blaming the app.
  • Each user enrolls separately (google-authenticator run as that user; the secret lives in their ~/.google_authenticator). Automation and deploy accounts are usually better served by keys without TOTP, scope AuthenticationMethods per-user with a Match User block if you mix.
  • Know what it protects: SSH logins, that's all. Your web apps, panels, and everything else exposed have their own login doors.

Still need help?

You can open a support ticket. So we can help on the first reply, it's worth mentioning:

  • the VPS hostname or IP,
  • where the flow fails (PAM, sshd config, a rejected code), with the exact prompt or error,
  • whether the Console still gets you in.
  • "How do I add two-factor authentication to SSH?"
  • "How do I set up google-authenticator on Ubuntu?"
  • "Should I use SSH keys, TOTP, or both?"
  • "Why are my SSH verification codes rejected (clock skew)?"
  • "What happens if I lose my phone (scratch codes)?"
  • "Can some users skip the code requirement (nullok, Match User)?"
Last reviewed: 2026-07-02