SSD Nodes Learn Hosting plans →
Przewodniki Matt ConnorAutor: Matt Connor

Jak zainstalować Vaultwarden na VPS z Dockerem

Instrukcja konfiguracji Vaultwarden na własnym serwerze VPS. Dowiedz się jak poprawnie wdrożyć kontener, zabezpieczyć dostęp przez HTTPS oraz wdrożyć procedurę backupu danych.

Co budujesz

Menedżer haseł, którego jesteś pełnym właścicielem: Vaultwarden działający w jednym małym kontenerze za reverse proxy, które dokonuje terminacji HTTPS, z oficjalnymi aplikacjami Bitwarden na telefonie, laptopie i w przeglądarce skierowanymi na ten serwer. Vaultwarden implementuje API serwera Bitwarden w języku Rust i obsługuje ten sam protokół co bitwarden.com, dzięki czemu oficjalni klienci współpracują z nim bez zmian, o ile serwer jest aktualny (nowe wersje klientów czasami wymagają odpowiedniej wersji Vaultwarden: 1.37.2 jest wymagane dla klientów 2026.8.0 i nowszych). Całość zajmuje około 100 MB pamięci RAM, w przeciwieństwie do oficjalnego stosu składającego się z wielu kontenerów.

Instalacja to kilkanaście linii w pliku Compose. Trzy kluczowe kwestie, które mają znaczenie i mogą powodować awarie, to: TLS musi istnieć przed pierwszym załadowaniem web vault, publiczna rejestracja musi zostać zamknięta natychmiast po utworzeniu własnego konta, a wolumen z danymi musi być archiwizowany i testowo przywracany, ponieważ ten jeden katalog przechowuje wszystkie Twoje hasła.

Wymagania wstępne i istotne pułapki

  • Serwer VPS z zainstalowanym Docker Engine oraz wtyczką Compose, działający na czystym systemie Ubuntu 24.04 KVM z dostępem root lub sudo. 512 MB pamięci RAM jest wartością wystarczającą; 1 GB zapewnia komfort pracy. Jest to jedno z najlżejszych rozwiązań, które można uruchomić, znajdujące się w czołówce listy usług wartych samodzielnego hostowania. Należy jednak dobrać parametry serwera pod kątem innych współdzielonych usług: uruchomienie własnej biblioteki zdjęć, takiej jak PhotoPrism lub Immich na tym samym VPS podnosi zapotrzebowanie na pamięć RAM do poziomu kilku gigabajtów, podczas gdy Vaultwarden zużywa jej znikome ilości. Ta sama zasada dotyczy interfejsów multimedialnych dodawanych w późniejszym czasie, ponieważ przekształcenie biblioteki Jellyfin w wirtualną wypożyczalnię kaset z lat 90. oznacza kolejny stale działający kontener oraz konieczność zapewnienia zapasu mocy na transkodowanie w ramach tego samego budżetu zasobów.
  • Domena z rekordem A (oraz AAAA, jeśli dostępny jest IPv6) wskazującym vault.example.com na adres IP serwera VPS. Certyfikat TLS jest wystawiany dla konkretnej nazwy, dlatego konfiguracja DNS musi być poprawna przed rozpoczęciem prac.
  • Porty 80 oraz 443 otwarte na świat i obsługiwane przez reverse proxy, a nigdy bezpośrednio przez Vaultwarden. Port 80 jest wykorzystywany wyłącznie do weryfikacji wyzwania ACME dla certyfikatu oraz przekierowania z HTTP na HTTPS.
  • Najważniejsza pułapka na wstępie: klienci Bitwarden odmawiają połączenia z serwerem, który nie korzysta z HTTPS. Nie istnieje możliwość "przetestowania połączenia przez HTTP", ta ścieżka nie zadziała z konkretnych powodów omówionych w dalszej części.

Dlaczego Vaultwarden, a nie oficjalny stos Bitwarden

