# Vaultwarden 部署指南

Bitwarden 兼容的自托管密码管理器，轻量、安全、功能完整。

## 功能特性

- 完全兼容 Bitwarden 官方客户端（浏览器插件、桌面端、移动端）
- 密码、笔记、信用卡、身份信息安全存储
- TOTP 两步验证码生成
- 密码分享（Send 功能）
- 组织与多用户协作
- 管理员面板
- 轻量级：使用 SQLite，单容器约 50MB 内存

## 技术栈

| 组件 | 版本 | 说明 |
|------|------|------|
| Vaultwarden | latest | Bitwarden 兼容服务端（Rust 实现） |
| SQLite | 内置 | 轻量数据库，无需额外部署 |
| Nginx | 系统包 | 反向代理 + HTTPS（Bitwarden 客户端必须 HTTPS） |
| Docker | 最新版 | 容器运行环境 |

## 前置条件

1. 一台 Linux 服务器（Ubuntu 22.04/24.04 推荐）
2. 一个已解析到服务器的域名（如 `vault.example.com`）
3. 服务器 80/443 端口可从外网访问
4. **必须启用 HTTPS**（Bitwarden 客户端强制要求）

## 目录结构

```
vaultwarden/
├── docker-compose.yml    # 容器编排
├── .env.example          # 配置模板
├── deploy.sh             # 一键部署脚本
├── backup.sh             # 备份脚本
├── uninstall.sh          # 完全卸载脚本
├── nginx/
│   └── vaultwarden.conf  # Nginx 反向代理配置
└── README.md             # 本文件
```

服务器上的数据目录：

```
/var/lib/vaultwarden/     # Vaultwarden 数据（SQLite + 附件 + RSA 密钥）
/var/backups/vaultwarden/ # 备份文件
```

## 快速部署

### 第一步：上传文件到服务器

```bash
# 在本地执行，上传 vaultwarden 目录
scp -r vaultwarden/ root@<服务器IP>:/opt/vaultwarden

# 如果服务器上还没有部署过 base（首台服务或全新服务器），还需上传 base
scp -r base/ root@<服务器IP>:/opt/base
```

### 第二步：登录服务器执行部署

```bash
ssh root@<服务器IP>

# 如果是全新服务器，先安装基础环境
cd /opt/base
cp .env.example .env
bash setup.sh

# 部署 Vaultwarden
cd /opt/vaultwarden
bash deploy.sh
# 首次运行会生成 .env（含自动生成的 ADMIN_TOKEN），按提示修改后重新运行
vi .env
bash deploy.sh
```

### 第三步：配置域名解析

在域名服务商添加 A 记录：

| 记录类型 | 主机记录 | 记录值 |
|----------|----------|--------|
| A | vault | `<服务器公网IP>` |

### 第四步：注册账号

1. 浏览器访问 `https://vault.yourdomain.com`
2. 点击「创建账户」注册一个主账号
3. 注册完成后，**强烈建议关闭注册功能**：

```bash
cd /opt/vaultwarden
# 编辑 .env，将 SIGNUPS_ALLOWED 改为 false
vi .env
docker compose restart
```

### 第五步：安装客户端

1. 下载 Bitwarden 客户端：https://bitwarden.com/download/
2. 打开客户端，点击左上角齿轮图标
3. 在「自托管服务器」中填入服务器 URL：`https://vault.yourdomain.com`
4. 保存后使用注册的账号登录

## 配置说明

### .env 配置项

