SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor

Apakah Vaultwarden Aman? Panduan Hardening

Vaultwarden mengenkripsi setiap item vault di klien, bukan server. Risiko utama ada pada admin token yang lemah dan file backup yang mudah diakses.

Apakah Vaultwarden aman? Jawaban singkat

Vaultwarden aman pada bagian yang paling penting, karena setiap item vault dienkripsi pada perangkat Anda sebelum dikirim ke server. Server hanya menyimpan blob yang tidak dapat dibacanya. Seseorang yang menyalin seluruh database tetap memerlukan master password untuk mendapatkan informasi yang berguna darinya.

Jawaban tersebut mencakup banyak hal, dan bagian yang dapat bermasalah adalah bagian yang Anda konfigurasi. Panel admin yang dilindungi token yang mudah ditebak. Port container yang dipublikasikan ke seluruh Internet. config.json dalam plaintext. File tar backup yang diletakkan di home directory pada server yang sama. Tidak satu pun dari hal tersebut merupakan masalah kriptografi. Semuanya menjadi alasan vault self-hosted dapat dikosongkan isinya.

Semua bagian di bawah ini mengasumsikan instalasi sudah berfungsi. Jika Anda belum memilikinya, siapkan terlebih dahulu menggunakan panduan instalasi Vaultwarden untuk VPS, lalu kembali dan ikuti daftar ini dari atas ke bawah secara berurutan.

Data yang sebenarnya disimpan server

Vaultwarden menerapkan model data Bitwarden. Nama item vault, nama pengguna, kata sandi, catatan, dan URI dienkripsi dengan kunci yang diturunkan dari master password Anda, di client, sebelum permintaan apa pun dikirim. Isi file lampiran dienkripsi dengan cara yang sama. Server menerima data buram yang dilengkapi UUID (universally unique identifier).

Beberapa data bukan ciphertext. Anda harus mengetahui dengan tepat data tersebut:

  • Alamat email akun Anda, dalam bentuk plaintext.
  • Pengaturan KDF (key derivation function) dan salt Anda, karena client memerlukannya untuk membangun ulang kunci saat login berikutnya.
  • Hash di sisi server dari hash master password yang dikirim client, yang digunakan untuk mengautentikasi proses login itu sendiri.
  • Metadata: keanggotaan organisasi, nama perangkat, dan waktu login terakhir.
  • Secret untuk metode two-factor yang melindungi login Vaultwarden. Secret ini disimpan tanpa enkripsi di tabel twofactor, karena server harus menghitung kode yang diharapkan untuk dibandingkan dengan kode Anda. Ini berbeda dari secret TOTP (time-based one-time password) yang Anda simpan di dalam item vault dan dienkripsi seperti field lainnya.

Folder data berukuran kecil. Pada instalasi Docker, folder tersebut adalah lokasi yang Anda mount pada /data.

sudo ls -l /vw-data/

db.sqlite3 menyimpan hampir seluruh state. attachments/ menyimpan file yang diunggah, satu file untuk setiap UUID, dan merupakan satu-satunya kelas data penting yang tidak disimpan dalam tabel database. sends/ menyimpan lampiran Send dan memang ditujukan untuk penggunaan sementara. icon_cache/ dapat dihapus tanpa dampak penting. rsa_key.pem dan file pendampingnya menandatangani JWT (JSON web tokens) pengguna yang sedang login, sehingga salinan private key tersebut dapat digunakan untuk memalsukan session login vault. config.json hanya ada setelah Anda mengaktifkan halaman admin. Proyek ini menjelaskannya secara tegas: file tersebut menyimpan token admin dan kredensial SMTP Anda dalam plaintext.

Jadi, model ancaman praktisnya adalah akses ke filesystem, bukan kriptografi jaringan. Akses baca ke satu direktori tersebut memberikan alamat email setiap pengguna, secret 2FA login mereka, kunci untuk memalsukan session, dan salinan offline setiap vault yang dapat diserang tanpa batas waktu. Setiap langkah di bawah ini bertujuan mencegah orang lain mengakses direktori tersebut.

Perbaiki token admin terlebih dahulu

/admin adalah panel kontrol lengkap: daftar pengguna, undangan, penghapusan, dan setiap pengaturan runtime. Panel ini hanya dilindungi oleh satu rahasia bersama. Tidak ada nama pengguna. Tidak ada autentikasi dua faktor per pengguna.