Te same klienty, ułamek obciążenia. Standardowe, oficjalne wdrożenie Bitwarden do samodzielnego hostowania jest dostarczane jako zestaw kontenerów (MSSQL Express, Identity, Api, Admin i inne) i wymaga co najmniej 2 GB pamięci RAM. Bitwarden oferuje również wersję Bitwarden lite, pojedynczy obraz Docker wymagający co najmniej 200 MB pamięci RAM, jednak jest on przeznaczony do użytku osobistego i laboratoriów domowych, a nie do zastosowań biznesowych, pozostawiając kwestię bazy danych i jej kopii zapasowych całkowicie po stronie użytkownika. Vaultwarden to pojedynczy plik binarny, który domyślnie przechowuje wszystko w bazie danych SQLite i w stanie spoczynku zużywa kilkadziesiąt megabajtów pamięci. Dla jednej osoby, rodziny lub małego zespołu jest to oczywisty wybór, a ponieważ wiernie implementuje API Bitwarden, dane pozostają przenośne między nim a serwisem bitwarden.com.

Rezygnuje się przy tym z większości funkcji korporacyjnych: brak obsługi SCIM (choć wsparcie dla OpenID Connect SSO pojawiło się w wersji 1.35.0), a użytkownik staje się administratorem, więc aktualizacje, HTTPS i kopie zapasowe należą do jego obowiązków. Ten przewodnik obejmuje właśnie te trzy zadania.

Dlaczego HTTPS nie jest opcjonalny

Sejf internetowy Bitwarden oraz rozszerzenia przeglądarkowe wyprowadzają klucze szyfrujące w przeglądarce przy użyciu Web Crypto API (window.crypto.subtle). Przeglądarki udostępniają crypto.subtle wyłącznie w bezpiecznym kontekście, czyli HTTPS lub w szczególnych przypadkach adresów pętli zwrotnej, takich jak http://localhost oraz http://127.0.0.1. Przy użyciu zwykłego http://vault.example.com jest to undefined, więc w momencie wyprowadzenia klucza przez aplikację występuje błąd, a w konsoli pojawia się:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')

Strona zawiesza się lub wyświetla ogólny błąd kryptograficzny i logowanie nie dochodzi do skutku. Klienci desktopowi, mobilni oraz przeglądarkowi przeprowadzają własną weryfikację adresu URL hostowanego samodzielnie i w przypadku punktu końcowego http (lub nieosiągalnego) odmawiają działania z komunikatem:

This is not a recognized Bitwarden server. You may need to check with your provider or update your server.

Oba przypadki mają tę samą przyczynę: brak poprawnego HTTPS. Dlatego najpierw konfigurujemy TLS i nigdy nie otwieramy sejfu przez http, nawet jednorazowo w celu szybkiego sprawdzenia.

Krok 1, DNS i reverse proxy (najpierw TLS)

Skieruj rekord na swój VPS i potwierdź, że rozwiązuje się on do właściwego adresu:

dig +short vault.example.com

Wyświetlona linia musi zawierać adres IP Twojego VPS. Jeśli jest pusta lub błędna, popraw konfigurację DNS i odczekaj czas TTL; wystawianie certyfikatu nie powiedzie się dla nazwy, która nie jest poprawnie rozwiązywana.

Dla frontendu HTTPS w tym przewodniku wykorzystano Traefik, który automatycznie wystawia i odnawia certyfikaty Let's Encrypt oraz integruje się bezpośrednio z Compose. Jeśli jeszcze go nie używasz, wykonaj najpierw konfigurację Traefik jako reverse proxy z automatycznym TLS; tworzy ona zewnętrzną sieć Docker (proxy poniżej) oraz resolver ACME (letsencrypt), do których podłącza się usługa Vaultwarden. Zwykły nginx z ręcznie wystawionym certyfikatem działa z perspektywy Vaultwarden identycznie.

Wolisz nginx i Certbot zamiast Traefik? Umieść Vaultwarden na 127.0.0.1:8080 (dodaj ports: ["127.0.0.1:8080:80"] do usługi i usuń etykiety Traefik), a następnie wystaw certyfikat i skonfiguruj proxy. Część dotycząca certyfikatów została opisana w wystawianiu certyfikatów Let's Encrypt za pomocą Certbot i nginx. Kluczowym dodatkiem jest obsługa WebSocket dla ścieżki powiadomień:

