> ## Documentation Index
> Fetch the complete documentation index at: https://help.freakhosting.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Set Up SSH 2FA with Google Authenticator on Linux

> Set up SSH 2FA with Google Authenticator: install libpam-google-authenticator, add the PAM module and require publickey,keyboard-interactive in sshd.

To add two-factor authentication to SSH, install `libpam-google-authenticator`, run `google-authenticator` as your user and scan the QR code, add `auth required pam_google_authenticator.so` to `/etc/pam.d/sshd`, then set `KbdInteractiveAuthentication yes` and `AuthenticationMethods publickey,keyboard-interactive` in your SSH config. After a restart, each login needs your SSH key and a 6-digit code.

| Difficulty | Time | Works on | Needs |
| - | - | - | - |
| Intermediate | 20 minutes | Ubuntu 22.04 / 24.04, Debian 12 / 13, AlmaLinux and Rocky Linux 9 / 10 (EPEL) | Sudo user with a working SSH key, an authenticator app |

Two-factor authentication (2FA) means you need two things to log in: something you have (your SSH key) and a time-based one-time code (TOTP) from an app such as Google Authenticator, Microsoft Authenticator or any other TOTP app.

## Before you start

* Log in with an [SSH key](https://help.freakhosting.com/portals/other/how-to-create-and-use-ssh-keys.md) as a [sudo user](https://help.freakhosting.com/portals/other/how-to-create-a-sudo-user-on-linux.md). Root users can leave out `sudo`.
* Check the server clock is synchronised, because codes depend on the time: `timedatectl` should show `System clock synchronized: yes`. See [set the timezone and time sync](https://help.freakhosting.com/portals/other/how-to-set-the-timezone-and-time-sync-on-linux.md).
* Keep your current SSH session open until you have tested a new login.
* If you get locked out, use the [VNC console](https://help.freakhosting.com/portals/vps-panel/how-to-enable-and-use-vnc-console-access.md). It logs in on the local console, which this setup does not change. On a dedicated server, [open a ticket](https://freakhosting.com/clientarea/submitticket.php) if you need console access.

> [!WARNING]
>
> A mistake in `/etc/pam.d/sshd` or the SSH config can block every SSH login. Make each change, test it from a second terminal, and only then close your first session.

## How to set up SSH 2FA

**1. Install the PAM module**

> [tab] Ubuntu / Debian
>
> ```bash theme={null}
> sudo apt update
> sudo apt install libpam-google-authenticator
> ```

> [tab] AlmaLinux / Rocky
>
> The package is in EPEL.
>
> ```bash theme={null}
> sudo dnf install epel-release
> sudo dnf install google-authenticator
> ```

**2. Create your secret as your normal user**

Run this as the user who will log in, **without** `sudo`:

```bash theme={null}
google-authenticator -t -d -r 3 -R 30 -w 3
```

`-t` makes time-based codes, `-d` stops a code being used twice, `-r 3 -R 30` allows 3 logins every 30 seconds and `-w 3` accepts the previous, current and next code. Scan the QR code with your app (or type in the secret key it prints if no QR code appears) and enter the code the app shows. The tool saves your secret in `~/.google_authenticator`.

**3. Save the emergency codes**

The tool prints five emergency scratch codes. Each works once if you lose your phone. Store them in your password manager, not on the server.

**4. Add the module to PAM**

```bash theme={null}
sudo nano /etc/pam.d/sshd
```

> [tab] Ubuntu / Debian
>
> Comment out the password line near the top and add the module below it:
>
> ```text theme={null}
> # @include common-auth
> auth required pam_google_authenticator.so
> ```

> [tab] AlmaLinux / Rocky
>
> Comment out the password line near the top and add the module below it:
>
> ```text theme={null}
> #auth       substack     password-auth
> auth       required     pam_google_authenticator.so
> ```

Commenting out the password line means PAM asks only for the code. Your SSH key is checked by SSH itself.

**5. Tell SSH to ask for key and code**

```bash theme={null}
sudo nano /etc/ssh/sshd_config.d/20-2fa.conf
```

```ini theme={null}
KbdInteractiveAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
```

Older guides use `ChallengeResponseAuthentication yes`. That is the deprecated name for `KbdInteractiveAuthentication` and does the same thing.

**6. Test the config and restart SSH**

```bash theme={null}
sudo sshd -t
```

> [tab] Ubuntu / Debian
>
> ```bash theme={null}
> sudo systemctl restart ssh
> ```

> [tab] AlmaLinux / Rocky
>
> ```bash theme={null}
> sudo systemctl restart sshd
> ```

## How to check it worked

Open a **new** terminal and connect:

```bash theme={null}
ssh alex@203.0.113.10
```

After your key is accepted, SSH asks for `Verification code:`. Type the 6-digit code from your app. If you are let in, 2FA works and you can close the old session. Check what SSH now enforces with:

```bash theme={null}
sudo sshd -T | grep -E 'authenticationmethods|kbdinteractive'
```

```text theme={null}
kbdinteractiveauthentication yes
authenticationmethods publickey,keyboard-interactive
```

## How to roll out 2FA when several users share the server

Add `nullok` to the PAM line (`auth required pam_google_authenticator.so nullok`). Users who have not yet run `google-authenticator` can then log in without a code. Remove `nullok` once every user has set it up, or those users can skip 2FA.

## How to turn 2FA off again

Remove `/etc/ssh/sshd_config.d/20-2fa.conf`, restore the original line in `/etc/pam.d/sshd`, run `sudo sshd -t` and restart SSH.

## Frequently asked questions

### My code is always rejected. What is wrong?

Usually the server clock is wrong. Run `timedatectl` and enable time sync. Also check you scanned the code for the right user: the secret is stored per user in `~/.google_authenticator`.

### Does SSH 2FA work with SFTP clients like FileZilla or WinSCP?

Yes, if the client supports keyboard-interactive login. It shows a prompt for the code. Automated scripts that cannot answer a prompt will stop working, so give them a separate user that is excluded with a `Match User` block.

### What if I lose my phone?

Log in with one of the emergency scratch codes instead of a TOTP code, then run `google-authenticator` again to create a new secret. Without codes, use the VNC console.

### On AlmaLinux the code prompt never appears. Why?

Check SELinux denials with `sudo ausearch -m AVC -ts recent`. See [use SELinux on AlmaLinux and Rocky](https://help.freakhosting.com/portals/other/how-to-use-selinux-on-almalinux-and-rocky.md) to read and fix them.

## Related guides

> [card] [VPS and dedicated server guides](https://help.freakhosting.com/portals/other/vps-and-dedicated-server-guides.md)
>
> Every guide in this section.

> [card] [Create and use SSH keys](https://help.freakhosting.com/portals/other/how-to-create-and-use-ssh-keys.md)
>
> The first factor for 2FA.

> [card] [Disable root login](https://help.freakhosting.com/portals/other/how-to-disable-root-login-over-ssh.md)
>
> Stop direct root logins.

> [card] [Set up Fail2Ban](https://help.freakhosting.com/portals/other/how-to-set-up-fail2ban-for-ssh-on-ubuntu.md)
>
> Block brute-force attempts.

> [card] [Security checklist](https://help.freakhosting.com/portals/other/linux-server-security-checklist.md)
>
> Harden the rest of your server.

***

> [!NOTE]
>
> **Checked against the official [google-authenticator-libpam project](https://github.com/google/google-authenticator-libpam), [Ubuntu SSH 2FA tutorial](https://ubuntu.com/tutorials/configure-ssh-2fa) and [sshd\_config manual](https://manpages.ubuntu.com/manpages/noble/man5/sshd_config.5.html)** on 4 November 2026; package installation, the `google-authenticator` options and the SSH configuration (`sshd -t`, `sshd -T`) were tested on Ubuntu 24.04 LTS. Commands can differ on other distributions or releases.

> [!NOTE]
>
> ### Need Extra Help?
>
> If you encounter any issues, our support team is ready to assist:
>
> * **Live Chat:** Quick assistance via our website.
> * **Support Ticket:** [Open a Ticket](https://freakhosting.com/clientarea/submitticket.php)
> * **Discord:** [Join our Community](https://discord.gg/freakhosting)
> * **Email:** [support@freakhosting.com](mailto:support@freakhosting.com)

> [!TIP]
>
> ### Save on Your Hosting
>
> Ready to upgrade your hosting? Use code **KB20** at checkout for **20% off** your first order!

***

**Last Updated:** November 2026


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.