SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

Vaultwarden two-factor authentication on a VPS

Turn on TOTP, email codes, FIDO2, YubiKey and Duo in Vaultwarden 1.37.4, enforce them with the org policy, and get a locked-out user back in safely.

What Vaultwarden two-factor authentication covers in 1.37.4

Vaultwarden two-factor authentication supports five second factors in release 1.37.4: an authenticator app (TOTP, time-based one-time password), email codes, FIDO2 WebAuthn security keys, YubiKey OTP and Duo. An authenticator app needs no server setting at all. The other four each need something on the server: working mail, a correct DOMAIN over HTTPS, Yubico credentials, or Duo credentials.

The 1.37.4 configuration has no setting that forces every user to turn on a second factor. Enforcement comes from the organization policy for two-step login, which Bitwarden's help pages call "Require two-step login". It only covers members of that organization. It also revokes members who have no second factor at the moment you switch it on.

This guide assumes Vaultwarden already runs under Docker Compose behind a reverse proxy with a valid certificate. If yours does not, start with installing Vaultwarden on a VPS and come back. Every setting below is an environment variable. Every name and default comes from the 1.37.4 .env.template and source code. The Vaultwarden wiki is not versioned per release, and it only has pages for WebAuthn and YubiKey, so the source is the better reference here.

Pin the release before you change anything

As of 28 October 2026, the newest tagged release is 1.37.4, published on 5 October 2026. Its release notes list seven security advisories, one rated High, and ask everyone to update as soon as possible. Pin that tag instead of latest, so the behaviour described here is the behaviour you run. Check the releases page for anything newer before you copy the tag.

services:
  vaultwarden:
    image: vaultwarden/server:1.37.4
    restart: unless-stopped
    env_file: vaultwarden.env
    volumes:
      - ./vw-data:/data
    # keep your existing ports, networks and proxy labels as they are

The env_file line keeps secrets such as the SMTP password and the Duo client secret out of the compose file. Create vaultwarden.env next to docker-compose.yml and lock it down, because it will hold credentials:

touch vaultwarden.env
chmod 600 vaultwarden.env

If your existing settings live under environment: instead, add the new variables there. Pick one place, so you never have to wonder which value won.

Two of the seven upgrade notes in 1.37.4 touch two-factor authentication. The Duo DUO_USE_IFRAME setting was removed, so delete it if your file still has it. A new email template, email/recover_twofactor, was added for recovery-code logins. Take a copy of /data first, as described in backing up and restoring Vaultwarden, because a rollback without a backup is a guess.

Apply a change and check that the container came back

After each change in the sections below, run these commands. docker compose config prints the final file with the environment filled in, so you can catch a typo before anything restarts. up -d recreates the container because its environment changed.

docker compose config
docker compose up -d
docker compose ps
docker compose logs --tail 50 vaultwarden

docker compose ps should list the vaultwarden service as running. Vaultwarden checks its configuration when it starts, and some broken combinations of 2FA settings stop it from starting at all. If the service keeps restarting, read the log first. The sections below give the 1.37.4 error text for each of those cases.

Authenticator apps (TOTP): nothing to configure

TOTP works out of the box. Each user scans a QR code in the web vault with an authenticator app such as Aegis or 2FAS.

A TOTP code is calculated from a shared secret and the current time in 30-second steps. That means the server clock matters. Docker containers use the host clock, so check the host:

timedatectl

A healthy host shows System clock synchronized: yes. If it says no, every code is judged against the wrong time.

By default Vaultwarden also accepts the code from the previous and the next 30-second step, to absorb small clock differences between phone and server. The switch for that is AUTHENTICATOR_DISABLE_TIME_DRIFT, default false. Setting it to true makes codes from the previous and next step invalid. Leave it at the default unless you have a reason, because a phone that is a few seconds off then fails at the edge of every step.

Email codes need working SMTP

Email two-step login turns itself on when mail is configured. In the 1.37.4 source it is enabled when SMTP is enabled and either SMTP_HOST or USE_SENDMAIL is set. The template says you need SMTP_FROM plus one of those two to enable the mail service.

SMTP_HOST=smtp.example.com
SMTP_FROM=vaultwarden@example.com
SMTP_FROM_NAME=Vaultwarden
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=vaultwarden@example.com
SMTP_PASSWORD=your-smtp-password

The default SMTP_SECURITY is starttls, with a default port of 587. The force_tls mode defaults to port 465. If you set SMTP_USERNAME, then SMTP_PASSWORD is mandatory.

The email code defaults in 1.37.4 are 6 digits (EMAIL_TOKEN_SIZE), valid for 600 seconds (EMAIL_EXPIRATION_TIME), with 3 attempts before the token is reset and a new email is needed (EMAIL_ATTEMPTS_LIMIT). Keep the size at 6. The template notes that clients assume 6 digits whatever this setting says.