server {
    listen 443 ssl;
    server_name vault.example.com;

    client_max_body_size 525M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Zwróć uwagę na linię X-Real-IP; pozwala ona Fail2ban na późniejszą identyfikację rzeczywistego atakującego zamiast 127.0.0.1. Cała reszta tego przewodnika jest identyczna, niezależnie od tego, czy przed usługą znajduje się Traefik, czy nginx.

Krok 2, plik Compose

Najpierw utwórz katalog projektu. Niniejszy przewodnik wykorzystuje /opt/vaultwarden, co sprawia, że nazwa projektu Compose, a tym samym wolumen danych vaultwarden_vw-data, są przewidywalne; kroki dotyczące Fail2ban oraz kopii zapasowych opisane poniżej zależą od tej konkretnej nazwy.

sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwarden

Utwórz plik .env dla sekretu administratora oraz plik Compose w tym katalogu.

# .env
ADMIN_TOKEN=paste-a-strong-token-here

Wygeneruj ten token za pomocą openssl rand -base64 48 i wklej go. (Silniejsza forma haszowana zostanie omówiona w dalszej części; długi, losowy ciąg znaków jest wystarczający na początek).

# docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "true"          # closed in Step 4, keep true just to register
      ADMIN_TOKEN: "${ADMIN_TOKEN}"
      IP_HEADER: "X-Forwarded-For"     # X-Real-IP if your proxy sends that instead
      LOG_FILE: "/data/vaultwarden.log"
      LOG_LEVEL: "warn"
    volumes:
      - vw-data:/data
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.vw.rule=Host(`vault.example.com`)"
      - "traefik.http.routers.vw.entrypoints=websecure"
      - "traefik.http.routers.vw.tls.certresolver=letsencrypt"
      - "traefik.http.services.vw.loadbalancer.server.port=80"

volumes:
  vw-data:

networks:
  proxy:
    external: true

Dwie kwestie w tym pliku stanowią o całym projekcie. Brak mapowania ports: oznacza, że Vaultwarden jest dostępny wyłącznie przez Traefik i jego TLS; publikowanie portu na hoście jest przyczyną, dla której użytkownicy przypadkowo udostępniają vault przez http. Z kolei DOMAIN musi być pełnym publicznym adresem URL HTTPS: jest on wpisany w linki do załączników, WebAuthn 2FA oraz punkt końcowy powiadomień, więc błędna lub nieprawidłowa wartość http powoduje ich niedziałanie, nawet jeśli strona się ładuje. Znacznik latest jest celowym wyjątkiem od standardowej zasady unikania latest; Vaultwarden wydaje swoje stabilne wersje jako pojedynczy, ciągły obraz, przy czym :testing stanowi oddzielny kanał wersji przedpremierowych, dlatego aktualizuj celowo i przejrzyj informacje o wydaniu przed pobraniem obrazu. Ten wyjątek jest jednak wąski: większość długo działających kontenerów lepiej przypiąć do konkretnego znacznika, co zapewnia przewidywalność agenta działającego stale na tym samym VPS po restartach i pobraniach obrazów.

Uruchom usługę i monitoruj dziennik:

docker compose up -d
docker compose logs -f vaultwarden

Poprawny start kończy się linią taką jak Rocket has launched from http://0.0.0.0:80. Odczekaj kilka sekund, aż Traefik pobierze certyfikat, a następnie załaduj https://vault.example.com; powinieneś zobaczyć web vault Bitwarden z poprawną ikoną kłódki i bez ostrzeżeń o certyfikacie.

Krok 3, silny ADMIN_TOKEN i pułapka $$

ADMIN_TOKEN zabezpiecza /admin, panel umożliwiający odczyt wszystkich użytkowników i ustawień instancji, dlatego należy go traktować jak hasło root. Dostępne są dwie metody konfiguracji.

Prostsza metoda polega na użyciu losowego ciągu znaków wygenerowanego wcześniej za pomocą openssl rand -base64 48. Ponieważ base64 nigdy nie zawiera znaku $, można go bezpośrednio wkleić do .env bez konieczności stosowania znaków ucieczki.

Metoda wzmocniona wykorzystuje skrót Argon2 PHC, dzięki czemu token w postaci jawnej nigdy nie jest zapisywany na dysku. Skrót należy wygenerować przy użyciu tego samego obrazu:

docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp

Narzędzie poprosi o dwukrotne wprowadzenie hasła i wyświetli ciąg znaków rozpoczynający się od $argon2id$v=19$.... Oto pułapka, która często kosztuje użytkowników godzinę pracy: Docker Compose traktuje $ jako interpolację zmiennych, więc w przypadku wklejenia skrótu bezpośrednio pod environment: w pliku Compose, należy podwoić każdy znak $ na $$. Ujęcie wartości w cudzysłów jest dopuszczalne; kluczowe znaczenie ma zastosowanie znaków ucieczki:

    environment:
      ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$c29tZXNhbHQ$$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

Jeśli wolisz przechowywać skrót w .env, zasada ulega zmianie: pozostaw pojedyncze znaki $, obejmij całą wartość pojedynczymi cudzysłowami (ADMIN_TOKEN='$argon2id$v=19$...'), a istniejąca linia ${ADMIN_TOKEN} w pliku Compose odczyta tę wartość. Nigdy nie podwajaj znaku $ w .env. Jeśli pozostawisz pojedyncze znaki $ bezpośrednio w pliku Compose, narzędzie wyświetli ostrzeżenie The "argon2id" variable is not set i wyczyści token, przez co /admin odrzuci poprawne hasło. Uruchom docker compose up -d i przechowuj tekst jawny wprowadzony w wierszu poleceń we własnym menedżerze haseł.

Krok 4, rejestracja konta i zabezpieczenie dostępu

Używając SIGNUPS_ALLOWED: "true", otwórz https://vault.example.com, kliknij Create account i zarejestruj się, podając adres e-mail oraz silne hasło główne. Tego hasła nie da się odzyskać, nie istnieje procedura jego resetowania, dlatego w pierwszej kolejności zapisz je w trwałym miejscu.

Teraz zamknij dostęp. Edytuj plik Compose, aby wyłączyć rejestrację:

      SIGNUPS_ALLOWED: "false"

Zastosuj zmiany za pomocą docker compose up -d. To nie jest zabezpieczenie, które można odłożyć w czasie. Pozostawienie otwartej rejestracji sprawia, że każdy, kto znajdzie adres URL – a roboty indeksujące z pewnością go znajdą – może utworzyć konto na Twoim serwerze. Osoby te nie uzyskają dostępu do Twojego sejfu, ale zużyją zasoby i przekształcą Twoją prywatną instancję w otwartą usługę. Sygnałem, że rejestracja pozostała włączona, jest /admin, gdzie pojawią się konta, których nie utworzyłeś.

Aby dodać członków rodziny lub współpracowników w późniejszym czasie bez ponownego otwierania publicznej rejestracji, użyj przycisku Invite User w /admin. Ta ścieżka wymaga skonfigurowanego SMTP, aby zaproszona osoba otrzymała swój link.

Krok 5, uzyskiwanie dostępu do /admin

Przejdź pod adres https://vault.example.com/admin i wprowadź tekstowy token administratora (losowy ciąg znaków lub hasło, które zostało zahaszowane – nie sam skrót). Wewnątrz panelu można wyświetlić listę użytkowników, dostosować ustawienia, wysłać testową wiadomość e-mail oraz wykonać kopię zapasową bazy danych.

Jeśli strona wyświetla komunikat The admin panel is disabled, please configure the 'ADMIN_TOKEN' variable to enable it, oznacza to, że ADMIN_TOKEN jest puste lub nieustawione, co całkowicie wyłącza panel (jest to poprawne rozwiązanie, jeśli panel nie jest potrzebny). Jeśli strona się ładuje, ale odrzuca token, sprawdź pułapkę związaną z ucieczką znaków $$ w poniższej liście błędów. Zapomniano tokena? Nie ma procedury odzyskiwania; należy edytować .env lub plik Compose, ustawić nowy token i wykonać docker compose up -d.

Krok 6, połączenie klientów Bitwarden

Każdy oficjalny klient może łączyć się z własnym serwerem, dlatego należy zainstalować wersję desktopową, mobilną lub rozszerzenie przeglądarkowe Bitwarden z oficjalnych sklepów. Nie jest wymagana specjalna kompilacja Vaultwarden.

Przed zalogowaniem należy otworzyć ustawienia (ikona koła zębatego) na ekranie logowania (oznaczone jako Self-hosted lub Region → Self-hosted), ustawić Server URL na https://vault.example.com i zapisać zmiany. Następnie należy zalogować się przy użyciu adresu e-mail oraz hasła głównego użytego podczas rejestracji. Klient powinien nawiązać połączenie i zaoferować funkcje autouzupełniania oraz zapisywania danych uwierzytelniających.

Jeśli klient wyświetla błąd This is not a recognized Bitwarden server. You may need to check with your provider or update your server., oznacza to, że adres URL jest błędny, używa protokołu http lub certyfikat jest niezaufany. Należy najpierw sprawdzić w przeglądarce, czy adres https://vault.example.com ładuje się poprawnie. Opóźnienia w synchronizacji na innych urządzeniach wynikają z działania mechanizmu WebSocket push, który opisano poniżej.

Krok 7, jail Fail2ban dla punktu końcowego logowania

Vaultwarden zapisuje każdą nieudaną próbę logowania do pliku określonego przez LOG_FILE, co stanowi idealne źródło danych dla mechanizmu ochrony przed atakami typu brute-force. Jeśli Fail2ban nie jest jeszcze uruchomiony, instrukcje instalacji i podstawowej konfiguracji znajdują się w przewodniku zabezpieczania SSH za pomocą Fail2ban; poniżej dodajemy jail dla Vaultwarden.

Najpierw należy ustalić lokalizację wolumenu nazwanego na hoście, aby Fail2ban mógł odczytać dziennik:

docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}'

