Vaultwarden 自架完整指南:用 Cloudflare Tunnel 反向代理 + 安全強化
Self-hosting Vaultwarden with Cloudflare Tunnel
自架密碼管理服務聽起來很硬核,但其實 Vaultwarden 搭配 Cloudflare Tunnel 設定起來十分簡單,設定一次後幾乎不用維護。不需要公網 IP、不用 DDNS、不用維護憑證、不用開防火牆規則。整個架構裡唯一露在外面的只有 Cloudflare,而 Cloudflare 本身基本上扛得住任何規模的 DDoS。
這篇文章是我自己跑了一段時間後的整理,從架設、架好之後該調的安全設定,到日常使用發現的技巧。
為什麼選 Cloudflare Tunnel
不推薦 nginx 反向代理
很多教學會教你架 nginx + Let's Encrypt 處理 HTTPS。這對大部分人不是一個好選擇,原因如下:
憑證要自己管。 Certbot 雖然能自動續期,但出狀況(DNS challenge 壞掉、rate limit 觸發)你得自己 debug。
多一層服務要維護。 nginx 設定檔、log rotation、版本更新都要自己做。
要設定公網訪問、開公網 port,還要做好防火牆規則。 Port 443 必須對外開放,等於把你的 server 直接掛在公網上,需要面對被 botnet 掃 port、DDoS 的風險。
不推薦 Tailscale Funnel
Tailscale 在分散組網、純內網使用的場景下非常好用,但要用它對外暴露服務(Funnel)有幾個痛點:
只有
443、8443、10000三個 port 可用,沒做反向代理的話你只能公開三個 web 服務。開 443 funnel 會佔用主機本身的 443 port,跟 Cloudflare Tunnel 完全不同。
不支援自訂域名,只能用
*.ts.net子域名。Tailscale daemon 會動 iptables,跟 Docker 網路偶爾會衝突。
Cloudflare Tunnel 的優點
cloudflared 是主動發起連線到 Cloudflare 邊緣的,所以你的 server:
- 不需要公網 IP
- 不需要 DDNS
- 不需要開任何 inbound port
- 不需要防火牆規則調整
- 不會被掃 port,主機不會被 DDoS
Cloudflare 自動幫你維護憑證。申請一個免費子域名(有興趣可看我之前的教學)或買一個域名託管到 Cloudflare 就能用。
但 Cloudflare 看得到 HTTP 明文怎麼辦?這是合理的擔憂,但實際影響比想像中小。
TLS 終止點是 CF edge,所以 Cloudflare 確實在 edge 那一端能看到完整 HTTP 請求內容,任何反向代理架構都有這個問題。但 Bitwarden 協議的核心設計是零知識,因此:
- 主密碼永遠不會離開你的客戶端
- 金庫資料在客戶端用 master key(從 password 推導出來)加密成 blob,已加密的 blob 才上傳到 server
- 認證送的是 hash 過兩輪的 auth hash,不是密碼本身
所以即使 Cloudflare 把所有流量錄下來,他們看到的是一坨密文,沒有主密碼就解不開。連 Bitwarden 自己的 server 都解不開託管的金庫。
如果你用瀏覽器開 https://vw.your-domain.com 輸入主密碼登入,Cloudflare 理論上可以在 edge 修改回應內容、塞惡意 JS 偷你的主密碼。能力上是存在的,但 Cloudflare 有強烈動機不這樣做(這樣會毀掉整個生意)。
緩解方法也很簡單,只用原生客戶端就沒問題。桌面 app、瀏覽器 extension、手機 app,這些 Cloudflare 完全動不了。原生客戶端跟 server 之間只交換加密 blob 跟 auth hash,被 MITM 也沒用。
前置步驟:取得 TUNNEL_TOKEN
- 進 Cloudflare Zero Trust → Networks → Connectors → Create a tunnel
- Select your tunnel type 選 Cloudflared
- 給 tunnel 命名
- 下一步選安裝方式 Docker,會跳出一行命令,裡面
--token後面那串eyJhIjoi...就是 token,存起來備用
前置步驟:設定 Public Hostname
Tunnel 建好後,在那條 tunnel 的 Public Hostname 加一條:
| 欄位 | 值 |
|---|---|
| Subdomain | vw(填你想設定的名稱) |
| Domain | your-domain.com |
| Service Type | HTTP |
| URL | vaultwarden:80 |

設定好以後現在網頁還不能通,因為容器還沒啟動。可以先複製網址存起來備用,如圖所示。
部署 Vaultwarden
最簡單的方式是把 Vaultwarden 跟 cloudflared 放在同一個 Portainer stack 裡,也可以用 docker compose,那麼你需要再建一個 .env 把環境變數填進去。這裡用 Portainer stack 來示範。
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vw.your-domain.com"
SIGNUPS_ALLOWED: "true" # 第一次先選 true,註冊好後改成 false 然後 update stack
SHOW_PASSWORD_HINT: "false"
ROCKET_PORT: "80"
LOG_LEVEL: "warn"
TZ: "Asia/Taipei"
volumes:
- vw-data:/data
# 完全不暴露 port
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared-vw
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN}
depends_on:
- vaultwarden
volumes:
vw-data:
進入 Portainer,點擊 stacks 按鈕,點擊 Add stack 按鈕。