| 变量 | 说明 | 默认值 |
|------|------|--------|
| `VAULTWARDEN_DOMAIN` | 访问域名 | 必填 |
| `CERTBOT_EMAIL` | Let's Encrypt 邮箱 | 必填 |
| `ADMIN_TOKEN` | 管理员面板令牌 | 自动生成 |
| `SIGNUPS_ALLOWED` | 允许新用户注册 | `true` |
| `SHOW_PASSWORD_HINT` | 显示密码提示 | `false` |
| `SENDS_ALLOWED` | 允许 Send 功能 | `true` |
| `VAULTWARDEN_IMAGE` | Docker 镜像 | `vaultwarden/server:latest` |
| `VAULTWARDEN_DATA_DIR` | 数据目录 | `/var/lib/vaultwarden` |
| `VAULTWARDEN_PORT` | 本地监听端口 | `8080` |
| `BACKUP_DIR` | 备份目录 | `/var/backups/vaultwarden` |
| `LOG_LEVEL` | 日志级别 | `info` |

### 管理员面板

访问 `https://vault.yourdomain.com/admin`，输入 `ADMIN_TOKEN` 中的明文令牌即可登录。

管理员面板可以：
- 查看所有用户
- 邀请新用户（关闭注册后）
- 删除用户
- 查看系统诊断信息
- 调整运行时配置

> **安全提醒**：可在 Nginx 配置中限制 `/admin` 路径仅允许特定 IP 访问。

### 使用 argon2id 加强 ADMIN_TOKEN 安全性

部署脚本默认生成随机字符串作为 ADMIN_TOKEN。如需使用更安全的 argon2id 哈希：

```bash
# 生成 argon2id 哈希（使用 Bitwarden 默认参数: m=64MiB, t=3, p=4）
docker run --rm -it vaultwarden/server /vaultwarden hash

# 或使用 OWASP 推荐参数（m=19MiB, t=2, p=1，更节省内存）
docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp
```

将生成的哈希值填入 `.env` 时，**必须用单引号包裹**（因为 argon2id 字符串包含 `$` 符号）：

```bash
# .env 中的写法（注意单引号）
ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$MmeK......'
```

> **注意**：登录管理面板时输入的是你生成哈希时使用的**原始明文密码**，不是哈希值本身。

## 日常运维

### 查看日志

```bash
cd /opt/vaultwarden
docker compose logs -f
docker compose logs --tail 100
```

### 备份

```bash
cd /opt/vaultwarden
bash backup.sh
```

备份内容包括：
- SQLite 数据库（支持在线安全备份）
- 附件和 RSA 密钥
- 部署配置

也可使用 Vaultwarden v1.32.1+ 内置备份命令：

```bash
docker exec -it vaultwarden /vaultwarden backup
```

备份文件保存在 `/var/backups/vaultwarden/`，自动清理 30 天前的旧备份。

**建议配置定时备份：**

```bash
# 每天凌晨 2 点自动备份
crontab -e
# 添加：
0 2 * * * cd /opt/vaultwarden && bash backup.sh >> /var/log/vaultwarden-backup.log 2>&1
```

### 恢复备份

```bash
cd /opt/vaultwarden
docker compose down

# 查看可用备份
ls /var/backups/vaultwarden/

# ⚠ 重要：先删除现有 WAL 文件，避免与恢复的数据库不匹配导致损坏
rm -f /var/lib/vaultwarden/db.sqlite3-wal /var/lib/vaultwarden/db.sqlite3-shm

# 恢复数据库
cp /var/backups/vaultwarden/<日期>/db.sqlite3 /var/lib/vaultwarden/

# 恢复附件
tar xzf /var/backups/vaultwarden/<日期>/vaultwarden-data.tar.gz -C /var/lib/

# 重启
docker compose up -d
```

> **警告**：恢复通过 `.backup` 方式创建的备份时，**必须先删除**现有的 `db.sqlite3-wal` 文件，否则 SQLite 会尝试用旧的 WAL 文件恢复数据库，可能导致数据损坏。

### 升级

```bash
cd /opt/vaultwarden

# 1. 备份数据
bash backup.sh

# 2. 拉取新镜像
docker compose pull

# 3. 重启
docker compose up -d

# 4. 检查运行状态
docker compose ps
docker compose logs --tail 20
```

### 停止 / 启动

```bash
cd /opt/vaultwarden
docker compose down      # 停止
docker compose up -d     # 启动
docker compose restart   # 重启
```

## 完全卸载

如果需要从服务器上完全移除 Vaultwarden，使用卸载脚本：

```bash
cd /opt/vaultwarden
bash uninstall.sh
```

脚本会**交互式确认**每个危险操作，按顺序执行：

| 步骤 | 操作 | 确认方式 |
|------|------|----------|
| 0 | 卸载前备份（可选） | y/N |
| 1 | 停止并删除 Vaultwarden 容器 | 输入 YES |
| 2 | 删除 Docker 镜像 | 自动 |
| 3 | 删除 Nginx 站点配置并重载 | 自动 |
| 4 | 删除 Let's Encrypt SSL 证书 | 自动 |
| 5 | 清理 Certbot 定时任务（仅当无其他证书时） | 自动 |
| 6 | 删除数据目录 | 输入 DELETE |
| 7 | 删除部署目录 `/opt/vaultwarden` | y/N |

**备份目录 `/var/backups/vaultwarden/` 始终保留**，不会被删除。

> 卸载后如需恢复，参考上方「恢复备份」章节。

<details>
<summary>手动卸载步骤（不使用脚本）</summary>

```bash
cd /opt/vaultwarden

# 1. 建议先备份
bash backup.sh

# 2. 停止并删除容器
docker compose down -v

# 3. 删除 Docker 镜像（可选）
docker image rm vaultwarden/server:latest

# 4. 删除 Nginx 配置
rm -f /etc/nginx/sites-enabled/vaultwarden /etc/nginx/sites-available/vaultwarden
nginx -t && systemctl reload nginx

# 5. 删除 SSL 证书
certbot delete --cert-name 你的域名

# 6. 删除数据目录（⚠ 不可恢复）
rm -rf /var/lib/vaultwarden

# 7. 删除部署目录（可选）
rm -rf /opt/vaultwarden

# 备份目录保留在 /var/backups/vaultwarden/
```

</details>

## 安全加固建议

### 1. 关闭注册

注册好所有需要的账号后：

```bash
# .env 中设置
SIGNUPS_ALLOWED=false
```

### 2. 限制管理面板访问

在 `nginx/vaultwarden.conf` 中取消注释 `/admin` 的 IP 限制部分，仅允许你的 IP 访问。

### 3. 启用两步验证

登录 Vaultwarden Web 界面 → 设置 → 两步登录 → 启用 TOTP 或其他验证方式。

### 4. 定期备份

配置定时任务，每天自动备份，并将备份文件同步到异地存储。

## 故障排查

### 客户端无法连接

```bash
# 检查 HTTPS 是否正常
curl -I https://vault.yourdomain.com

# 检查容器是否运行
docker compose ps

# 检查端口
curl http://127.0.0.1:8080/alive
```

### 502 Bad Gateway

```bash
# 容器未运行
docker compose up -d

# 检查端口是否匹配
grep VAULTWARDEN_PORT .env
grep proxy_pass /etc/nginx/sites-available/vaultwarden
```

### 管理面板无法登录

```bash
# 确认 ADMIN_TOKEN 已设置
grep ADMIN_TOKEN .env

# 如果使用 argon2id 哈希，登录时输入的是原始明文密码
# 检查容器日志中的错误
docker compose logs --tail 20
```

### SSL 证书问题

```bash
# 检查证书状态
certbot certificates

# 手动续期
certbot renew --dry-run

# 检查域名解析
dig vault.yourdomain.com
```

## 端口说明

| 端口 | 协议 | 说明 |
|------|------|------|
| 80 | TCP | HTTP → HTTPS 重定向 |
| 443 | TCP | HTTPS（Nginx 反向代理） |
| 8080 | TCP | Vaultwarden HTTP（仅监听 127.0.0.1） |