Polecenie to wyświetli ścieżkę podobną do /var/lib/docker/volumes/vaultwarden_vw-data/_data; plik dziennika znajduje się wewnątrz pod adresem vaultwarden.log. Należy utworzyć filtr:

# /etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =

Oraz jail:

# /etc/fail2ban/jail.d/vaultwarden.local
[vaultwarden]
enabled   = true
filter    = vaultwarden
logpath   = /var/lib/docker/volumes/vaultwarden_vw-data/_data/vaultwarden.log
banaction = iptables-allports
chain     = DOCKER-USER
maxretry  = 5
findtime  = 600
bantime   = 3600

Przeładuj konfigurację za pomocą sudo systemctl restart fail2ban i sprawdź status za pomocą sudo fail2ban-client status vaultwarden.

Skuteczność tej ochrony zależy od trzech szczegółów konfiguracji Docker. Po pierwsze, jeśli w dzienniku przy każdej nieudanej próbie widnieje IP: 127.0.0.1 lub adres IP proxy, oznacza to, że Vaultwarden blokuje proxy. Należy ustawić IP_HEADER na nagłówek faktycznie przesyłany przez proxy (X-Forwarded-For dla Traefik, X-Real-IP dla powyższego bloku nginx, CF-Connecting-IP w przypadku korzystania z Cloudflare). Od wersji 1.37.4, dzięki X-Forwarded-For, Vaultwarden przyjmuje najbardziej wysunięty w prawo adres, który nie znajduje się w IP_HEADER_TRUSTED_PROXIES (wartość domyślna local obejmuje proxy na tym samym hoście lub w tej samej sieci Docker). Jeśli przed proxy znajduje się CDN, jego adresy również należy tam uwzględnić. Po drugie, wybór odpowiedniego łańcucha iptables zależy od używanego proxy: jeśli Traefik działa jako kontener z opublikowanymi portami, ruch przechodzi przez ścieżkę FORWARD w Dockerze, więc blokada musi znajdować się w DOCKER-USER, jak pokazano powyżej. Jeśli jednak wybrano opcję host-nginx z Kroku 1, połączenia kończą się na łańcuchu INPUT hosta, a blokada DOCKER-USER ich nie wykryje; w takim przypadku należy usunąć linię chain = DOCKER-USER, aby Fail2ban używał domyślnego łańcucha INPUT. Po trzecie, należy użyć banaction = iptables-allports zamiast domyślnej konfiguracji opartej na portach. Ten jail nie definiuje portu, a blokada wszystkich portów w DOCKER-USER skutecznie odcina sprawcę od każdej usługi opublikowanej na serwerze.

