飞牛 NAS 自建密码箱 Vaultwarden 实录:双重 NAT 也拦不住一张免费证书

上个周末我把家里那台 NAS 的容器列表数了一遍,23 个。

第 24 个是昨天半夜加进去的,它只干一件事:替我记密码。
图片.png

先说个丢人的事

我今年 36,做机电这行 14 年,能背下来一整套消防设施的联动逻辑。

但上个月有一天,我连续点了三次「忘记密码」。

一个是网盘,一个是老家的宽带账号,还有一个是某个连我自己都想不起来为啥要注册的论坛。最后那个我干脆放弃了——反正注册完也没用过。

浏览器自带的「记住密码」我用过,确实省事。问题是换台设备就没了,而且那东西本质上还是躺在浏览器里,重装系统、换电脑、手机丢了,都得重来一遍。

后来我想明白了:这事不该靠脑子,该靠一台机器。


为什么不用现成的商业密码管理器

倒不是说它们不好。1Password、Bitwarden 官方、各家浏览器自带的,都挺成熟。

但我就是不太想把所有账号的钥匙交给一个我控制不了的服务器。这不是阴谋论,是很简单的账:

  • 密码箱这东西一旦被攻破,损失不是「一个账号」,是全部账号
  • 我没有能力去审计那家公司到底怎么存、怎么加密、会不会哪天被收购
  • 而这事,恰恰是我自己家里那台 24 小时开着的 NAS 最适合干的活

所以我决定自建。花一个晚上。


选型:为什么是 Vaultwarden

自建密码管理器有几个主流选择,我简单说下我怎么筛的:

方案为什么没选 / 选了
Bitwarden 官方自建版太重,要拖一堆容器 + SQL Server,我这台小机器伺候不起
KeePass / KeePassXC最安全、也最"本地",但就是个加密文件,跨设备同步要自己折腾 WebDAV,手机端体验一般
Passbolt / Psono偏团队协作,个人用太绕
Vaultwarden ✅Bitwarden 服务端的 Rust 轻量重写版,一条 docker 起来,内存占用一百多兆

Vaultwarden 最香的一点是:它兼容 Bitwarden 的官方客户端。

也就是说,服务器是我自己的,但手机 App、电脑浏览器扩展,我用的还是 Bitwarden 那些成熟客户端——iOS、安卓、Windows、Mac、Chrome、Edge,全都有。

存进去的密码、验证码(TOTP)、附件,电脑上改一下,手机上几秒钟就同步过去了。


真正的难点不是装它,是那张证书

Vaultwarden 本体五分钟就能跑起来。我真正折腾了一晚上的,是证书。

原因是两个坎叠在一起:

第一个坎:Bitwarden 客户端要求 HTTPS。不是"建议",是硬要求。

网页版的密码箱走的是一套浏览器加密接口(WebCrypto),而浏览器只在 https 或者 localhost 下才开放这套接口。你用 http://192.168.1.100:8080 打开,页面能显示,但一登录就崩。

手机 App 松一点,会弹「不安全连接」的警告让你硬上,但我不想天天看那个警告。

第二个坎:我家是双重 NAT。

公网 IP 在光猫上,拨号也在光猫上,我自己的路由器 WAN 口拿的是光猫内网地址。这意味着——路由器上做端口映射,对外根本无效。

而申请免费证书的标准姿势(HTTP 验证)需要一个能被公网访问的地址。这路直接堵死。

解法:换成 DNS 验证