進入編輯頁面,照著圖片設置。


DOMAIN 這裡填上剛剛複製的網址。

往下滑看到 Environment variables,點擊 Add an environment variable,name 填上 TUNNEL_TOKEN,value 就是剛剛複製的 Cloudflared token,將它貼上,點擊 Deploy the stack。
初始設定:註冊與關閉公開註冊
如果你的 Vaultwarden 是要個人使用,要防止其它人用你的伺服器註冊帳號,那麼第一次部署完請做以下步驟:
- 用瀏覽器進設定好的網址應該就能看到登入頁,註冊你自己的帳號
- 回到 Portainer,把 stack env 裡
SIGNUPS_ALLOWED改成false - Update the stack 重新拉起
如果你只給自己用,完全不需要設 ADMIN_TOKEN。設定 ADMIN_TOKEN 後會多一個 /admin 路徑,這是管理用戶的介面,有需要這個功能請查找其它文章,這裡不再贅述。
強化主密碼與 Argon2id
進金庫 → Account Settings → Security → Keys,把 KDF 從預設的 PBKDF2 改成 Argon2id。Argon2id 是現在公認最強的 password hashing 函數,對 GPU 跟 ASIC 的暴力破解抵抗力比 PBKDF2 強得多。
Argon2id 在 iOS AutoFill 上的問題
如果你會在 iOS 上用 AutoFill(自動填入密碼):Argon2id 預設的 64MB 記憶體可能會讓 AutoFill 出問題。因為 iOS AutoFill extension 的記憶體上限是 120MB,Argon2id 佔太多記憶體就可能讓 AutoFill 報錯甚至終止。GitHub 上有用戶回報即使設 64MB 也不見得穩定(90–105MB 則是穩定失敗),如果你平時會輸入主密碼解鎖,那麼應該把 Argon2id 記憶體下調到 48MB;如果平時用 FaceID / TouchID / PIN 解鎖,它們都不用 Argon2,因此不受 120MB 的限制。
密碼熵比 KDF 參數重要
很多人會拚命把 Argon2id iterations 跟 memory 拉滿,但其實提高密碼熵才是最能提升安全性的因素。
KDF 參數的作用是讓單次嘗試變慢,但如果你的主密碼只有 40 bits 熵,再強的 Argon2id 參數也只能拖延幾天到幾年;反過來如果你密碼有 100+ bits 熵,連 MD5(無 salt)暴力破解都是幾乎不可能的任務。
用 Bitwarden 內建密碼產生器產生的 20 字元密碼(混合大小寫、數字、符號,字元集共 70 個),密碼熵大約是 122.6 bits。假設攻擊者每秒能計算十億個雜湊值(Argon2id 實際上遠遠達不到這個速度,就算用 GPU 農場每秒也只有幾千次,這裡是誇飾),在第 50 年放棄破解,這組密碼被破解的機率是 ,100 年是 ,就算算滿 1000 年也只有 ,攻擊者能探索的密碼空間連總數的一億億分之一都不到。被破解的機率趨近於 。
| 攻擊持續時間 | 假設總嘗試運算次數 | 破解機率 (嘗試次數 / 總組合數) |
|---|---|---|
| 50年 | ||
| 100年 | ||
| 1000年 |
因此設定一個高熵的主密碼,然後把 Argon2id 記憶體調到 48MB,能保證安全性和相容性,是比較好的作法。
但請注意主密碼一旦忘記,金庫真的就解不開了。主密碼應該寫在實體紙本鎖在抽屜或保險箱,給自己留一條後路。
兩步驟驗證(2FA)
自架 Vaultwarden 的好處之一是能夠解鎖很多 Bitwarden 付費版的功能,其中一個功能是 authenticator TOTP 整合:網站的兩步驟驗證金鑰(TOTP Secret)可以直接存進 vault。Bitwarden 查詢密碼後,不需要跳出 app 打開其它的 authenticator,直接看驗證碼輸入就好,也不用額外備份 authenticator。換裝置只要在 Bitwarden 中輸入 Vaultwarden 網址、登錄帳號,authenticator 和密碼就會同步到裝置上了。

例外:vault 自己的 2FA
既然 Vaultwarden 本身存放著所有密碼與驗證碼,那麼 Vaultwarden 帳號更應該啟用兩步驟驗證保護。但 Vaultwarden 自己的登入 2FA 需要另外的 authenticator 來存放,不然雞生蛋蛋生雞,登不進去就解不開。所以至少需要一個獨立的 Authenticator app 來保存 Vaultwarden 的登入驗證碼。
設定路徑:Account Settings → Security → Two-step Login → Authenticator app,啟用後會跳出 QR code。