Krok 8, wykonanie kopii zapasowej skarbca, a następnie jego przywrócenie

Wolumen vw-data jest Twoim menedżerem haseł. Przechowuje on db.sqlite3 (każdy wpis), katalogi attachments/ i sends/, pliki rsa_key.* podpisujące sesje logowania oraz config.json z panelu administratora. Kopia zapasowa, która pomija którykolwiek z tych elementów, zawiedzie w momencie, gdy będzie potrzebna.

Kopiowanie db.sqlite3 w czasie, gdy Vaultwarden zapisuje dane, może spowodować przechwycenie niekompletnego, uszkodzonego pliku. Wykonaj zatem migawkę "na zimno" (cold snapshot); przerwa w działaniu potrwa zaledwie kilka sekund:

#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F)
DEST=/root/vw-backups
VOL=$(docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}')
mkdir -p "$DEST"
docker compose -f /opt/vaultwarden/docker-compose.yml stop vaultwarden
tar czf "$DEST/vw-$STAMP.tgz" -C "$VOL" .
docker compose -f /opt/vaultwarden/docker-compose.yml start vaultwarden

Uruchamiaj to zadanie przez cron każdej nocy i kopiuj .tgz poza serwer. Kopia zapasowa znajdująca się wyłącznie na serwerze, który zabezpieczasz, nie jest kopią zapasową. Poprawnym sposobem przesyłania danych jest nocna kopia zapasowa restic na inny serwer lub pamięć obiektową, co szyfruje archiwum i deduplikuje powtarzające się migawki. Przycisk Backup Database w panelu administratora to wygodna migawka "na gorąco" samego pliku SQLite, ale pomija ona załączniki i klucze.

