Vaultwarden 2FA: logowanie dwuetapowe krok po kroku
Włącz drugi składnik logowania w Vaultwarden: e-mail, Duo, YubiKey OTP i klucz FIDO2. Konfiguracja SMTP, kod odzyskiwania i zabezpieczenie strony /admin.
Czym jest logowanie dwuetapowe w Vaultwarden
Logowanie dwuetapowe w Vaultwarden, czyli 2FA (uwierzytelnianie dwuskładnikowe), ustawia się w dwóch miejscach naraz. Użytkownik włącza wybraną metodę w sejfie webowym, ale administrator serwera musi ją wcześniej udostępnić przez zmienne środowiskowe kontenera. Gdy pominiesz tę drugą część, połowa metod po prostu nie pojawi się na liście, a Ty będziesz szukał błędu w przeglądarce zamiast w pliku docker-compose.yml.
Serwer udostępnia pięć metod: aplikację TOTP (jednorazowy kod oparty na czasie), kod wysyłany e-mailem, Duo, YubiKey OTP oraz klucze FIDO2 WebAuthn. TOTP działa od razu po instalacji. Kod e-mailem wymaga działającej poczty wychodzącej, i to jest miejsce, w którym zatrzymuje się większość osób hostujących samodzielnie. Pozostałe trzy metody wymagają wpisów w konfiguracji kontenera i restartu.
Tekst powstał na wersji Vaultwarden 1.37.3, wydanej 13 września 2026. Zanim skopiujesz zmienne do siebie, sprawdź numer własnej wersji w stopce strony /admin i przejrzyj release notes projektu, bo nazwy opcji bywają dodawane między wydaniami.
Jednej rzeczy ta wersja nie robi: nie pozwala zalogować się samym passkey, bez hasła głównego. README projektu wymienia FIDO2 WebAuthn wyłącznie jako drugi składnik po haśle. Materiały o „Login with passkeys” opisują hostowaną usługę Bitwarden, a nie ten serwer. Jeśli planujesz wdrożenie dla zespołu, sprawdź ten punkt w release notes w dniu wdrożenia, a nie w cudzym artykule.
Najpierw kod odzyskiwania, potem drugi składnik
Przy własnym serwerze nie ma infolinii, która zresetuje konto. Jesteś użytkownikiem i pomocą techniczną w jednej osobie, więc kolejność musi być odwrotna niż w usłudze hostowanej: najpierw droga wyjścia, dopiero potem zamek.
Po włączeniu pierwszej metody wejdź w sejfie webowym w Ustawienia, dalej Bezpieczeństwo, dalej Logowanie dwuetapowe, i kliknij „View recovery code”. Ten kod wyłącza wszystkie metody 2FA na koncie, więc traktuj go jak drugie hasło główne. Zapisz go poza sejfem. Kod odzyskiwania trzymany w sejfie, do którego nie możesz się zalogować, nie jest kopią zapasową. Kartka schowana w domu w zupełności wystarczy.
Druga droga wyjścia jest po stronie serwera. Na liście użytkowników na stronie /admin, przy koncie z włączonym drugim składnikiem, pojawia się przycisk „Remove all 2FA”. To ratunek na sytuację, w której tracisz telefon i kod odzyskiwania naraz. To także powód, dla którego strona /admin wymaga mocniejszej ochrony niż konto zwykłego użytkownika: kto wejdzie na /admin, ten zdejmuje drugi składnik każdemu w instancji. Wracam do tego niżej.
SMTP, bez którego metoda e-mail nie zadziała
SMTP (simple mail transfer protocol) to protokół poczty wychodzącej. Vaultwarden nie ma własnego serwera pocztowego, więc dopóki nie wskażesz mu cudzego, metoda „Email” nie pojawi się wśród dostępnych opcji 2FA. Nie zobaczysz przy tym żadnego komunikatu o braku konfiguracji, bo z punktu widzenia sejfu ta metoda zwyczajnie nie istnieje.
services:
vaultwarden:
image: vaultwarden/server:1.37.3
environment:
DOMAIN: https://sejf.example.pl
SIGNUPS_ALLOWED: "false"
SMTP_HOST: smtp.example.pl
SMTP_FROM: vaultwarden@example.pl
SMTP_FROM_NAME: Vaultwarden
SMTP_SECURITY: starttls
SMTP_PORT: "587"
SMTP_USERNAME: vaultwarden@example.pl
SMTP_PASSWORD: tajne-hasloZmienna SMTP_SECURITY przyjmuje trzy wartości i każda ma swój port. starttls to wartość domyślna z portem 587, czyli port submission, na którym połączenie zaczyna się jawnie i dopiero potem przechodzi na szyfrowane. force_tls to szyfrowanie od pierwszego pakietu, zwykle na porcie 465. off wyłącza wymóg szyfrowania i schodzi na port 25. Jeśli ustawisz force_tls i zostawisz port 587, połączenie zawiesi się do czasu przekroczenia limitu z SMTP_TIMEOUT, bo serwer po drugiej stronie czeka na jawne EHLO, a Vaultwarden od razu próbuje uzgodnić TLS (transport layer security).
Adres z SMTP_FROM musi być nadawcą, którego Twój dostawca poczty akceptuje dla podanego loginu. Większość dostawców odrzuca wiadomość, gdy adres nadawcy nie zgadza się z kontem, więc uwierzytelnienie przechodzi, a wysyłka i tak się nie udaje.
Sprawdzenie jest wbudowane. Na stronie /admin, w sekcji ustawień SMTP, jest pole „Enter test email” i przycisk „Send test email”. Wpisz swój adres i wyślij. Wiadomość powinna dojść w kilkanaście sekund. Gdy nie dochodzi, ustaw tymczasowo SMTP_DEBUG: "true", zrestartuj kontener i powtórz próbę: w logu pojawi się wtedy pełna rozmowa z serwerem poczty, razem z odpowiedzią, która kończy sprawę. Po skończonej diagnostyce wyłącz tę opcję, bo log robi się bardzo obszerny.
Jedna pułapka kolejności. Ustawienia zapisane przez formularz na /admin trafiają do pliku data/config.json i mają pierwszeństwo przed zmiennymi środowiskowymi. Jeśli raz zapiszesz SMTP przez panel, a potem poprawisz hasło w docker-compose.yml, serwer dalej będzie używał starej wartości z config.json. Wybierz jedno miejsce konfiguracji i trzymaj się go.
Aplikacja TOTP i kod e-mailem: dwie metody bez sprzętu
TOTP to metoda domyślna i najmniej kłopotliwa. Użytkownik skanuje kod QR aplikacją w telefonie i przepisuje sześć cyfr. Po stronie serwera nie trzeba ustawiać niczego. Warunkiem poprawnego działania jest zgodny czas: TOTP liczy kody z zegara, więc serwer z zegarem rozjechanym o minutę zacznie odrzucać poprawne kody. Na VPS-ie pilnuje tego zwykle systemd-timesyncd albo chrony, i warto to sprawdzić przed włączeniem 2FA dla wszystkich.
Metoda e-mail wysyła jednorazowy kod na adres konta. Jej zachowanie regulują cztery zmienne: EMAIL_TOKEN_SIZE (domyślnie 6 cyfr), EMAIL_EXPIRATION_TIME (600 sekund), EMAIL_ATTEMPTS_LIMIT (3 próby) oraz EMAIL_2FA_AUTO_FALLBACK. Ostatnia z nich, ustawiona na true, sprawia że kod e-mailem wysyła się automatycznie, gdy użytkownik nie ma żadnej innej metody. Wydłużanie EMAIL_EXPIRATION_TIME kuszące bywa przy wolnej poczcie, ale każda dodatkowa minuta to dłuższe okno, w którym kod z przechwyconej skrzynki wciąż działa.
E-mail jako jedyny drugi składnik ma słabość, którą trzeba nazwać wprost: kto ma dostęp do skrzynki, ten ma drugi składnik. Jeśli skrzynka jest chroniona tym samym hasłem, co sejf, to nie dołożyłeś warstwy, tylko ją narysowałeś. Dla konta administratora wybierz klucz sprzętowy albo TOTP.
Klucz FIDO2 WebAuthn, czyli klucz sprzętowy
FIDO2 WebAuthn to metoda z fizycznym kluczem USB lub NFC, obsługiwana także przez Nitrokey i SoloKey. Z punktu widzenia odporności na phishing jest najlepsza z całej piątki, bo klucz podpisuje wyłącznie dla domeny, dla której został zarejestrowany. Fałszywa strona podszywająca się pod Twój sejf nie dostanie poprawnego podpisu, nawet gdy użytkownik da się nabrać.
Po stronie serwera wymagana jest dokładnie jedna rzecz: poprawnie ustawiona zmienna DOMAIN, z prefiksem https:// i z portem na końcu, gdy nie używasz 443.
DOMAIN=https://sejf.example.plWitryna musi być podawana po HTTPS z ważnym certyfikatem, bo przeglądarki udostępniają API WebAuthn tylko w bezpiecznym kontekście. Adres w pasku przeglądarki musi zgadzać się z wartością DOMAIN co do znaku. Wpisana w DOMAIN domena staje się identyfikatorem, do którego klucz przywiązuje poświadczenie, więc późniejsza zmiana adresu sejfu unieważnia wszystkie zarejestrowane klucze. Przenosisz instancję na nową domenę? Zaplanuj ponowną rejestrację kluczy, zanim wyłączysz starą, albo trzymaj kody odzyskiwania pod ręką.
Zarejestruj dwa klucze na konto: jeden noszony przy kluczach do domu, drugi zamknięty w szufladzie. Klucz sprzętowy można zgubić, a konto z jednym kluczem i bez kodu odzyskiwania to konto stracone.
YubiKey OTP
YubiKey OTP to starszy mechanizm, w którym klucz po dotknięciu wpisuje długi ciąg znaków, a serwer weryfikuje go w usłudze walidacyjnej YubiCloud. Jest to metoda inna niż FIDO2, mimo że urządzenie bywa to samo.
YUBICO_CLIENT_ID=11111
YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAAPara kluczy API pochodzi ze strony https://upgrade.yubico.com/getapikey/. Jeżeli Twój YubiKey został przeprogramowany, musi być jeszcze zarejestrowany w YubiCloud pod adresem https://upload.yubico.com/, inaczej walidacja zwróci błąd mimo poprawnej konfiguracji. Opcjonalna zmienna YUBICO_SERVER wskazuje własny serwer walidacyjny. Gdy jej nie podasz, używane są domyślne serwery YubiCloud.
Z tego wynika warunek, o którym łatwo zapomnieć: Twój VPS musi mieć wyjście na świat po HTTPS, żeby sprawdzić kod. Serwer odcięty regułą wychodzącą zapory odrzuci poprawny YubiKey, bo nie ma jak zapytać o jego ważność. Oznacza to też, że YubiCloud jest w tej metodzie stroną trzecią, podczas gdy FIDO2 weryfikujesz całkowicie u siebie.
Duo
Duo to zewnętrzna usługa z powiadomieniem push na telefon, sensowna głównie tam, gdzie firma już jej używa. W panelu Duo tworzysz aplikację i przenosisz z niej trzy wartości.
DUO_IKEY=<Client ID>
DUO_SKEY=<Client Secret>
DUO_HOST=<API Hostname>Vaultwarden domyślnie korzysta z nowego okna logowania Duo. Zmienna DUO_USE_IFRAME ustawiona na true przywraca stary tryb „Traditional Prompt” oparty na iframe, który jest oznaczony jako przestarzały. Nie włączaj go w nowej instalacji. Podobnie jak przy YubiKey OTP, uwierzytelnienie wymaga łączności serwera z usługą zewnętrzną, więc awaria po stronie Duo oznacza brak logowania u Ciebie.
Czy warto: to są metody, za które w Bitwardenie się płaci
Dla osoby, która porównywała cenniki, obraz jest prosty. W hostowanym Bitwardenie TOTP i kod e-mailem są w planie darmowym, natomiast klucze sprzętowe, YubiKey OTP i Duo należą do planu Premium, kosztującego (stan na wrzesień 2026) 10 USD rocznie za użytkownika. Twój własny serwer daje wszystkie te metody bez osobnej opłaty, dla każdego konta w instancji.
Rachunek nie jest jednak zerowy, tylko przesunięty. Płacisz czasem: za SMTP, za aktualizacje obrazu, za kopie zapasowe i za bycie własną pomocą techniczną o drugiej w nocy. Jeśli ważysz te dwie strony, porównanie obu podejść rozwija zestawienie Vaultwardena z oficjalnym serwerem Bitwarden, a samą instalację od zera opisuje przewodnik po uruchomieniu menedżera haseł na własnym VPS-ie. Dla jednej osoby i dla rodziny rachunek zwykle wychodzi na korzyść własnego serwera. Dla firmy bez dyżuru administratora, zwykle nie.
Strona /admin to osobne drzwi, bez drugiego składnika
To najważniejszy fragment tego tekstu. Strona /admin nie korzysta z kont użytkowników i nie ma żadnego drugiego składnika. Chroni ją wyłącznie wartość ADMIN_TOKEN. Kto ją pozna, ten zobaczy listę kont, wyłączy 2FA każdemu i zmieni konfigurację serwera.
Dokumentacja projektu zaleca, żeby nie trzymać tam zwykłego hasła, tylko skrót w formacie PHC wygenerowany algorytmem Argon2id. Vaultwarden ma do tego wbudowane polecenie.
docker run --rm -it vaultwarden/server /vaultwarden hashPolecenie zapyta o hasło i wypisze ciąg zaczynający się od $argon2id$v=19$m=65540,t=3,p=4$. Ten ciąg wstawiasz jako ADMIN_TOKEN, a przy logowaniu na /admin wpisujesz hasło, nie skrót.
Tu czeka pułapka, na której potyka się wiele osób. Znak $ ma znaczenie dla Docker Compose. W pliku .env wpisz skrót w apostrofach i nie zmieniaj niczego. W docker-compose.yml musisz podwoić każde wystąpienie $ na $$, inaczej Compose podstawi puste zmienne i token nigdy nie zadziała, a komunikat o błędzie będzie mówił tylko o nieprawidłowym haśle.
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$...'Warto dołożyć trzy ograniczenia. ADMIN_RATELIMIT_SECONDS i ADMIN_RATELIMIT_MAX_BURST spowalniają zgadywanie tokenu, a ADMIN_SESSION_LIFETIME (domyślnie 20 minut) skraca czas życia zalogowanej sesji panelu. Zmienna DISABLE_ADMIN_TOKEN ustawiona na true otwiera panel każdemu, kto zna adres, więc ma sens wyłącznie wtedy, gdy przed Vaultwardenem stoi inny mechanizm uwierzytelnienia. Jeśli panel nie jest Ci potrzebny na co dzień, najlepszą ochroną jest jego brak: usuń ADMIN_TOKEN, nie ustawiaj DISABLE_ADMIN_TOKEN i upewnij się, że w data/config.json nie ma klucza admin_token. Alternatywnie zostaw panel wyłącznie w sieci prywatnej, na przykład wystawiając sejf przez tunel Cloudflare bez otwierania portów na VPS-ie i blokując tam ścieżkę /admin.
Ustawienia, które warto zmienić przy okazji
SIGNUPS_ALLOWED=falsezamyka rejestrację, żeby ktoś obcy nie założył konta na Twoim serwerze. Nowych użytkowników dodajesz wtedy zaproszeniem.DISABLE_2FA_REMEMBER=truewyłącza opcję „zapamiętaj to urządzenie”, przez którą drugi składnik znika na kolejne 30 dni.INCOMPLETE_2FA_TIME_LIMIT=3wysyła powiadomienie e-mail, gdy ktoś poda poprawne hasło główne, ale nie dokończy drugiego kroku. To najwcześniejszy sygnał, że Twoje hasło główne wyciekło. Ta opcja działa tylko przy skonfigurowanym SMTP, co jest kolejnym argumentem, żeby zająć się pocztą najpierw.EMAIL_2FA_ENFORCE_ON_VERIFIED_INVITE=truewymusza drugi składnik na kontach tworzonych z zaproszenia, więc nowy użytkownik nie zostaje przy samym haśle.
Czego logowanie dwuetapowe nie chroni
Drugi składnik chroni logowanie, czyli moment, w którym ktoś rozmawia z Twoim serwerem. Nie chroni kopii katalogu data, którą ktoś wyniósł z serwera albo z Twojego backupu. Taka kopia nigdy nie przechodzi przez ekran logowania, więc żadna z pięciu metod jej nie dotyczy.
O bezpieczeństwie wyniesionej kopii decyduje co innego: siła hasła głównego i parametry funkcji KDF, z której wyprowadzany jest klucz szyfrujący sejf. Mechanizm szyfrowania po stronie klienta i to, co realnie widzi serwer, rozkłada na części analiza bezpieczeństwa samego Vaultwardena. Drugą połową tej samej rozmowy są kopie zapasowe, bo plik db.sqlite3 skopiowany w trakcie zapisu potrafi być nie do odtworzenia; poprawną procedurę opisuje instrukcja tworzenia i odtwarzania kopii zapasowej Vaultwardena. Włączone 2FA bez sprawdzonego odtworzenia backupu to dwa zamki w drzwiach postawionych na piasku.
Co najczęściej nie działa
Metoda „Email” nie pojawia się na liście. SMTP nie jest skonfigurowany albo konfiguracja nie została wczytana. Wyślij wiadomość testową z /admin i sprawdź log kontenera przy włączonym SMTP_DEBUG.
Klucz FIDO2 nie chce się zarejestrować. Sejf jest otwarty po HTTP, certyfikat jest nieważny, albo adres w pasku przeglądarki różni się od wartości DOMAIN. Wystarczy www z jednej strony i brak www z drugiej.
Klucze przestały działać po przeprowadzce. Zmiana DOMAIN unieważnia zarejestrowane poświadczenia WebAuthn. Zaloguj się kodem odzyskiwania i zarejestruj klucze ponownie.
Poprawne kody TOTP są odrzucane. Zegar serwera się rozjechał. Sprawdź synchronizację czasu na VPS-ie, zanim zaczniesz podejrzewać aplikację w telefonie.
Token panelu /admin nie działa mimo poprawnego hasła. Skrót Argon2 trafił do docker-compose.yml bez podwojenia znaków $.
Zmiana w docker-compose.yml nie przynosi skutku. Wartość została wcześniej zapisana przez panel i siedzi w data/config.json, który ma pierwszeństwo.
FAQ
Czy Vaultwarden pozwala zalogować się samym passkey, bez hasła głównego?
Nie w wersji 1.37.3 z 13 września 2026. README projektu wymienia FIDO2 WebAuthn wyłącznie jako drugi składnik, używany po podaniu hasła głównego. Logowanie bez hasła, znane z hostowanego Bitwardena jako „Login with passkeys”, nie jest w tym serwerze funkcją dostępną. Przed wdrożeniem sprawdź release notes swojej wersji, bo to się może zmienić.
Włączyłem 2FA i zgubiłem telefon. Jak odzyskać dostęp do sejfu?
Użyj kodu odzyskiwania zapisanego przy włączaniu metody: wyłącza on wszystkie metody 2FA na koncie i wpuszcza Cię samym hasłem głównym. Jeżeli kodu nie masz, zaloguj się na stronę /admin i kliknij „Remove all 2FA” przy swoim koncie. Gdy nie masz ani kodu, ani tokenu do panelu, pozostaje odtworzenie katalogu data z kopii zapasowej sprzed włączenia drugiego składnika.
Dlaczego metoda e-mail nie pojawia się wśród dostępnych opcji?
Vaultwarden pokazuje tę metodę dopiero wtedy, gdy ma działającą pocztę wychodzącą. Ustaw SMTP_HOST, SMTP_FROM, SMTP_SECURITY i SMTP_PORT, zrestartuj kontener, a potem wyślij wiadomość testową przyciskiem „Send test email” na stronie /admin. Dopóki test nie przechodzi, metoda pozostanie niewidoczna, i nie jest to błąd interfejsu.
Czy strona /admin ma własne logowanie dwuetapowe?
Nie ma żadnego. Panel administracyjny chroni wyłącznie ADMIN_TOKEN, dlatego wpisz tam skrót Argon2id wygenerowany poleceniem docker run --rm -it vaultwarden/server /vaultwarden hash, a nie zwykłe hasło. Ogranicz też tempo prób zmiennymi ADMIN_RATELIMIT_SECONDS i ADMIN_RATELIMIT_MAX_BURST. Jeśli panel nie jest Ci potrzebny na co dzień, usuń ADMIN_TOKEN i klucz admin_token z data/config.json, co wyłącza tę stronę całkowicie.
Która metoda 2FA jest najlepsza dla konta administratora?
Klucz FIDO2 WebAuthn, bo jako jedyny wiąże podpis z domeną i przez to odrzuca stronę podszywającą się pod Twój sejf. Zarejestruj dwa klucze, jeden noszony i jeden zapasowy. Kod e-mailem zostaw jako metodę dla mniej wrażliwych kont: kto przejmie skrzynkę pocztową, ten przejmuje także ten drugi składnik.