Rackvio supports time-based one-time passwords (TOTP, RFC 6238) as a second factor on password logins. You scan a QR code with an authenticator app, and from then on signing in needs your password and a six-digit code from your phone. A stolen password is no longer enough on its own.
This is free in every edition, including the fully air-gapped self-hosted Community Edition. There is no tier gate, no capability flag and no licence check on it — a security baseline should not be an upsell.
| Community | Cloud Starter | Cloud Growth | Enterprise | |
|---|---|---|---|---|
| TOTP on password logins | Yes | Yes | Yes | Yes |
| Single-use recovery codes | Yes | Yes | Yes | Yes |
| Admin reset of another user’s enrolment | Yes | Yes | Yes | Yes |
| Org-wide “require MFA” with a grace period | Yes | Yes | Yes | Yes |
| SSO, where your identity provider owns the second factor | — | Yes | Yes | Yes |
SSO is the only row that is paid, and it is a different thing: it hands authentication to your identity provider entirely. The second factor on a Rackvio password is not withheld from anyone.
The setting lives on your own account page — avatar menu -> Change Password, or
/account/change-password, listed as Security in the account navigation. Look for the
Two-factor authentication card.
Enrolment is not active until you confirm. If you scan the QR and close the dialog, nothing is protecting your account yet — the card says so, and you start again from step 1.
The code you confirm with is a used code. Rackvio refuses to accept the same code twice, which is what stops an intercepted code being replayed. So if you finish setup and immediately sign in somewhere else within the same 30-second window, that sign-in is refused with “That code did not match.” Wait for your app to roll to the next code and it works. This is correct behaviour, not a fault.
Confirming enrolment produces ten recovery codes. Each looks like 3F7K-9QRT — eight
characters and a dash. They are drawn from an alphabet with no 0, O, 1, I or L in it, so
there is nothing to misread when you write them down.
On a self-hosted install — especially an air-gapped one with a single administrator — there may be nobody who can help you. An admin reset needs a second administrator with a working login. If you are the only one, your recovery codes are the whole of your safety net.
Enter your email and password as usual. Rackvio then asks for a code:
3f7k9qrt and 3F7K-9QRT are the same code.Codes are accepted within plus or minus 30 seconds of your phone’s clock, so a slightly fast or slow device still works. A code that has already been used is never accepted again, even inside that window.
Wrong codes count toward the same lockout counter as wrong passwords. There is deliberately not a second, separate MFA lockout — one counter, one lockout, one thing for an administrator to clear.
If the recovery codes are gone too, another administrator in your organization can reset your enrolment from Administration -> Users -> Reset MFA. That clears your authenticator and every one of your recovery codes, and it is recorded in the audit log with who did it, to whom, and when. Enrol a new authenticator immediately afterwards — until you do, your account is protected by a password only.
An administrator cannot use that button on their own row; it is not offered. Changing your own second factor goes through Change Password, which asks you to prove you still hold one.
Administrators can make MFA mandatory from Administration -> Security.
403. The moment they confirm an
authenticator, the next sign-in is a normal session.If an organization ends up with no enrolled administrator who can sign in, the requirement can be cleared from the backend container:
# One organization
docker compose exec backend rackvio admin mfa-disable-requirement "Default Organization"
# Every organization (multi-tenant deployments)
docker compose exec backend rackvio admin mfa-disable-requirement allThis clears the org-wide requirement and its grace clock, and writes an audit row. It removes nobody’s second factor — enrolled users keep their authenticators. To clear one user’s enrolment, use the admin reset in the UI.
SSO users are never prompted for a Rackvio TOTP code, in grace or after it. Their second factor belongs to their identity provider, which is where it should be configured and enforced. This holds for service accounts too: an integration account cannot produce a TOTP code, so requiring one of it would simply be a scheduled outage.
SECRET_KEYTOTP secrets are encrypted at rest. By default the encryption key is derived from your existing
SECRET_KEY, which is what makes MFA work on a Community install that configures nothing extra.
Before you rotate SECRET_KEY, print and pin the current derived key:
docker compose exec backend rackvio admin mfa-print-key
# -> set MFA_ENCRYPTION_KEY to the printed value in your environment,
# THEN rotate SECRET_KEY.MFA_ENCRYPTION_KEY is optional and, once set, takes precedence over the derived key — so existing
enrolments keep working across the rotation.
If you rotate without doing this, nobody is permanently locked out. Recovery codes are bcrypt-hashed and do not depend on that key, so every enrolled user can still sign in with one. What it costs is one recovery code and a re-scan per user, and at the login screen they are told “your authenticator can no longer be verified” rather than being sent to a password reset that cannot help.
This belongs in your incident runbook, not only here. Secret rotation is something you do at 3am after a security incident, which is exactly when nobody is thinking about MFA.
A user who controls the account’s mailbox can clear an MFA lockout by completing a password reset, because
POST /auth/reset-passwordclearsfailed_login_attemptsandlocked_until. They still cannot pass the second factor: the reset rewritespassword_hashand touches neithertotp_secret_encnoruser_mfa_recovery_codes. This is exactly the behaviour password lockouts have always had, and MFA reuses the same two columns by design so that an operator unlocking an account in the UI clears one lockout state rather than leaving a second latch closed.
Naming these is more useful to you than leaving them to be discovered: