
密码管理器这东西我前前后后折腾过不少。从浏览器自带密码到各种云端同步再到本地加密文件最后干脆在极空间上部署了一个叫 password-XL 的自托管服务才算真正消停了。今天这篇不聊虚的就把我这一路踩过的坑、最终选型的原因、以及极空间私有化部署 password-XL 的完整过程全写出来给打算入坑自托管密码管理器的朋友一个可以抄作业的参考。先说结论如果你手里正好有一台极空间 NAS那把它变成专属密码服务器是性价比极高的玩法。password-XL 提供了一整套密码存储、自动填充、多端同步的能力数据完全掌握在自己手里不依赖任何第三方云服务。这篇文章适合对隐私敏感、喜欢折腾、或者单纯不想把几十个账号密码交给别人的读者从原理到实操一次性讲透。1. 为什么密码管理器最终都会走向自托管1.1 云密码管理器的三个无法回避的隐患我最早用的是某大厂的云密码管理器用起来确实方便浏览器插件一点就填。但用着用着心里总不踏实尤其是看了几次安全通告之后。第一个隐患是服务端一旦被攻破哪怕数据是加密存储的别人拿到的也是你全部密码的密文配合弱主密码或离线字典攻击结果很难说。第二个隐患是同步通道不可控你并不知道自己的密码库在传输过程中经过了哪些节点虽然理论上 TLS 加密能保证传输安全但信任链的底层终究是一家商业公司。第三个隐患是厂商锁死遇到使用体验下降、免费额度缩水、甚至服务停摆迁移成本非常高。国内外的云服务都有过关闭密码管理业务的历史数据导出倒是给你但几十个站点的账密一个个重新导入烦都烦死。自托管直接把这三大隐患全部拆掉。密码库只存在于你自己的设备上同步也走你自己的网络或者你控制的域名。密码库文件本身加密对方即使拿到硬盘文件也解不开。厂商锁死更不存在因为厂商就是你自己想换环境备份文件拖走就是。可以说密码管理器这个品类天然适合自托管。1.2 自托管到底解决了什么很多人对自托管有个误解觉得就是把软件装在自己电脑上而已。实际上自托管解决的核心问题不是装在哪儿而是数据主权和信任边界。密码这种极度敏感的数据最怕的就是多一层中间人。自己托管之后加密、存储、传输三个环节都能做到完全闭环。尤其是那些对合规有要求、或者单纯不想让密码出现在别人数据库里的用户自托管几乎是唯一选择。另一个经常被忽略的点是隐私边界。云密码管理器声称不读取你的密码因为加密在本地完成。但服务端仍然能掌握你的元数据你注册了哪些网站、多久改一次密码、从哪个 IP 登录。这些元数据给到大数据分析能拼凑出非常精细的个人画像。自托管把这些也一并收回到自己手里整个软件栈都是开源的日志自己看审计自己来彻底告别黑盒。1.3 为什么偏偏是极空间我用过的 NAS 不止一台最终把密码管理器跑在极空间上有几个很实际的原因。极空间的操作系统本身对 Docker 的支持非常成熟图形化界面就能管理容器、端口和存储卷比纯命令行友好太多但又保留了高级用户需要的灵活性。另一个原因是我已经有一台极空间长期开机密码管理器服务需要 7x24 小时在线单独租一台云服务器成本不低而 NAS 本来就是常年开着的顺带跑一个容器几乎不增加额外功耗。极空间的软硬件整合做得不错存储盘坏了还能自动冗余比普通 PC 当服务器稳得多。当然极空间不是唯一选择群晖、威联通、甚至一台树莓派都能跑。但如果你已经有极空间那这趟车就非常值得上不需要额外买设备不需要注册新域名就能通过内网穿透方式访问数据加上极空间自带的备份功能完全能当一个小型私有云来用。2. password-XL 到底是个什么项目2.1 项目定位与核心功能password-XL 是一个面向个人和家庭用户的开源密码管理器服务端设计之初就瞄准了轻量、安全、易部署三个目标。它把密码库的存储与同步服务打包成一个独立的 Docker 镜像你可以把它安装在任意支持 Docker 的设备上包括极空间 NAS。部署完成后通过浏览器访问 Web 端就能完成密码库的创建、分类、条目管理和自动填充。核心功能上password-XL 覆盖了密码管理器的全部刚需。密码条目支持自定义字段比如登录地址、用户名、密码、TOTP 动态验证码、备注等等。密码生成器可以指定长度、字符集、是否排除歧义字符。组织功能允许你把条目按文件夹或标签分组后续还可以通过分享功能把某个密码安全地共享给家人或同事。最关键的是它提供了一整套客户端生态包括 Web 界面、浏览器插件、以及 iOS/Android 移动端多端数据通过自托管服务自动同步体验上和商业密码管理器几乎无差别。用一句白话总结password-XL 就是你自己当服务商的密码管理器它能做到的就是让你在密码管理上彻底自主可控。2.2 技术选型与安全设计从部署层面看password-XL 的镜像做得比较克制只有一个主服务容器数据库默认使用文件型 SQLite零外部依赖对 NAS 这种资源有限的设备非常友好。这种设计意味着你不需要额外部署 Redis、PostgreSQL 等依赖组件拉一个镜像起来就完事儿极大降低了维护成本。安全设计上密码库的加密依旧在客户端完成。也就是说你在浏览器插件或者手机 App 里保存密码时数据先在本地用主密码派生出的密钥加密再把密文上传到服务端。服务端保存的所有数据都是密文即使是部署者自己在没有主密码的情况下也看不到里面的内容。这套零知识架构是目前密码管理器的主流方案password-XL 完整地继承了下来所以部署在自己手里并不等于自己能看到所有密码心里有数就好。传输层面password-XL 支持标准 HTTPS部署时我们可以通过反向代理给它加上证书。本地局域网内使用可以不做强制 HTTPS但为了远程访问的账密安全我强烈建议开启 HTTPS。数据库层面SQLite 文件可以通过极空间的存储空间映射到机械硬盘上配合极空间自带的备份功能实现定期快照。2.3 与主流密码管理器的异同可能有人会问直接用 Bitwarden 或 Vaultwarden 不就行了为什么选 password-XL这两者的逻辑不太一样。Bitwarden 是商业公司的开源产品生态成熟但官方服务端镜像偏重对 NAS 部署不算特别友好。Vaultwarden 虽然是社区适配版但毕竟是在逆向兼容 Bitwarden 协议很多细节要自己调。password-XL 从第一天起就是按照自托管优先来设计的没有历史包袱镜像大小更小配置项更直观尤其适合第一次接触自托管的用户。当然password-XL 在生态广度上暂时比不过那些老牌项目浏览器插件的界面比较朴素移动端的功能也在持续迭代。但它的核心稳定性很强数据格式是标准加密 JSON字段结构开放即使以后要迁移到其他密码管理器也能通过导出来平滑切换。对我来说够用 顺手 完全可控 比 功能繁多 但运行环境复杂 更有吸引力。3. 极空间上部署 password-XL 的完整实操3.1 部署前的三件准备第一件准备是确认极空间的 Docker 功能可用。极空间系统的 Docker 管理位于应用中心或者高级设置里不同版本路径略有不同但基本都能找到容器或Docker入口。你要能够在图形界面上看到镜像、容器、存储卷这几个菜单这是部署的基础。第二件准备是规划端口和存储路径。password-XL 容器默认监听一个 HTTP 端口例如 8080我们需要把它映射到极空间主机的某个空闲端口上。为避免冲突建议先查一下极空间上已占用的端口我一般固定用 8899 作为映射端口。存储路径安排在极空间的 /data/ 目录下新建一个 password-xl 文件夹里面再建 data 子目录用来存放 SQLite 数据库文件。这样做的好处是备份时可以单独把整个目录复制出来不会污染极空间系统文件。第三件准备是安装一个 SSH 客户端。虽然极空间图形界面能完成大部分操作但编写 docker-compose 文件时还是直接通过 SSH 登录到极空间的 Linux 环境更方便。Windows 用户用 Windows Terminal 里的 PowerShell 直接 ssh root极空间IP 就行macOS 用户直接用 Terminal。如果你不想用 SSH也可以在极空间的文件管理里手工创建 compose 文件再通过 Docker 管理界面导入但 SSH 的效率高得多。3.2 我用 Docker Compose 完成部署的全程记录我在 SSH 登录极空间后先创建了一个项目目录用来集中存放 password-XL 的配置文件和数据库mkdir -p /data/password-xl/data cd /data/password-xl接着新建一个 docker-compose.yml 文件内容如下。这个版本是我在多次调整之后确定的注释部分直接放在文件里方便以后自己回看version: 3.8 services: password-xl: image: passwordxl/server:latest container_name: password-xl restart: unless-stopped ports: - 8899:8080 volumes: - /data/password-xl/data:/app/data environment: - TZAsia/Shanghai - LANGC.UTF-8 - DOMAINhttps://your.domain.com - ENABLE_SIGNUPfalse healthcheck: test: [CMD, curl, -f, http://localhost:8080/alive] interval: 30s timeout: 5s retries: 3这里有几个参数需要解释。端口映射8899:8080的含义是极空间本机的 8899 端口映射到容器内部的 8080 端口外部访问时就访问http://极空间IP:8899。卷映射/data/password-xl/data:/app/data把容器内部的数据库目录映射到宿主机这样即使容器重建数据也不会丢。restart: unless-stopped是防止极空间重启后容器不会自动恢复。ENABLE_SIGNUPfalse表示禁止开放注册因为自托管只给自己用注册接口暴露在公网等于招人来用你的服务器。写完 compose 文件后我执行了部署命令docker compose up -d第一次执行会拉取镜像视网络情况可能需要几十秒到几分钟。等容器启动后再执行docker compose ps查看状态显示 running 就说明起来了。之后访问http://极空间IP:8899能看到 password-XL 的初始化界面会要求你创建管理员账号和主密码。这一步是整个服务安全的关键主密码最好设置成 4 个随机单词加数字的组合长度至少 12 位以上这个密码用于加密整个密码库一旦遗忘没有任何找回机制。3.3 反向代理与 HTTPS 配置密码管理器的流量不该裸奔尤其当你希望通过外网访问的时候。我的做法是在极空间上用内置的反向代理能力或者再加一个 Nginx 容器把your.domain.com的 443 端口流量转发到本机的 8899 端口。由于极空间本身支持申请免费 SSL 证书我直接在系统设置里配置了域名和证书然后在反向代理规则里指定来源域名 your.domain.com目标地址 127.0.0.1:8899。这样外部访问https://your.domain.com时流量首先通过 TLS 加密再由极空间转发给 password-XL 容器。配置完成后需要回头改一下 docker-compose.yml 里的环境变量把 DOMAIN 更新成实际的域名并重建容器让配置生效docker compose up -d --force-recreate这一步不能省。password-XL 会根据 DOMAIN 生成一些固定的链接和 WebSocket 地址如果客户端连接时发现地址对不上会出现能登录却无法同步的问题。我一开始就吃过这个亏在局域网内用 IP 地址部署的后来切到域名时忘记改 DOMAIN搞了半天最后重建容器才解决。3.4 数据持久化与备份策略自托管密码管理器最怕的就是服务器硬盘挂了。极空间本身有 RAID 或 zdr 机制能够降低硬盘故障导致的数据丢失风险但密码库文件最好还要再做一个异地备份。我的备份策略是两重第一重是利用极空间的备份工具把/data/password-xl/data这个目录定时备份到极空间内置的另一块存储池或者外接硬盘第二重是每天凌晨通过 cron 脚本把 SQLite 文件用 pgp 加密后打包上传到私有网盘。具体加密步骤也很简单。SQLite 文件处于写入状态时直接复制可能会导致不一致所以备份前先创建一个快照。我写了一个极简的脚本放在/data/password-xl/backup.sh里#!/bin/bash BACKUP_DIR/data/password-xl/data STAMP$(date %Y%m%d%H%M%S) cp $BACKUP_DIR/db.sqlite3 /backups/db-$STAMP.sqlite3 gpg --yes --batch --recipient myemail.com --output /backups/db-$STAMP.sqlite3.gpg /backups/db-$STAMP.sqlite3 rm /backups/db-$STAMP.sqlite3加密备份的原因很简单即使备份文件泄露没有 GPG 私钥和主密码谁也解不开密码库。如果你不想用 GPG也可以直接依赖极空间的加密备份功能但我的经验是多一道加密心里踏实。恢复的时候只需把备份文件解密后放回/data/password-xl/data/db.sqlite3再重启容器即可。4. 把密码库用起来客户端接入与日常使用4.1 Web 端初始化容器起来之后第一次访问 Web 界面先要初始化管理员账户。这个账户不是密码库本身而是用来登录 password-XL 管理界面的管理员身份。初始化后会引导你创建一个密码库这个密码库才是真正存放密码条目的容器密库的主密码与管理员密码可以是同一个也可以不同但为了减少记忆负担大多数人都设成一样。我建议还是分开管理员密码用来管理服务配置主密码用来加密密码库两者权限边界更清晰。完成密库创建后界面会给你一串恢复密钥这串密钥非常重要。恢复密钥相当于主密码的备用救生圈如果哪天你忘了主密码可以通过恢复密钥重新导出密码库的加密内容但要解密仍然需要原主密码所以恢复密钥更多是防止服务端数据损坏而不是忘记主密码。把它打印出来或者存到离线的地方不要和主密码放在一起。4.2 浏览器插件与移动端接入这是 password-XL 比较出彩的地方。在浏览器扩展商店里搜索password-XL安装后打开设置填入你的服务端地址和账户信息插件会自动同步密码库。之后在任意网站登录页按一下快捷键插件就能自动填充账密。填充背后依赖的是前端本地解密插件获取加密密文后在用主密码派生出的密钥在本地解密再自动输入到网页字段中。这个过程中浏览器插件在内存中保留的明文时间非常短使用完毕会立即消除。移动端接入时需要留意证书信任问题。如果你没有走反向代理、而是直接通过 IP 访问手机 App 会报证书无效。我的建议是无论如何都配好 HTTPS 域名家庭网络里可以配一个本地 DNS 解析把内网域名指向极空间 IP这样无论在内外网都能用同一个域名访问手机上也不用额外导入自签名证书。移动端支持指纹解锁指纹验证通过后 App 才会向内存中导入主密码体验上基本跟商业密码管理器持平。4.3 导入旧密码库如果你是从其他密码管理器迁移过来导入流程比较重要。password-XL 支持 CSV 导入格式要求比较宽松通常从旧服务导出的 CSV 都能直接映射。我自己从 Chrome 导出的密码 CSV 有几百行导入时在字段映射界面把网址、用户名、密码三列对应好即可。导入过程不会对旧文件做任何修改即使映射错误也只需要重新导入一次。需要注意的是密码库导入前最好先创建好文件夹分类不然几百个条目全部堆在未分类里后期整理非常费劲。我的习惯是导入之前先建好工作、生活、金融、娱乐几个文件夹导入后在 Web 界面上批量勾选条目拖动归组几分钟就能搞定。导入完成之后记得清空旧浏览器里的密码记录避免出现两套密码库的混乱。5. 常见问题与排查技巧实录5.1 部署阶段的高频报错我实际部署时遇到的第一类问题是镜像拉取超时。极空间所在的网络环境拉取 Docker Hub 镜像有时候极慢甚至卡住。解决办法是给极空间配置一个可用的镜像加速地址这个可以在 Docker 管理界面的设置里填。如果你不方便使用加速地址还有一个偏方是找一台网络条件好的机器先把镜像导出 tar 包再导到极空间上手动加载但操作麻烦非万不得已不推荐。第二类问题是端口被占用。极空间的某些服务会占用 8080 等常见端口如果 compose 里书写的映射端口已经被占用容器会一直处于 restarting 状态。排查思路是先docker ps -a查看容器状态再用ss -lntp | grep 8899查看端口占用情况。我的习惯是尽量用 8000 以上的稀有端口同时避免使用 NAS 管理界面的默认端口段。第三类问题是容器启动了但网页打不开。此时先确认容器日志执行docker logs password-xl看到Listening on 8080说明容器本身正常。然后检查极空间防火墙是否放行了宿主机映射出来的端口部分极空间版本会默认拦截非系统应用端口。放行后一般就能正常访问。5.2 日常使用中的诡异问题用了两三个月后我最容易遇到的是同步冲突。手机端在弱网环境下修改了一条密码但没及时同步随后电脑端也修改了同一条两边就会产生冲突。password-XL 的解决策略是保留修改时间较晚的版本并生成一条冲突备份内容。遇到这种情况不用慌在 Web 端找到该条目的历史记录把想要保留的内容恢复即可。另一个经常被忽视的问题是时区设定。如果容器环境变量里没有正确配置 TZAsia/Shanghai数据库内密码条目的修改时间就会和本地时间相差 8 个小时导致排序和同步判断出现微妙偏差。所以 compose 文件里必须带上时区配置这是我第一次部署时就踩过的坑。如果你同时开启了极空间自带的下载服务和媒体服务要注意这些服务对带宽的抢占。当内网有人做大量下载时password-XL 的同步速度会明显变慢。解决方案很简单把某个常用的客户端设为离线模式优先只有手动点击同步时才走网络能有效规避带宽挤占问题。5.3 安全加固必须做的几件事容器起来能用了不代表万事大吉。安全永远是动态过程。我的密码管理器部署完成之后做了以下五件事每一件都很重要。第一关闭了服务端注册功能。我在 compose 文件里把ENABLE_SIGNUP设成了 false否则一旦服务地址泄漏任何人都可以注册并创建自己的密码库白白占用你的计算资源和带宽。第二为主密码库开启两步验证。password-XL 支持在登录时校验 TOTP 验证码与密码管理器的主密码形成双因子这样即便主密码被钓鱼攻击者也进不了你的密码库。第三定时更新镜像。我每个月会检查一次 password-XL 的镜像是否有新版本执行docker compose pull docker compose up -d完成升级确保服务端漏洞得到修复。第四限制管理后台的访问来源。可以借助极空间的防火墙把管理后台的端口访问权限限定在家庭或办公网段。第五定期审计密码库。我每三个月会用 Web 端自带的弱密码检测功能扫一遍把重复使用的密码、暴露密码及时替换掉。自托管给了你完全的控制权但也不意味着就可以偷懒该做的保养一样不能少。写在最后的个人体会折腾过自托管密码管理器之后我最大的感受是掌控感带来的安心远大于技术实现的快感。现在我的所有密码只存放在两台设备上一台极空间作为服务端一台移动硬盘作为加密备份。出差时通过 HTTPS 域名访问在家时走局域网直连整个过程没有第三方介入心里踏实。如果你也想试着把密码管理器私有化记住一点不要追求一步到位先把最基本的主密码设置好、把数据库备份脚本跑通之后再慢慢加域名、加双因子、加自动更新。密码服务的底线不是功能多少而是数据在你手里。