我的做法:同一個 QR code 掃兩次
- 用獨立 Authenticator app 掃一次(這是主要登入用的,必須有)
- 同一個 QR 也用 Bitwarden 手機 app 掃一次存進 vault
第二次掃進 vault 是為了「已登入裝置的便利性」——當你要在新筆電登入 Vaultwarden 時,可以從手機上已經解鎖的 vault 直接看到 TOTP,不用每次都掏出獨立 Authenticator app。同時也達到「兩個獨立位置互為備份」的效果,獨立 Authenticator 壞了還有 vault 那份,反之亦然。安全性、便利性、備份能力一次到位。
推薦的獨立 Authenticator app
不要再用 Authy 了。 桌面版 2024 年 3 月停止服務,手機版進入維護模式不再開發,2024 年 7 月還爆出 3300 萬筆使用者電話號碼外洩。
目前比較推薦的選擇:
- Ente Auth:開源,端對端加密雲端同步,跨平台(桌面/手機/瀏覽器)。最像當年的 Authy。
- 2FAS:開源,可用 iCloud / Google Drive 備份,有瀏覽器 extension。
- Bitwarden Authenticator:Bitwarden 自家獨立 app,可選擇跟 vault 雙向同步(同一支裝置內透過 OS IPC 同步,不走 server 同步)。
- Aegis(Android only):純本地加密備份。
Recovery code 一定要印出來
啟用 2FA 後系統會提供一組 recovery code。這組碼不要存在 vault 裡,印出來放實體保險箱或抽屜。所有 Authenticator 裝置都無法使用時,這是唯一能進 vault 的方法。
日常使用:讓子域名分開比對
預設情況下 Bitwarden 會把同一個主域名下的子域名當成同一個目標,所以 a.example.com 跟 b.example.com 的登入會被一起列出來。如果你部署了很多服務並劃分了子域名,a.example.com 的帳號會出現在 b.example.com 的自動填入中;如果想讓 Bitwarden 對它們分開比對,請依照以下步驟設定:
操作路徑:Vault → 該筆登入項目 → Website (URI) → 右側齒輪 → Match detection → Host
幾種 match detection 模式的差異:
- Base domain(預設):比對到主網域,子域名一視同仁
- Host:依主機名比對,
a.example.com跟b.example.com是不同目標 - Starts with / Regular expression:更精細的控制
- Exact:連協定、主機、路徑都鎖死,最嚴格
子域名很多的服務(Google、AWS、Atlassian 等)改成 Host 會讓 auto-fill 體驗精準很多。Bitwarden 也支援每個登入項目單獨設定,不用整個帳號改。

小結
使用 Vaultwarden + Cloudflare Tunnel 自架密碼管理服務,架設一次之後幾乎不用維護,憑證自動續期、沒有對外暴露的 port,配合 Bitwarden 協議的零知識設計,安全性很高。
幾個值得記住的原則:
- 建議用 native client,性能更有優勢;如果你怕 web vault 在 reverse proxy 架構下的 MITM 風險,用客戶端可以放心很多
- Vaultwarden 可以設
ADMIN_TOKEN開啟/admin管理介面,但一般個人用戶沒必要。註冊完立刻關SIGNUPS_ALLOWED,就不用怕有人在你的伺服器上註冊帳號 - 20 字元高熵主密碼 > 調高 KDF 參數
- iOS AutoFill 使用者注意 Argon2id 記憶體別超過 48MB
- Recovery code 印出來放實體保險箱,零知識架構沒有「忘記密碼可以救援」這回事
最後兩件事:定期備份 vw-data volume、記得更新 Vaultwarden 容器。
封面圖片來源:https://pixabay.com/photos/door-bell-door-knob-bell-ring-498392/
參考資料:
- 使用 Bitwarden 與自架後端 Vaultwarden 來管理密碼與 2FA Authenticator | omegaatt
- 自架Bitwarden伺服器「Vaultwarden」備份現有帳號密碼 · Ivon的部落格
- Best Argon2id settings? - Bitwarden Community Forums
- PBKDF2 vs Argon2 - which is better? - Bitwarden Community Forums
- Encryption Key Derivation | Bitwarden
- Unable to autofill on iOS - Bitwarden Community Forums
- Important PSA for iOS and Argon2 users - Bitwarden Community Forums
- iOS not auto-filling properly with argon2id · bitwarden/mobile #2389
- Integrated Authenticator | Bitwarden
- Forming URIs for Autofill | Bitwarden
- 搭建自己的密码库Vaultwarden | ByteJog
- Ubuntu 上的 Bitwarden/Vaultwarden 從零開始安裝教學 | Trent's Blog