剪藏#剪藏

自建vaultwarden,实现自动同步与镜像更新 - 文档共建 - LINUX DO

2025 年 5 月 6 日1 分钟
分享Twitter / XTelegram微博

在ChatGPT的辅助下完成了自建vaultwarden,多次修改后终于有个能用的了,具体操作有:

  • 容器采用目录挂载方式启动,这样方便备份和更新

  • 保留90天备份,将整个挂载目录压缩加密备份,每天5点自动备份到onedrive

  • 备份使用GPG加密存储

  • 其实本地密码文件本身是加密存储的,但是配置文件会泄露一点信息,故我再次加密

  • 每天自动检测vaultwarden镜像是否有更新,有的话自动更新并启动(有佬推荐使用watchower自动更新镜像)

  • 实现这些需要的:

  • 一台vps

  • 一个域名,这个域名解析到你的vps上, 本文假设域名为 my.com

  • 服务器或VPS挂了怎么办:

  • vaultwarden支持离线使用,密码在本地会存一份,即使bitwarden插件现在连不上VPS也可以继续使用密码

  • 本地存的那份密码可以导出

  • bitwarden官方不是有自己的镜像吗? 为什么要使用vaultwarden?

  • bitwarden官方占用比vaultwarden大,如果你的VPS空间紧张,那vaultwarden很适合你

目录结构

为组织脚本和相关文件,建议使用以下目录结构:

JAVASCRIPT
/vaultwarden_backup/

├── admin_token_hash
├── backup  
│   ├── backup_2024-10-19.tar.gz.gpg
│   ├── backup_2024-10-20.tar.gz.gpg
│   ├── backup_2024-10-21.tar.gz.gpg
│   ├── backup_2024-10-22.tar.gz.gpg
│   └── backup_2024-10-24.tar.gz.gpg
├── backup.log
├── backup_update_script.sh
└── gpg_passphrase_file

admin_token_hash 保存 Vaultwarden 后台密码 Hash
backup 存放每天自动备份文件
backup.log 存放脚本 backup_update_script.sh 执行时输出的日志
backup_update_script.sh 自动备份和镜像更新脚本
gpg_passphrase_file GPG 加密文件

环境准备

1. 必要工具

确保您的系统已经安装以下工具:

  • Docker:用于运行 Vaultwarden。

  • Rclone:用于将备份文件上传到 OneDrive。

  • GPG:用于加密备份文件。

  • Argon2:用于生成 ADMIN_TOKEN 的哈希值。

  • Cron:用于定时执行备份和更新脚本。

JAVASCRIPT
sudo apt update
sudo apt install docker.io rclone gpg argon2 
sudo systemctl start docker 
sudo systemctl enable docker

在远程Linux服务器上安装并配置rclone``(配置rclone流程我记不清了,这个是我找的)

1 安装rclone

如果你的Linux服务器还没有安装rclone,可以按照以下步骤安装:

  1. 通过SSH连接到你的远程Linux服务器。

  2. 运行以下命令来下载并安装rclonecurl https://rclone.org/install.sh | ``sudo`` bash

  3. 安装完成后,可以通过以下命令确认安装是否成功:rclone version