Panduan lama menyarankan Anda membuat ADMIN_TOKEN dengan openssl rand -base64 48. Cara ini berfungsi, tetapi menulis rahasia dalam teks biasa ke config.json dan file compose Anda. Vaultwarden juga menerima string Argon2 PHC (password hashing competition), sehingga nilai yang disimpan berupa hash. Buat string tersebut pada container yang sedang berjalan:

docker exec -it vaultwarden /vaultwarden hash

Atau tanpa menyentuh container yang sedang berjalan:

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

Perintah ini meminta password dua kali, lalu mencetak baris yang diawali dengan $argon2id$. Pada instalasi bare metal, jalankan ./vaultwarden hash. Jika Anda ingin menggunakan CLI argon2 secara langsung, project tersebut mendokumentasikan parameter minimum OWASP:

echo -n 'MySecretPassword' | argon2 "$(openssl rand -base64 32)" -e -id -k 19456 -t 2 -p 1

Sekarang perhatikan jebakan yang dapat menghabiskan waktu satu jam. String PHC berisi banyak karakter $, sedangkan Docker Compose memperlakukan $ sebagai interpolasi variabel. Jika Anda menempelkannya tanpa escape ke dalam blok environment:, nilai yang diterima container akan rusak. Akibatnya, /admin menolak token yang sebenarnya benar. Ada dua bentuk yang aman. Dalam docker-compose.yml, gandakan setiap $:

environment:
  ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$UUZxK1FZMkZoRHFQRlVrTXZvS0E3bHpNQW55c2dBN2NORzdsa0Nxd1JhND0$$cUoId+JBUsJutlG4rfDZayExfjq4TCt48aBc9qsc3UI

Dalam file .env, escape tidak diperlukan, tetapi gunakan tanda kutip tunggal:

ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$MmeKRnGK5RW5mJS7h3TOL89GrpLPXJPAtTK8FTqj9HM$DqsstvoSAETl9YhnsXbf43WeaUwJC6JhViIvuPoig78'

Selanjutnya, batasi laju akses ke panel dan persingkat sesi:

ADMIN_RATELIMIT_SECONDS=300
ADMIN_RATELIMIT_MAX_BURST=3
ADMIN_SESSION_LIFETIME=20

Setelah tiga percobaan yang gagal dalam lima menit, panel berhenti merespons client tersebut. Sesi admin berakhir setelah 20 menit tanpa aktivitas.

Yang lebih baik: nonaktifkan halaman tersebut. Sebagian besar instance hanya memerlukannya sekali untuk mengonfigurasi SMTP dan mengundang pengguna pertama, lalu tidak pernah lagi. Untuk menonaktifkannya, jangan tetapkan ADMIN_TOKEN maupun DISABLE_ADMIN_TOKEN, hapus kunci "admin_token" dari config.json, lalu buat ulang container. Menghapus kunci dari file penting karena halaman admin menulis pengaturan ke sana, dan nilai dalam config.json mengalahkan environment. Menghapus variabel saja membuat halaman tersebut tetap terbuka.

Tutup pendaftaran sebelum ada yang menemukan domain tersebut

SIGNUPS_ALLOWED=false
SIGNUPS_VERIFY=true
SHOW_PASSWORD_HINT=false

SIGNUPS_ALLOWED secara default bernilai true. Biarkan demikian. Siapa pun yang mengakses domain Anda dapat membuat akun, dan datanya disimpan dalam db.sqlite3 yang sama dengan data Anda. Ubah nilainya menjadi false, lalu tambahkan pengguna melalui undangan dari halaman admin. Fitur ini memerlukan SMTP yang berfungsi. INVITATIONS_ALLOWED juga secara default bernilai true dan memungkinkan pemilik organisasi mengundang pengguna lain. Pengaturan ini sesuai jika Anda memercayai pengguna, dan seharusnya bernilai false pada instance pengguna tunggal. Jika hanya domain tertentu yang boleh digunakan untuk pendaftaran, SIGNUPS_DOMAINS_WHITELIST=example.com lebih terbatas daripada pendaftaran terbuka, tetapi jauh lebih lemah daripada undangan.