Teraz rytuał, który odróżnia realną kopię zapasową od życzeniowej: przywróć ją raz i udowodnij, że działa:

mkdir -p /tmp/vw-restore
tar xzf /root/vw-backups/vw-2026-07-15.tgz -C /tmp/vw-restore
docker run --rm -p 127.0.0.1:8888:80 -v /tmp/vw-restore:/data vaultwarden/server

Z poziomu laptopa utwórz tunel za pomocą ssh -L 8888:127.0.0.1:8888 you@your-vps i otwórz http://localhost:8888 (lub http://127.0.0.1:8888). Ponieważ adresy pętli zwrotnej (loopback) są traktowane jako bezpieczny kontekst, crypto.subtle jest dostępny, a skarbiec odszyfrowuje się tutaj przez zwykły protokół http – jest to jedyny rodzaj adresu, gdzie jest to dozwolone. Zaloguj się głównym hasłem i potwierdź obecność wpisów: jeśli są widoczne, oznacza to, że baza danych, klucze RSA i główne hasło działają poprawnie, a Ty możesz odtworzyć usługę na nowym serwerze VPS w kilka minut. Zatrzymaj kontener za pomocą Ctrl-C i usuń /tmp/vw-restore. Utrzymuj nawyk korzystania z tuneli dla każdego innego interfejsu administracyjnego na serwerze, który nigdy nie powinien być wystawiony na działanie Internetu. W ten sam sposób uzyskasz dostęp do samodzielnie hostowanego skanera bezpieczeństwa open-kritt na porcie 5173.

Tryby awarii i towarzyszące im komunikaty

Cannot read properties of undefined (reading 'importKey') w konsoli przeglądarki. Skarbiec został załadowany przez http, więc crypto.subtle jest niezdefiniowane; należy łączyć się wyłącznie przez https:// i dodać przekierowanie HTTP na HTTPS na poziomie proxy.

This is not a recognized Bitwarden server... w kliencie. Adres Server URL jest ustawiony na http, zawiera literówkę lub certyfikat jest niezaufany; należy upewnić się, że https://vault.example.com wyświetla poprawną ikonę kłódki, a następnie wprowadzić go ponownie w ustawieniach klienta dla instancji self-hosted.

/admin odrzuca poprawne hasło. Skrót Argon2 utracił znaki ucieczki; każdy $ musi być zapisany jako $$ w pliku Compose (chyba że znajduje się wewnątrz pojedynczego cudzysłowu w .env, gdzie wystarczy pojedynczy $) lub wprowadzono skrót zamiast tekstu jawnego, który on reprezentuje.

Powolna synchronizacja między urządzeniami; konsola pokazuje WebSocket connection to 'wss://vault.example.com/notifications/hub' failed. Proxy nie przekazuje nagłówków Upgrade/Connection; Traefik wykonuje to automatycznie, natomiast nginx wymaga dodania dwóch linii upgrade z kroku 1. Skarbiec nadal działa, ale synchronizacja odbywa się tylko przy otwarciu aplikacji. Stary dedykowany port 3012 został usunięty w wersji v1.31.0, więc osobna ścieżka WebSocket nie jest wymagana.

Fail2ban zgłasza blokadę, ale atakujący nadal się łączy. Blokowany jest 127.0.0.1 z powodu błędnej konfiguracji IP_HEADER lub blokada znajduje się w niewłaściwym łańcuchu iptables; należy ustawić chain = DOCKER-USER oraz banaction = iptables-allports.