2 初始化rclone配置

  1. 运行rclone config命令启动配置过程:rclone config

  2. 输入n来创建一个新的remote。

  3. 输入remote的名称(例如onedrive

  4. 继续按提示操作,直到要求进行OAuth认证的步骤。

在这一步,通常rclone会自动打开浏览器来完成OAuth认证,但由于我们是在远程服务器上,这就需要在本地的Windows机器上进行认证。

在本地Windows机器上完成OAuth认证

1 获取认证URL

  1. rclone提示你需要在浏览器中打开一个URL来完成认证时,它会输出一个类似于下面的链接:https://accounts.google.com/o/oauth2/auth?client_id=XXXXXXX&response_type=code&scope=XXXXX

  2. 复制这个链接,你需要将它复制到本地的机器。

2 在Windows机器上打开浏览器并完成认证

  1. 在本地Windows电脑上,打开浏览器,并粘贴刚才从远程服务器上复制的OAuth认证URL。

  2. 按照浏览器中的指示进行登录,并授权rclone访问你的云存储账户。

  3. 完成认证后,浏览器将返回一个包含认证代码的页面。这时候会显示一段长的代码。

3 将认证代码粘贴回远程Linux服务器

  1. 复制认证完成后页面中显示的授权代码。

  2. 回到你连接远程Linux服务器的终端,在rclone提示你输入认证代码的地方,粘贴该代码并按回车。

完成rclone配置

  1. 继续完成后续的配置。通常是选择默认值(除非你有其他自定义需求),然后保存并退出。

  2. 你可以通过以下命令测试配置是否成功(以Google Drive为例):rclone lsd onedrive:vaultwarden_backup 如果能够列出你的云存储目录结构,说明配置成功。 如果目录不存在,可以手动创建:rclone ``mkdir`` onedrive:vaultwarden_backup

配置GPG

1:生成一个随机密码

我们可以使用 opensslpwgen 生成一个强密码:

JAVASCRIPT
# 使用 openssl 生成随机密码
openssl rand -base64 32 > /vaultwarden_backup/gpg_passphrase_file

# 确保文件权限是 600
chmod 600 /vaultwarden_backup/gpg_passphrase_file

这样会在 /vaultwarden_backup/gpg_passphrase_file 中生成一个 32 字节的随机密码,并设置为仅当前用户可读。

2:安装 GPG

如果你的系统上还没有 GPG,请进行安装:

JAVASCRIPT
sudo apt update
sudo apt install gnupg -y

3:使用 GPG 创建加密测试文件

你可以测试一下这个 GPG 密码文件是否正常工作:

JAVASCRIPT
# 读取生成的密码到变量
GPG_PASSPHRASE=$(< /vaultwarden_backup/gpg_passphrase_file)

# 创建一个测试文件
echo "This is a test backup file." > test_file.txt

# 使用 GPG 加密测试文件
gpg --batch --yes --symmetric --cipher-algo AES256 --passphrase "$GPG_PASSPHRASE" -o test_file.txt.gpg test_file.txt

# 检查是否生成了加密文件
ls test_file.txt.gpg

4:解密文件测试

确保可以使用相同的密码文件解密:

JAVASCRIPT
# 解密文件
gpg --batch --yes --passphrase "$GPG_PASSPHRASE" -o decrypted_test_file.txt -d test_file.txt.gpg

# 检查解密结果
cat decrypted_test_file.txt

5:清理测试文件

如果一切正常,可以删除测试文件:

JAVASCRIPT
rm test_file.txt test_file.txt.gpg decrypted_test_file.txt

注意事项

  1. 文件权限:确保 /vaultwarden_backup/gpg_passphrase_file 的权限是 600,以保证安全:chmod`` 600 /vaultwarden_backup/gpg_passphrase_file

  2. 备份密码文件:将该密码文件妥善保存(例如在安全的地方备份),因为如果丢失,将无法解密备份文件。可以存到onedrive的保险库中.

生成 ADMIN_TOKEN 的哈希值

Vaultwarden 官方推荐使用 argon2 生成 ADMIN_TOKEN 的哈希值。请按照以下步骤操作:

生成哈希值并保存

使用以下命令生成 ADMIN_TOKEN 的哈希值,并将其保存到 /vaultwarden_backup/admin_token_hash 文件中:

JAVASCRIPT
# 替换 "123456789" 为您实际的管理员密码
echo -n "123456789" | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4 > /vaultwarden_backup/admin_token_hash

# 设置文件权限,确保只有授权用户可以读取
sudo chmod 600 /vaultwarden_backup/admin_token_hash

示例输出(保存在 /vaultwarden_backup/admin_token_hash 文件中):

JAVASCRIPT
$argon2id$v=19$m=65540,t=3,p=4$bXBGMENBZUVzT3VUSFErTzQzK25Jck1BN2Z0amFuWjdSdVlIQVZqYzAzYz0$T9m73OdD2mz9+aJKLuOAdbvoARdaKxtOZ+jZcSL9/N0

注意:将 "123456789" 替换为您的实际管理员密码,确保密码足够强壮。

备份和镜像更新脚本

1. 设置备份目录和权限

确保备份目录存在,并设置正确的权限:

JAVASCRIPT
sudo mkdir -p /vaultwarden_backup
sudo chmod -R 700 /vaultwarden_backup

2. 完整备份与更新脚本

将以下脚本保存为 /vaultwarden_backup/backup_update_script.sh,并赋予可执行权限。

JAVASCRIPT
#!/bin/bash

# ================== 配置部分 ==================

BACKUP_DIR="/vaultwarden_backup/backup"       # 本地备份存储路径
SOURCE_DIR="/VM_data"                         # 需要备份的源目录
REMOTE="onedrive:vaultwarden_backup"          # rclone 远程 OneDrive 目录
DATE=$(date +"%Y-%m-%d")                      # 当前日期
BACKUP_FILE="backup_$DATE.tar.gz"             # 备份文件名
GPG_FILE="$BACKUP_FILE.gpg"                   # 加密后的备份文件名
GPG_PASSPHRASE_FILE="/vaultwarden_backup/gpg_passphrase_file"   # GPG 加密密码文件
RETENTION_DAYS=90                             # 保留的天数
LOG_FILE="/vaultwarden_backup/backup_update_script.log"         # 日志文件

# Docker 配置
IMAGE_NAME="vaultwarden/server:latest"        # 镜像名称
CONTAINER_NAME="vaultwarden"                  # 容器名称

# 日志函数
log() {
    echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" | tee -a $LOG_FILE
}

# 检查 GPG 密码文件是否存在
if [ ! -f "$GPG_PASSPHRASE_FILE" ]; then
    log "GPG 密码文件不存在,备份终止"
    exit 1
fi

# 读取 GPG 密码
GPG_PASSPHRASE=$(< "$GPG_PASSPHRASE_FILE")

# 创建备份
log "开始备份"
if tar -czf "$BACKUP_DIR/$BACKUP_FILE" -C "$SOURCE_DIR" .; then
    log "备份文件已创建: $BACKUP_FILE"
else
    log "备份失败"
    exit 1
fi

# GPG 加密
if gpg --batch --yes --passphrase "$GPG_PASSPHRASE" -c "$BACKUP_DIR/$BACKUP_FILE"; then
    log "备份文件已加密: $GPG_FILE"
else
    log "加密失败,备份终止"
    exit 1
fi

# 删除未加密的文件
rm "$BACKUP_DIR/$BACKUP_FILE"
log "未加密的备份文件已删除"

# 同步到 OneDrive
if rclone copy "$BACKUP_DIR/$GPG_FILE" "$REMOTE"; then
    log "已同步到 OneDrive: $GPG_FILE"
else
    log "同步到 OneDrive 失败"
    exit 1
fi

# 清理本地和远程超过保留期的备份
find "$BACKUP_DIR" -name "backup_*.tar.gz.gpg" -type f -mtime +$RETENTION_DAYS -delete
rclone delete --min-age ${RETENTION_DAYS}d "$REMOTE"
log "超过 $RETENTION_DAYS 天的旧备份已删除"

log "备份完成"


# ================== Docker 镜像更新 ==================

log "开始检查 Docker 镜像更新"

# 拉取最新镜像
if docker pull $IMAGE_NAME; then
    log "拉取最新镜像成功: $IMAGE_NAME"
else
    log "拉取镜像失败"
    exit 1
fi

# 获取最新镜像的 ID
LATEST_IMAGE_ID=$(docker inspect --format='{{.Id}}' $IMAGE_NAME)

# 获取当前运行容器的镜像 ID
CURRENT_IMAGE_I
JAVASCRIPT
D=$(docker inspect --format='{{.Image}}' $CONTAINER_NAME)

# 检查是否有更新
if [ "$LATEST_IMAGE_ID" != "$CURRENT_IMAGE_ID" ]; then
    log "有新镜像,更新容器..."

    # 停止并移除旧容器
    if docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME; then
        log "旧容器已停止并移除"
    else
        log "停止或移除旧容器失败"
        exit 1
    fi

    # 重新启动容器
    if docker run -d --name $CONTAINER_NAME \
        -v /VM_data:/data \
        -e ADMIN_TOKEN="$(cat /vaultwarden_backup/admin_token_hash)" \
        -e INVITATIONS_ALLOWED=false \
        -p 80:80 \
        --restart unless-stopped \
        $IMAGE_NAME; then
        log "容器已更新并重新启动"
    else
        log "容器启动失败"
        exit 1
    fi
else
    log "镜像没有更新,不执行操作"
fi

log "Docker 镜像检查完成"

3. 设置脚本执行权限

确保脚本具有可执行权限,并设置正确的所有者和权限:

JAVASCRIPT
sudo chmod +x /vaultwarden_backup/backup_update_script.sh
sudo chown your_backup_user:your_backup_group /vaultwarden_backup/backup_update_script.sh

注意:将 your_backup_useryour_backup_group 替换为实际的用户和组,确保只有授权用户可以执行和修改脚本。我使用的是chown vaultwarden:vaultwarden /vaultwarden_backup/backup_update_script.sh

4. 配置定时任务(Cron)

使用 cron 定期执行备份和更新脚本。以下示例将脚本设置为每天凌晨2点执行。

  1. 编辑 Crontabsudo`` crontab -e

  2. 添加以下行# 每天凌晨5点执行备份与更新脚本 0 5 * * * /vaultwarden_backup/backup_update_script.sh >> /vaultwarden_backup/backup.log 2>&1

  3. 保存并退出

5. 验证脚本

在首次运行脚本之前,建议手动执行一次以确保一切正常:

JAVASCRIPT
sudo /vaultwarden_backup/backup_update_script.sh

检查日志文件 /vaultwarden_backup/backup.log 以确保所有步骤顺利完成。

bitwarden配置

1. 选自托管

2. 填解析到这个vps的域名

3. 注册第一个用户,第一个注册用户就是管理员

4. 进入后台管理,关闭新用户注册,因为这只是我们自己用

后台网址为 https://域名/admin, 这里密码填上面使用 argon2中的密码(例子中为123456789)

安全提示

  • 密码安全:确保 /vaultwarden_backup/gpg_passphrase_file/vaultwarden_backup/admin_token_hash 文件的权限为 600,且仅限授权用户访问。

  • 脚本权限:确保脚本拥有适当的执行权限,并且只有授权用户可以修改。

  • 定期检查:定期检查备份日志,确保备份和更新过程正常运行。

  • 套CDN: 给解析到VPS的域名套上CDN,防止泄露VPSIP,这个可以在Cloudcone中打开

  • 开防火墙: 注意放行443和80端口

至此,已经结束,下面都是一些佬推荐的,不属于上面教程的一部分,感兴趣的可以看看

其他佬倾情推荐

docker compose一把梭, 注意他使用的是alpine系统镜像

JAVASCRIPT
services:

  vault:
    image: vaultwarden/server:alpine
    container_name: vault
    network_mode: host
    restart: always
    volumes: [ "./data/:/data" ]
    environment:
      # Vault
      - DOMAIN=https://vault.xxx.com
      - SIGNUPS_ALLOWED=false
      - SIGNUPS_VERIFY=true
      - INVITATIONS_ALLOWED=false
      # Rocket
      - ROCKET_ADDRESS=127.0.0.1
      - ROCKET_PORT=3018
      # Websocket
      - WEBSOCKET_ENABLED=true
      - WEBSOCKET_ADDRESS=127.0.0.1
      - WEBSOCKET_PORT=3019
      # SMTP
      - SMTP_HOST=smtp.gmail.com
      - SMTP_PORT=587
      - SMTP_SECURITY=starttls
      - SMTP_FROM=xxx@gmail.com
      - SMTP_USERNAME=xxx@gmail.com
      - SMTP_PASSWORD=xxx

原文地址: https://linux.do/t/topic/241010

相关文章