SHOW_PASSWORD_HINT secara default bernilai false dan sebaiknya tetap demikian. Jika diaktifkan, memasukkan alamat email yang valid pada formulir login akan menampilkan petunjuk kata sandi utama akun tersebut. Hal ini membocorkan petunjuk tersebut sekaligus mengonfirmasi bahwa alamat email itu terdaftar.

Jika instance Anda pernah mengaktifkan pendaftaran terbuka selama waktu tertentu, buka halaman admin dan periksa daftar pengguna sebelum menganggap bahwa hanya ada satu akun di dalamnya.

Port yang tidak Anda maksudkan untuk dipublikasikan

Docker image mendengarkan pada port 80 di dalam container. Instalasi bare-metal menggunakan ROCKET_PORT=8000 secara default. Perintah run yang didokumentasikan memublikasikannya seperti ini:

--publish 127.0.0.1:8000:80

Prefix 127.0.0.1: adalah inti dari konfigurasi ini. Jika Anda menulis -p 8000:80, Docker akan melakukan bind pada 0.0.0.0. Docker melakukannya dengan menulis aturan DNAT (destination network address translation) ke dalam tabel nat. Aturan tersebut dievaluasi sebelum chain filter yang dikelola ufw. Karena itu, ufw status melaporkan port sebagai ditolak, padahal port tersebut tetap menerima koneksi dari Internet. Mekanisme lengkapnya dijelaskan dalam panduan tentang port Docker yang melewati ufw.

Periksa port yang benar-benar sedang mendengarkan:

sudo ss -tlnp | grep 8000

Hasil yang benar adalah satu baris yang terikat pada 127.0.0.1:8000. Baris yang terikat pada 0.0.0.0:8000 berarti vault terekspos secara langsung. Perbaiki pemetaan tersebut, lalu buat ulang container. Port binding ditetapkan saat container dibuat, dan docker compose restart tidak akan mengubahnya:

docker compose up -d --force-recreate

Masih ada satu port lain dalam panduan lama: 3012, yaitu port WebSocket terpisah. Dukungan untuk port tersebut dihapus pada Vaultwarden 1.31.0 karena trafik notifikasi dipindahkan ke port HTTP utama. WEBSOCKET_ENABLED dan WEBSOCKET_PORT diabaikan sejak 1.29.0. Pengaturan yang digunakan saat ini adalah ENABLE_WEBSOCKET, yang secara default bernilai true. Jika firewall atau file compose Anda masih membuka port 3012, tutup port tersebut.

Hentikan TLS pada reverse proxy, bukan di Rocket

Vaultwarden dapat melayani TLS (transport layer security) sendiri melalui Rocket, yaitu web framework yang digunakannya. Namun, proyek ini menyarankan agar cara tersebut tidak digunakan di lingkungan produksi. TLS bawaan Rocket tidak mendukung SNI (server name indication) secara ketat. Karena itu, panduan hardening juga menyarankan agar instance diakses menggunakan hostname dan tidak pernah menggunakan alamat IP langsung. Rentang IP publik terus-menerus dipindai. Vault yang merespons pada alamat IP akan ditemukan.

Bagian server block nginx yang penting:

client_max_body_size 525M;

location / {
  proxy_pass http://127.0.0.1:8000;
  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_set_header Upgrade $http_upgrade;
  proxy_set_header Connection $connection_upgrade;
}

Secara default, nginx menetapkan client_max_body_size ke 1 MB. Tanpa baris tersebut, unggahan lampiran gagal dengan 413 Request Entity Too Large pada error log nginx, sedangkan Vaultwarden sama sekali tidak mencatat apa pun. Header Upgrade dan Connection meneruskan handshake WebSocket ke /notifications/hub. Jika header tersebut dihilangkan, vault tetap berfungsi. Namun, perubahan tidak lagi muncul pada perangkat lain sampai halaman dimuat ulang secara manual.

Konfigurasi Caddy lebih singkat dan memperoleh sertifikat secara otomatis:

vw.example.com {
  reverse_proxy 127.0.0.1:8000 {
    header_up X-Real-IP {remote_host}
  }
}

Selanjutnya, beri tahu Vaultwarden tentang konfigurasi tersebut:

DOMAIN=https://vw.example.com
IP_HEADER=X-Real-IP

