Two-factor authentication (2FA) requires both an SSH key and a time-based one-time password (TOTP) to log in, providing defence-in-depth even if your SSH key is compromised.
Step 1 — Install Google Authenticator PAM Module
$apt update$apt install -y libpam-google-authenticatorStep 2 — Configure 2FA for a User
Run as the user who will use 2FA (not root):
$google-authenticatorAnswer the prompts:
Do you want authentication tokens to be time-based (y/n) y
Your new secret key is: JBSWY3DPEHPK3PXP
Your verification code is 123456
Your emergency scratch codes are:
12345678
87654321
...
Do you want me to update your "/home/deploy/.google_authenticator" file? (y/n) y
Do you want to disallow multiple uses of the same authentication token? (y/n) y
By default, a new token is generated every 30 seconds. Do you want to allow a window of 3 tokens? (y/n) n
Do you want to enable rate-limiting? (y/n) y[!IMPORTANT] Save the emergency scratch codes in a secure location. They are single-use codes for when you cannot access your authenticator app.
Scan the QR code with Google Authenticator, Authy, or any TOTP app.
Step 3 — Configure PAM
$nano /etc/pam.d/sshdAdd this line at the top:
auth required pam_google_authenticator.soStep 4 — Configure SSH Daemon
$nano /etc/ssh/sshd_configUpdate these settings:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactiveRestart SSH:
$systemctl restart sshdStep 5 — Test the Configuration
Open a new terminal and connect:
$ssh deploy@YOUR_SERVER_IPAuthenticated with partial success.
Verification code:Enter the 6-digit TOTP code from your authenticator app.
[!WARNING] Test 2FA in a new terminal before closing your existing session. If 2FA is misconfigured, you could lock yourself out. Keep the LightYear web console available as a fallback.