Two optional settings link email codes to enrolment, and both default to false. The template describes EMAIL_2FA_ENFORCE_ON_VERIFIED_INVITE as "Setup email 2FA on registration regardless of any organization policy". It describes EMAIL_2FA_AUTO_FALLBACK as "Automatically setup email 2FA as fallback provider when needed". Both depend on email 2FA, and 1.37.4 rejects them when email 2FA is off.

Email is the weakest of the five factors. A code sent to a mailbox is only as safe as that mailbox's password. Offer it as a fallback, and push people toward an app or a security key.

FIDO2 WebAuthn needs HTTPS and a matching DOMAIN

Security keys are tied to the address of the site. The wiki page for FIDO2 WebAuthn says Vaultwarden must be served over HTTPS with a valid certificate. It also says DOMAIN must be set to the same address you use to reach Vaultwarden, including https://, and a port if it is not 443.

DOMAIN=https://vw.example.com

The template gives two other valid shapes: https://vw.domain.tld:8443 with a port, and https://domain.tld/vw with a path. It also warns that a DOMAIN that does not match the address users open breaks more than security keys. Attachment downloads and links in emails can fail too.

The common mistake is a second hostname. DOMAIN says https://vw.example.com, but some people open https://vault.example.com because the proxy answers both. That second name does not match DOMAIN, so security keys do not work there. Pick one name, set it in DOMAIN, and redirect the other one at the proxy. The wider HTTPS and proxy setup is covered in how secure a self-hosted Vaultwarden really is.

YubiKey OTP needs Yubico API credentials

YubiKey OTP is the mode where the key types a long one-time code when you touch it. It is separate from FIDO2, and many YubiKeys can do both. OTP needs a client ID and a secret key from Yubico:

YUBICO_CLIENT_ID=11111
YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAA

Those are the template's placeholder values, not working ones. YUBICO_SERVER is optional. Leave it unset and Vaultwarden uses the default YubiCloud servers. Set both values or neither. With only one of them and Yubico support enabled, 1.37.4 refuses to start with an error saying both YUBICO_CLIENT_ID and YUBICO_SECRET_KEY must be set for Yubikey OTP support.

If every user can register a FIDO2 key, you may not need OTP at all. FIDO2 needs no third-party credentials, which means one fewer secret on the server.

Duo needs three values from the Duo admin panel

Instance-wide Duo, which the template calls "global Duo support", needs all three of these values. They come from an application you create in your Duo admin panel. Follow Duo's own documentation for that part.

DUO_IKEY=<Client ID>
DUO_SKEY=<Client Secret>
DUO_HOST=<API Hostname>

If global Duo support is enabled and some, but not all, of the three values are set, configuration validation fails with All Duo options need to be set for global Duo support. Leaving all three unset is valid; users then configure their own Duo credentials. Remember the 1.37.4 upgrade note: DUO_USE_IFRAME no longer exists, so remove it rather than carrying it over from an older file.

Can you force 2FA for every Vaultwarden user?

Not with a server setting. The 1.37.4 config.rs and .env.template contain no instance-wide switch that requires a second factor. The closest option is EMAIL_2FA_ENFORCE_ON_VERIFIED_INVITE, which sets up email codes only. That is the state of 1.37.4, so check the release notes of later versions before you assume it still holds.

Two settings are easy to mistake for enforcement. DISABLE_2FA_REMEMBER=true makes users who already have a second factor use it on every login. The "remember" checkbox stays visible but is ignored. It does nothing for a user with no second factor. SIGNUPS_ALLOWED defaults to true, and new accounts start with no second factor unless email 2FA is automatically set up during registration. A public instance with open signups therefore keeps creating accounts that no policy covers.

Enforcement is the organization policy for two-step login. It applies to members of the organization where you turn it on. A personal account that belongs to no organization is never covered. If you want every user covered, every user needs to be a member of an organization with the policy on.

What happens to members without 2FA when the policy is switched on

This is the part that surprises people, so read it before you save the policy. In 1.37.4, saving the two-step login policy as enabled runs enforcement at once. Every confirmed member below Admin rank who has no second factor is revoked. In Vaultwarden's role ordering, that means both the Manager and User roles. Owners and admins are skipped. If mail is configured, each revoked member gets an email. If enforcement hits an error, the policy is not saved.

Bitwarden's documentation describes the same effect: members who are not owners or admins have their access revoked, are emailed, and must become compliant before access is restored. "Revoked" is a membership status. The member is not removed from the organization, but they lose access to its items.

The policy keeps enforcing after that. While it is on, a member below Admin who has no second factor cannot be confirmed, restored or have their membership changed unless EMAIL_2FA_AUTO_FALLBACK=true successfully activates email 2FA for their verified email address. The 1.37.4 error follows the pattern Cannot <action> because 2FA is required (membership <id>). If a member later removes their last second factor, enforcement runs again and they are revoked.

Roll it out in this order:

  1. Make sure owners and admins have a second factor, because the policy will not check them.
  2. Tell members the date, and which factors your server offers.
  3. Give them time to enrol, then switch the policy on.
  4. Restore revoked members after they enrol. The source blocks restoring a member below Admin who still has no second factor unless automatic email fallback successfully activates one.