IP_HEADER secara default sudah bernilai X-Real-IP. Jadi, tugasnya adalah memastikan proxy benar-benar menetapkan header tersebut. Jika tidak, setiap baris log dan setiap rate limit login akan melihat 127.0.0.1, yaitu proxy itu sendiri. Akibatnya, kegagalan dari satu penyerang akan dihitung terhadap semua pengguna pada instance tersebut. Tetapkan DOMAIN ke URL https yang sebenarnya. Vaultwarden menggunakan nilai ini untuk membuat link undangan dan reset password, dan security key WebAuthn terikat pada origin tersebut.

Ada satu detail yang sering terlewat. Koneksi WebSocket meneruskan session token dalam query string sebagai /notifications/hub?access_token=[JWT]. Nilai tersebut masuk ke access log proxy tanpa penyamaran. Redact parameter access_token dalam format log, atau pastikan log tersebut tidak dikirim ke lokasi mana pun yang tidak Anda kendalikan.

Blokir brute force pada endpoint login

Batas laju aktif secara default (LOGIN_RATELIMIT_SECONDS=60, LOGIN_RATELIMIT_MAX_BURST=10). Batas ini memperlambat penyerang, tetapi tidak menghentikannya. fail2ban dapat menghentikannya, tetapi Vaultwarden harus menulis file log terlebih dahulu, dan secara default tidak melakukannya:

LOG_FILE=/data/vaultwarden.log
LOG_LEVEL=info
EXTENDED_LOGGING=true

Login yang gagal kemudian menghasilkan tepat satu baris. Filter Anda harus mencocokkan string ini:

[2026-08-07 09:14:22][vaultwarden::api::identity][ERROR] Username or password is incorrect. Try again. IP: 203.0.113.10. Username: user@example.com.

Tulis filter ke /etc/fail2ban/filter.d/vaultwarden.local:

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =

Tulis jail ke /etc/fail2ban/jail.d/vaultwarden.local:

[vaultwarden]
enabled = true
port = 80,443
filter = vaultwarden
banaction = %(banaction_allports)s
logpath = /vw-data/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Jika Anda tetap menggunakan halaman admin, tambahkan jail kedua yang failregex-nya adalah ^.*Invalid admin token\. IP: <ADDR>.*$, karena kegagalan login admin dicatat dengan pesan yang berbeda dan filter login tidak akan pernah menemukannya. Kemudian periksa konfigurasi Anda:

sudo systemctl restart fail2ban
sudo fail2ban-client status vaultwarden

Jail yang berfungsi mencantumkan file log Anda di bawah File list dan melaporkan Currently failed: 0. Masukkan kata sandi yang salah tiga kali dari jaringan yang berbeda. Penghitung tersebut akan bertambah, lalu alamat itu muncul di bawah Banned IP list. Jika penghitung tidak pernah bertambah, penyebab yang biasanya terjadi adalah logpath: nilai tersebut harus berupa path file pada host, bukan path /data/... di dalam container. Penyebab umum kedua adalah X-Real-IP yang tidak ada, sehingga setiap ban menargetkan proxy Anda sendiri. Konfigurasi lainnya, termasuk jail SSH yang seharusnya sudah Anda jalankan, tersedia di panduan fail2ban untuk Ubuntu 24.04.

Kata sandi master tetap merupakan keseluruhan sistem

Enkripsi sisi klien berarti kata sandi master adalah kuncinya. Kata sandi master yang pendek pada instance yang databasenya telah disalin penyerang tidak dilindungi oleh apa pun dalam tulisan ini, karena penyerang dapat menyerang salinan tersebut secara offline dengan kecepatan yang diizinkan oleh perangkat keras mereka. Tidak ada pengaturan server yang dapat menjangkau mesin milik penyerang.

PASSWORD_ITERATIONS=600000 mudah disalahartikan. Pengaturan ini menentukan jumlah iterasi untuk hash sisi server dari hash login yang dikirim klien, dan templat konfigurasi proyek menyatakan bahwa nilai yang diubah akan diterapkan kepada pengguna yang sudah ada saat login berikutnya. Pengaturan ini tidak memengaruhi KDF sisi klien, yaitu pengaturan yang menentukan biaya serangan offline terhadap vault. Pengaturan tersebut berlaku untuk setiap akun: seseorang yang mendaftar bertahun-tahun lalu mungkin masih menggunakan pengaturan KDF lama yang lebih rendah sampai menaikkannya di pengaturan keamanan vault web, yang akan mengenkripsi ulang kuncinya. Sampaikan hal ini kepada mereka, karena server tidak dapat melakukannya untuk mereka.

