In this guide
  1. Why this is worth the ten minutes
  2. Adding TOTP 2FA to SSH
  3. Enabling 2FA on aaPanel
  4. What to do about backup codes
  5. A note on hardware keys
  6. Frequently asked questions

Our VPS security checklist covers disabling password auth for SSH in favor of keys, which handles the most common automated attack. Two-factor authentication is the next layer: it protects you specifically against the scenario where a private key itself is compromised — copied off a laptop, exposed in a misconfigured backup, or extracted from a compromised CI pipeline. It's a genuinely quick addition once you know the steps.

Why this is worth the ten minutes

Key-based SSH auth is strong, but it's a single factor — whoever has the key file gets in. Adding a second factor (a time-based one-time code from an authenticator app) means a leaked key alone isn't enough, which meaningfully changes the risk profile for very little ongoing friction once it's set up.

Adding TOTP 2FA to SSH

On most Debian/Ubuntu systems, Google's PAM module handles this cleanly:

sudo apt install libpam-google-authenticator
google-authenticator

Running google-authenticator as your user generates a QR code to scan into any TOTP app (Google Authenticator, Authy, 1Password, and similar all work identically here — the standard is open). Then wire it into SSH's PAM configuration:

# in /etc/pam.d/sshd, add:
auth required pam_google_authenticator.so

# in /etc/ssh/sshd_config, ensure:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

That last line is the important one — it requires both your SSH key and the TOTP code, not either/or. Restart SSH, and — critically — test in a second terminal window before closing your current session, the same rule that applies to every SSH configuration change.

Enabling 2FA on aaPanel

aaPanel has TOTP-based 2FA built into its security settings — enable it from the panel's security/settings page, scan the QR code into your authenticator app, and confirm with a generated code. Since the control panel is arguably an even more attractive target than SSH itself (one login gives access to every site and database on the server), this is worth enabling even if you skip 2FA everywhere else initially.

What to do about backup codes

Both the SSH PAM module and aaPanel's 2FA generate backup/scratch codes when you enable them — save these somewhere durable and separate from the server itself (a password manager, not a text file on the same machine). Losing your phone without backup codes on hand means being locked out of your own server, which is a genuinely painful way to learn this lesson.

A note on hardware keys

Hardware security keys (YubiKey and similar, using FIDO2/WebAuthn or PIV) offer a stronger guarantee than TOTP codes, since they resist phishing in a way that a time-based code typed into a fake prompt doesn't. SSH supports hardware-key-backed keys natively in modern OpenSSH versions. This is worth the upgrade if you're securing infrastructure for a team, but TOTP alone is a solid, low-friction improvement over no second factor at all for a solo founder's setup.

Frequently asked questions

Will this lock me out if I lose my phone?

Only if you didn't save the backup codes somewhere separate — which is why that step isn't optional. With backup codes saved, losing your phone is an inconvenience (re-registering a new authenticator app), not a lockout.

Does 2FA slow down routine SSH access noticeably?

Marginally — you type a six-digit code in addition to your key being used automatically, adding a few seconds per login. For how often most solo founders actually SSH into a production server, this is a trivial cost for the security benefit.

Should I require 2FA for every user on the server, or just admin accounts?

At minimum, every account with sudo or control panel admin access — those are the accounts whose compromise actually matters. For a solo-run server, that's usually just your own account, making this a quick, one-time setup rather than an ongoing policy to enforce across a team.