Recovery codes: what using one actually does

Every user with two-step login has one recovery code. The web vault shows it only after the user enters their master password again. Tell users to write it down or print it, and to keep it outside the vault. A recovery code stored inside the vault it unlocks is no use.

Using the code at login does much more than let one login through. In 1.37.4 it removes all of that user's second factors, clears every "remember this device" token, runs the organization policy check again, logs an event, and clears the stored recovery code. Spaces and letter case in the typed code do not matter, because the source strips spaces and lowercases it before comparing.

Two consequences follow. First, the user has no second factor after recovery and no recovery code either, so they must enrol again to get a new code. Second, if they belong to an organization with the policy on and rank below Admin, the policy check revokes them until they enrol and are restored.

With mail configured, 1.37.4 also emails the user. The template's subject is Two-Step Login Recovered From <ip>, and the body says two-step login on the account has been disabled by using the account's recovery code. A user who gets that email and did not use the code should change their master password at once. A failed send is only logged, and the login still goes through.

How an admin removes a locked-out user's 2FA

A user who lost their phone and their recovery code can still be helped. The 1.37.4 admin page has a "Remove all 2FA" button, shown only for users who have two-step login enabled. It deletes all of that user's second factors, clears their remember-device tokens, runs the organization policy check, and clears their recovery code.

The admin page needs ADMIN_TOKEN unless DISABLE_ADMIN_TOKEN=true bypasses its built-in authentication. If neither is set, the admin panel is disabled. The template recommends an Argon2 PHC string rather than a plain token, and the Vaultwarden security guide covers how to protect that page.

Before you press the button, confirm the person is who they claim to be, through a channel an attacker would not control. Removing someone's second factor because of one email is exactly the attack the second factor was meant to stop.

After you press it, the same policy rule applies as with a recovery code. A Manager or User in an organization with the policy on may be revoked straight away. Have the user enrol a new factor right after, then restore their membership.

Admin removal fixes a lost second factor. It does not give anyone else access to a vault. If you want a trusted person to be able to reach someone's vault in an emergency, that is a separate feature: Vaultwarden emergency access.

Optional: alerts for logins that stop at the second step

INCOMPLETE_2FA_TIME_LIMIT defaults to 3 minutes. If a login passes the master password but does not finish the second step in that time, Vaultwarden emails the user. If the user did not try to log in, someone else knows their master password. Set it to 0 to turn it off. INCOMPLETE_2FA_SCHEDULE runs the check every minute by default. Both need working mail to be any use.

Why a 2FA change broke logins, with the cause for each

The container restarts in a loop after you added YubiKey or Duo. One value of a required group is missing. Run docker compose logs --tail 50 vaultwarden and look for the Yubico or Duo error described above. docker compose config shows which values actually reach the container.

Security key registration fails on one hostname but works on another. DOMAIN does not match the address in the browser. Fix the hostname, or redirect the second name to the first at the proxy.

Email codes never arrive. The mail transport is not working. Check the log for SMTP errors right after a code is requested. Then check SMTP_SECURITY against the port: starttls with 587, force_tls with 465.

Every TOTP code is rejected. The host clock is wrong, or AUTHENTICATOR_DISABLE_TIME_DRIFT=true removed the tolerance. timedatectl answers the first question.

A member suddenly lost access to shared items. The two-step login policy revoked them, either when it was switched on or when they removed their last second factor. They enrol a factor, and then their membership can be restored.

FAQ

Can I force two-factor authentication for all users in Vaultwarden?

Not with a server setting in 1.37.4. Its configuration has no instance-wide switch. Enforcement comes from the organization policy for two-step login, which covers members of that organization only. The policy does not check owners and admins, so make sure they enrol by hand.

What happens to existing members when I turn on the two-step login policy?

In Vaultwarden 1.37.4, every confirmed member below Admin rank with no second factor is revoked the moment the policy is saved. They are emailed if mail is configured. They stay in the organization but lose access to its items. After they enrol a second factor, their membership can be restored.

Why does registering a security key fail on my Vaultwarden server?

FIDO2 WebAuthn needs HTTPS with a valid certificate. DOMAIN must also match the exact address users open, including https:// and any port other than 443. If people reach the vault on a second hostname, security keys fail there. Use one hostname and redirect the others.

What does the Vaultwarden recovery code do when I use it?

It removes every second factor on the account and clears remembered devices. The code is then used up, so you must turn two-step login on again to get a new one. With mail configured, 1.37.4 emails the user about it. If you are in an organization with the two-step login policy and rank below Admin, you are revoked until you enrol again.

Can a Vaultwarden admin reset a user's 2FA?

Yes. With ADMIN_TOKEN set, the 1.37.4 admin page has a "Remove all 2FA" button for users who have two-step login enabled. It deletes all their second factors and their recovery code. Verify the user's identity first, and have them enrol again at once, because the organization policy can revoke them straight after.

Was this article useful?