Selanjutnya, aktifkan autentikasi dua faktor untuk setiap akun. Fitur ini tidak melindungi ciphertext, karena kunci vault hanya berasal dari kata sandi master. Namun, fitur ini mencegah kata sandi yang dicuri saja cukup untuk login dan menyinkronkan salinan. REQUIRE_DEVICE_EMAIL=true mewajibkan email login perangkat baru: jika Vaultwarden tidak dapat mengirimkannya, login gagal, sehingga login dari perangkat yang tidak dikenali tidak pernah berlangsung tanpa pemberitahuan. Fitur ini memerlukan SMTP yang berfungsi; jika tidak, setiap login dari perangkat baru akan ditolak.

Backup adalah titik kegagalan self-hosted vault

Satu tar czf dari folder data yang dibiarkan di direktori home pada VPS yang sama membatalkan semua langkah di atas. Arsip tersebut berisi db.sqlite3 dengan ciphertext setiap pengguna, rsa_key.pem yang dapat memalsukan sesi login, serta config.json dengan token admin dan password SMTP dalam teks biasa. Akses baca ke satu file itu berarti akses baca ke vault.

Dua aturan sudah mencukupi. Simpan arsip di luar server. Enkripsi arsip sebelum dikirim.

Ada juga masalah integritas data. Menyalin db.sqlite3 menggunakan cp saat service sedang berjalan dapat menghasilkan file yang sedang ditulis dan tidak dapat dibuka. Anda mungkin baru mengetahuinya saat melakukan restore. Gunakan snapshot bawaan SQLite:

sqlite3 /vw-data/db.sqlite3 ".backup '/tmp/vw-db-backup.sqlite3'"

Sisi restore, yang sering tidak pernah diuji, dibahas dalam panduan backup dan restore Vaultwarden.

Yang Anda korbankan dibandingkan Bitwarden hosted

Evaluasi yang jujur. Layanan hosted Bitwarden dioperasikan oleh orang-orang yang pekerjaan penuhnya adalah mengelolanya, dengan audit pihak ketiga yang dipublikasikan dan petugas yang siaga pada pukul 3 pagi. Self-hosting menukar hal tersebut dengan jadwal patching Anda sendiri.

Vaultwarden merilis perbaikan keamanan sebagai rilis biasa, dan rilis tersebut sering diterbitkan. Berdasarkan pemeriksaan pada 7 October 2026 terhadap release feed proyek, rilis saat ini adalah 1.37.4, yang diterbitkan pada 5 October 2026. Catatan rilisnya mencakup tujuh security advisory, dengan tingkat keparahan tertinggi High, dan sangat menyarankan pembaruan sesegera mungkin. Ini adalah rilis keempat sejak 1.37.0 pada 24 July 2026: 1.37.1 menyusul pada 29 July, 1.37.2 pada 22 August (diperlukan untuk client versi 2026.8.0 dan yang lebih baru), serta 1.37.3 pada 13 September, yang mencabut remember token 2FA ketika kredensial atau 2FA berubah dan menerapkan rate limit pada endpoint prelogin dan auth request. Jika Anda menjalankan organisation dengan admin yang tidak sepenuhnya Anda percayai, catatan 1.37.4 juga menyarankan agar API key setiap organisation dirotasi setelah pembaruan. Instance yang Anda siapkan setahun lalu lalu lupakan masih menjalankan code yang berusia setahun. Tag latest tidak membantu dengan sendirinya: container yang sedang berjalan tetap menggunakan image yang digunakan saat pertama kali dijalankan sampai Anda menjalankan docker compose pull dan membuatnya kembali. Terapkan unattended upgrades di Ubuntu untuk package host, lalu masukkan pembaruan container ke pengingat kalender yang benar-benar akan Anda baca.