证书颁发机构(Let's Encrypt)验证域名归属有两种方式:

  • HTTP 验证:我给你一个文件,你放到 http://你的域名/.well-known/...,我访问一下能看到就算你的 → 需要公网可达 ❌
  • DNS 验证:我给你一条 TXT 记录,你加到你域名的解析里,我查一下能查到就算你的 → 只用到 DNS,不需要公网 IP,不需要开任何端口 ✅

DNS 验证这条路,完美绕开双重 NAT。

而且我的域名解析托管在腾讯云 DNSPod,它有 API,所以这件事可以全自动,连 TXT 记录都不用我手动加。
图片.png


开工(可收藏的命令清单)

下面这一段是纯操作,想自己抄的可以直接复制。
完整版(含架构图、验收清单、9 条踩坑)我整理成文档放在 NAS 上了,需要的话评论区说一声。

① 起 Vaultwarden

# 国内拉镜像记得换源,不然卡死
sudo docker pull docker.m.daocloud.io/vaultwarden/server:latest
sudo docker tag docker.m.daocloud.io/vaultwarden/server:latest vaultwarden/server:latest

mkdir -p /vol1/1000/docker/vaultwarden

sudo docker run -d --name vaultwarden --restart unless-stopped \
  -p 8080:80 \
  -v /vol1/1000/docker/vaultwarden:/data \
  -e SIGNUPS_ALLOWED=true \
  -e WEBSOCKET_ENABLED=true \
  -e DOMAIN="https://pass.你的域名.com:8443" \
  -e ADMIN_TOKEN="你自己生成的随机串" \
  -e TZ=Asia/Shanghai \
  vaultwarden/server:latest

② 加一条内网解析

# 用 DNSPod API 加一条 A 记录
# pass.你的域名.com -> 192.168.1.100(你家 NAS 的内网 IP)
# 这一步用腾讯云 API 密钥,脚本是 TC3-HMAC-SHA256 签名,二十来行 Python

③ 用 acme.sh 签证书(DNS 验证)

sudo docker run --rm \
  -v /vol1/1000/docker/acme:/acme.sh \
  --env-file /vol1/1000/docker/acme/account.env \
  neilpang/acme.sh \
  --issue --server letsencrypt --dns dns_tencent \
  -d pass.你的域名.com --keylength 2048 -m 你的邮箱

④ nginx 做 HTTPS 前端

server {
    listen 8443 ssl;
    server_name pass.你的域名.com;
    ssl_certificate     /certs/pass.你的域名.com/fullchain.cer;
    ssl_certificate_key /certs/pass.你的域名.com/pass.你的域名.com.key;

    client_max_body_size 128M;

    location / {
        proxy_pass http://172.17.0.1:8080;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP         $remote_addr;
    }
    # 实时同步的 WebSocket,不加会同步延迟
    location /notifications/hub {
        proxy_pass http://172.17.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

⑤ 自动续期(不然 90 天后过期)

用一个 systemd timer,每周跑一次 acme.sh --cron,续完顺手让 nginx 重新加载证书。


踩的坑(一共 9 个,挑几个说)

坑现象怎么解
镜像拉不动docker pull 卡在那不动换国内源,最后是 docker.m.daocloud.io 拉通的
http 下页面用不了页面能开,一登录就崩必须上 HTTPS,浏览器的加密接口限制
双重 NATHTTP 验证签证书必失败改 DNS 验证,完全不需要公网
fake-ip 绕路 ⚠️域名解析正常,就是连不上旁路由 Clash 把它当国外流量了,得加直连规则
sudo -S 吃 stdin写 systemd 配置文件,结果是 0 字节别用管道喂 sudo,先写 /tmp 再 sudo cp
容器重建丢数据账号全没了必须挂载 -v ...:/data 持久化

第四个坑最阴——我一开始以为是证书问题,查了半天。

后来才想明白:我家里所有设备都走旁路由的 Clash,而那玩意儿是 fake-ip 模式。我把域名解析指向了一个内网 IP,但 Clash 只看域名规则,判定「这是个外网域名」→ 直接扔给日本节点 → 日本节点当然连不上我家的 192.168.1.100。

解决办法是在 OpenClash 的规则头部插两条直连:

- DOMAIN-SUFFIX,你的域名.com,DIRECT
- DOMAIN,pass.你的域名.com,DIRECT

⚠️ 顺带提醒自己也提醒你:机场订阅一更新,这两条就被冲掉了,得重新加。


用起来什么样

现在是这样:

  • 电脑浏览器装 Bitwarden 扩展,设置里填自建服务器地址
  • 手机装 Bitwarden,右上角齿轮 → 「自托管环境」→ 填地址
  • 网页版当管理后台用

电脑上改一条,手机上几秒就同步。验证码也一起进去了,不用再单独装个 TOTP App。

它有个明确的局限,我提前说清楚:

我故意把域名的解析指向内网 IP,所以外网打不开。

这是权衡后的选择——公网暴露一个密码箱,风险大过我需要的便利。而且手机 App 有本地加密缓存,出门在外照样能翻密码,只是不能新增、不能同步。

真要外网也能用,也有办法(端口映射 / 内网穿透 / Cloudflare Tunnel),但那是另一个话题了,等我哪天想动了再说。


最后一个提醒

主密码一定要记牢。

这东西的加密是端到端的——服务器管理员看不到你的密码,也救不了你的密码。

我自己是在保险柜里放了一张纸条。

那晚折腾到十一点半,我把最后一个账号导进箱子,关电脑之前,顺手把冰箱上贴着的那张写满账号密码的便签撕了。

字写得挺潦草的,撕的时候还挺舍不得。


本文同步发布于博客「壹根辣条」,技术细节(含完整部署文档、验收清单、9 条踩坑)整理在飞牛 NAS 上,需要可以留言。

飞牛 NAS 自建密码箱 Vaultwarden 实录:双重 NAT 也拦不住一张免费证书
https://ifmo.cn/index.php/archives/vaultwarden-nas-password-manager.html
本文作者 辣条
发布时间 2026-09-10
许可协议 CC BY-NC-SA 4.0
发表新评论