Aktualizacje

Pobierz nowy obraz i odtwórz kontener; nazwany wolumen oraz wszystkie dane zostaną zachowane:

docker compose pull
docker compose up -d

Vaultwarden często publikuje nowe wersje. Monitoruj informacje o wydaniach projektu zamiast blokować wersję poprawki, ponieważ niektóre wydania zawierają instrukcje dotyczące migracji. Przed każdą dużą aktualizacją wykonaj kopię zapasową; powrót do poprzedniej wersji jest możliwy poprzez przywrócenie archiwum tar do nowego wolumenu.

FAQ

Czy Vaultwarden to to samo co Bitwarden?

Jest to kompatybilny, niezależny serwer, a nie oficjalne rozwiązanie. Vaultwarden implementuje API serwera Bitwarden w języku Rust, dzięki czemu oficjalne klienty desktopowe, mobilne, przeglądarkowe oraz CLI działają z nim poprawnie, zużywając ułamek zasobów wymaganych przez oficjalny stos technologiczny. Format skarbca jest identyczny, więc migracja w obu kierunkach jest możliwa poprzez eksport i import danych.

Czy naprawdę potrzebuję HTTPS, czy mogę uruchomić usługę przez http w sieci lokalnej?

HTTPS jest wymagany w każdym przypadku poza testami na interfejsie zwrotnym (loopback). Webowy skarbiec Bitwarden oraz rozszerzenia korzystają z przeglądarkowego API Web Crypto, które jest dostępne wyłącznie w bezpiecznym kontekście. W przypadku zwykłego http klient zgłasza błąd Cannot read properties of undefined i nie loguje się. Jedynymi adresami http, które działają, są adresy typu loopback, takie jak http://localhost lub http://127.0.0.1, dlatego test przywracania w kroku 8 wykorzystuje tunel SSH.

Jak zablokować rejestrację niepowołanym osobom na moim serwerze?

Ustaw SIGNUPS_ALLOWED: "false" w pliku Compose i wykonaj docker compose up -d natychmiast po utworzeniu własnego konta. Od tego momentu dodawaj nowych użytkowników za pomocą przycisku Invite User w /admin, co wymaga skonfigurowanego SMTP, aby użytkownicy otrzymali link z zaproszeniem. Okresowo sprawdzaj listę administratorów, aby upewnić się, że nie pojawiły się nieoczekiwane konta.

Jak wykonać kopię zapasową skarbca Vaultwarden?

Zatrzymaj kontener na czas tworzenia kopii i zarchiwizuj cały wolumen vw-data, pliki db.sqlite3, attachments/, sends/, config.json oraz rsa_key.*, a następnie skopiuj archiwum poza serwer, najlepiej w ramach nocnego zadania cron. Kopiowanie działającego pliku SQLite grozi uszkodzeniem migawki, dlatego należy to robić przy wyłączonej usłudze. Co najważniejsze, przywróć kopię raz do tymczasowego kontenera i zaloguj się, aby mieć pewność, że kopia jest poprawna, zanim zaczniesz na niej polegać.

Czy samodzielne hostowanie haseł jest bezpieczne?

Tak, pod warunkiem wykonania trzech czynności opisanych w tym przewodniku: wdrożenia poprawnego HTTPS, wyłączenia otwartej rejestracji wraz z silnym tokenem administratora oraz przetestowania kopii zapasowych. Skarbiec jest szyfrowany po stronie klienta za pomocą hasła głównego, więc nawet serwer nie widzi haseł w postaci jawnej, a kradzież pliku db.sqlite3 nie pozwala na odczytanie wpisów bez tego hasła. Serwer przechowuje jednak adresy e-mail kont oraz posolone hasze wywiedzione z haseł głównych, które atakujący może próbować łamać offline, dlatego należy chronić plik bazy danych oraz każdą jego kopię. Ceną za to rozwiązanie jest przejęcie odpowiedzialności za aktualizacje i kopie zapasowe, dlatego Fail2ban oraz procedura przywracania danych nie są opcjonalne. Gdy te elementy są gotowe, szczegółowa analiza potencjalnych wektorów ataku na własny skarbiec stanowi użyteczny kolejny krok, ponieważ przy wpisach szyfrowanych po stronie klienta, głównymi punktami wymagającymi ochrony pozostają token administratora oraz archiwum kopii zapasowej.