Kesimpulan yang seharusnya diambil pembaca secara jujur: kriptografi di sini adalah rancangan Bitwarden dan tetap kuat, sedangkan risiko operasional sepenuhnya berpindah kepada Anda. Jika Anda melakukan patching dan mencadangkannya di lokasi lain, instance Vaultwarden pada VPS yang Anda kendalikan merupakan tempat yang wajar untuk menyimpan password. Jika kedua kebiasaan tersebut tidak akan dilakukan, bayarlah layanan hosted dan alihkan perhatian Anda ke hal lain. Perbandingan berdasarkan fitur tersedia di Vaultwarden dibandingkan dengan Bitwarden self-hosted.

Perkuat host di bawah container

Vaultwarden adalah salah satu proses pada sistem Linux, dan root pada sistem tersebut dapat membaca /vw-data terlepas dari konfigurasi aplikasi. Jalankan container sebagai pengguna tanpa hak istimewa dengan user: "1000:1000" di file compose, lalu pastikan folder data dimiliki oleh pengguna dan grup yang sesuai. Pasang apa pun yang tidak perlu ditulis oleh container sebagai read-only dengan :ro. Setelah itu, tutup akses dari luar: Pengerasan SSH pada VPS membahas login khusus dengan cryptographic key dan penonaktifan autentikasi berbasis kata sandi. Langkah ini mencegah serangan sederhana yang dapat melewati semua perlindungan tersebut.

FAQ

Apakah seseorang dapat membaca kata sandi saya jika mereka mencuri database Vaultwarden?

Tidak secara langsung. Setiap item vault dienkripsi di client menggunakan kunci yang diturunkan dari master password, sehingga db.sqlite3 berisi ciphertext. Data yang langsung mereka peroleh adalah alamat email setiap akun, pengaturan KDF, metadata login dan perangkat, serta secret autentikasi dua faktor dalam tabel twofactor. Data tersebut disimpan tanpa enkripsi karena server harus menghitung kode yang diharapkan. Mereka juga dapat menyerang ciphertext vault secara offline selama yang mereka inginkan. Karena itu, panjang master password menjadi faktor yang menentukan hasilnya.

Apakah saya sebaiknya menggunakan ADMIN_TOKEN atau menonaktifkan halaman admin sepenuhnya?

Nonaktifkan halaman tersebut jika memungkinkan. Sebagian besar instance hanya memerlukannya sekali untuk mengonfigurasi SMTP dan mengundang pengguna. Setelah itu, halaman tersebut biasanya tidak diperlukan lagi. Untuk menonaktifkannya, jangan tetapkan ADMIN_TOKEN maupun DISABLE_ADMIN_TOKEN, hapus kunci "admin_token" dari config.json, lalu buat ulang container. Menghapus variabel lingkungan saja tidak cukup karena pengaturan yang ditulis melalui halaman admin tersimpan di config.json dan memiliki prioritas lebih tinggi. Jika halaman tersebut tetap digunakan, simpan token sebagai hash Argon2 yang dihasilkan oleh vaultwarden hash, bukan sebagai string acak plaintext, lalu tetapkan ADMIN_RATELIMIT_MAX_BURST=3.

ADMIN_TOKEN saya benar, tetapi /admin menolaknya. Apa masalahnya?

Hampir selalu masalahnya adalah interpolasi $. String PHC Argon2 berisi beberapa karakter $. Docker Compose memperluas karakter tersebut sebagai variabel di dalam blok docker-compose.yml environment:, sehingga container menerima nilai yang berubah meskipun file Anda tampak benar. Gandakan setiap $ menjadi $$ di file compose, atau pindahkan nilainya ke file .env yang dibungkus dengan tanda kutip tunggal. Dengan cara ini, escaping tidak diperlukan. Buat ulang container setelahnya karena perubahan lingkungan tidak diterapkan hanya dengan restart.

Apakah saya masih perlu membuka port 3012 untuk notifikasi?

Tidak. Dukungan untuk trafik WebSocket pada port 3012 dihapus dalam Vaultwarden 1.31.0 karena notifikasi dipindahkan ke port HTTP utama. WEBSOCKET_ENABLED dan WEBSOCKET_PORT juga telah diabaikan sejak 1.29.0. Pengaturan saat ini adalah ENABLE_WEBSOCKET, yang secara default bernilai true. Tutup port 3012 di firewall dan hapus port tersebut dari file compose. Selanjutnya, pastikan reverse proxy meneruskan header Upgrade dan Connection karena sinkronisasi real-time saat ini bergantung pada header tersebut.