自己搭 VaultWarden 最怕两件事:
1)数据库/附件丢了;
2)备份任务跑没跑成功你根本不知道。
这篇分享一套我亲测可用的方案:
- 本地先压缩备份(保留最近 7 份)
- 自动上传阿里云 OSS(保留最近 30 份)
- 无论成功失败都发邮件提醒(带完整日志)
环境:飞牛 FNOS / Docker / 阿里云 OSS / rclone / msmtp
目录
- 一、安装 rclone(飞牛自带)
- 二、rclone 配置对接阿里云 OSS(每一步选什么)
- 三、验证 rclone 配置是否成功
- 四、安装 msmtp(QQ 邮箱 SMTP 发信)
- 五、备份 + 上传 + 邮件提醒脚本(最终版)
- 六、定时任务/计划任务怎么跑
- 七、常见坑
一、安装 rclone(飞牛自带)
飞牛系统源里一般直接有 rclone:
apt install rclone
二、配置 rclone 对接阿里云 OSS(每一步选什么)
1)进入交互配置
rclone config
2)新建 remote
看到选项:
n) New remote</span>
s) Set configuration password</span>
q) Quit config</span>
**输入:**n
3)remote 名称
提示:name>
输入:oss
4)选择存储类型 Storage
列表很长,这里选择:
- 4 / s3(Amazon S3 兼容的,包含 Alibaba)
**输入:**4
5)选择 S3 provider
选择:
**输入:**2
6)是否从环境变量取 AK(env_auth)
提示:env_auth>
输入:1(等价于 false,表示下一步手动输入 AK/SK)
7)输入 AK / SK(RAM 子账号)
access_key_id>:填 RAM 子账号 AK
secret_access_key>:填 RAM 子账号 SK
RAM 权限建议给到 bucket 的读写删(备份上传/删除旧备份都要用)。
8)选择 endpoint(地域节点)
会列很多地域,比如北京是:
oss-cn-beijing.aliyuncs.com
这一步选择你 bucket 所在地域(北京就选 “North China 2 (Beijing)”)
**在列表里是:**6
注意:rclone 这里要填的是 Endpoint(oss-cn-beijing.aliyuncs.com),

不是 bucket 域名(bucket-xxx.oss-cn-beijing.aliyuncs.com)。
9)acl(默认对象权限)
ACL 不是账户读写权限,它是对象公开/私有属性。备份建议私有:
选择:1 / private(默认)
**输入:**1
10)storage_class(存储类型)
**选:**2 / STANDARD
**输入:**2
11)Edit advanced config?
选:n(不编辑高级)
**输入:**n
12)确认保存
看到摘要后选:Yes this is OK
**输入:**y
三、验证 rclone 配置是否成功
1)列出 bucket
rclone lsd oss:
示例输出:
# rclone lsd oss: -1 2026-02-09 10:11:38 -1 [bucket名称]
2)列 bucket 内容
rclone lsf oss:[bucket名称]
3)上传测试文件
echo test > /tmp/oss_test.txt
rclone copy /tmp/oss_test.txt oss:[bucket名称]/vw-backups/ -P
4)删除测试文件
rclone deletefile oss:[bucket名称]/vw-backups/oss_test.txt
deletefile 只能删文件,不能删目录;
如果要清空整个前缀,用 rclone delete 或 rclone purge
四、安装 msmtp(用 QQ 邮箱 SMTP 发提醒邮件)
1)安装
apt update
apt install -y msmtp msmtp-mta ca-certificates
安装时会问 Enable AppArmor support?

建议选:No
2)写配置(/etc/msmtprc)
把 [YOUR_QQ_AUTH_CODE] 12345@qq.com换成 QQ 邮箱 SMTP 授权码和你的邮箱账户(不加中括号)(不是登录密码):
cat >/etc/msmtprc <<'EOF'
defaults
auth on
tls on
tls_starttls off
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log
account qq
host smtp.qq.com
port 465
from 12345@qq.com
user 12345@qq.com
password [YOUR_QQ_AUTH_CODE]
account default : qq
EOF
chmod 600 /etc/msmtprc
3)测试发邮件
echo -e "Subject: test\n\nhello" | msmtp -t 12345@qq.com
4)查看日志
tail -n 50 /var/log/msmtp.log
看到类似:
smtpstatus=250 ... exitcode=EX_OK
说明发信成功。
五、备份 + 上传 + 邮件提醒脚本
特点:
- 停止 VaultWarden 容器保证一致性
- 本地压缩包命名:
VaultWarden-full-YYYY-MM-DD_HHMMSS.zip
- 压缩包只保留一层目录
VaultWarden/…(不带 /vol1/1000 这种长路径)
- 上传 OSS
- 本地保留最近 7 份、OSS 保留最近 30 份
- 无论成功/失败都发邮件,邮件里带完整日志
只改三个变量:MAIL_TO、MAIL_FROM、REMOTE_DIR
#!/usr/bin/env bash
set -euo pipefail
# ====== 邮件设置(必改) ======
MAIL_TO="666666@qq.com" # 收件人
MAIL_FROM="12345@qq.com" # 发件人:与 /etc/msmtprc from 一致
HOST_TAG="$(hostname)"
# ==============================
# ====== 备份设置 ======
SRC_DIR="/vol1/1000/SSD_Files/ProgramFiles/VaultWarden" #(此处改你的容器数据路径)
LOCAL_DIR="/vol1/1000/SSD_Files/ProgramFiles/backups/vaultwarden" #(此处改本地备份路径)
REMOTE_DIR="oss:[bucket名称]/vw-backups"
KEEP_LOCAL=7
KEEP_REMOTE=30
CONTAINER_NAME="vaultwarden" # 改为你的容器名称
# =======================
TS="$(date +%F_%H%M%S)"
ZIP_NAME="VaultWarden-full-${TS}.zip"
ZIP_PATH="${LOCAL_DIR}/${ZIP_NAME}"
mkdir -p "${LOCAL_DIR}"
# 记录日志,邮件里会带上
LOG_FILE="$(mktemp /tmp/vw-backup-${TS}.XXXX.log)"
exec > >(tee -a "$LOG_FILE") 2>&1
START_AT="$(date '+%F %T')"
UPLOAD_OK="NO"
send_report_mail() {
local status="$1" # SUCCESS / FAILED
local exit_code="$2"
local end_at="$3"
local local_cnt="$4"
local oss_cnt="$5"
local subject="[${status}] VaultWarden backup ${HOST_TAG} ${TS} (exit=${exit_code}, upload=${UPLOAD_OK})"
{
echo "From: ${MAIL_FROM}"
echo "To: ${MAIL_TO}"
echo "Subject: ${subject}"
echo "Content-Type: text/plain; charset=UTF-8"
echo
echo "Status : ${status}"
echo "Host : ${HOST_TAG}"
echo "Start : ${START_AT}"
echo "End : ${end_at}"
echo "Exit code : ${exit_code}"
echo "Upload OK : ${UPLOAD_OK}"
echo "ZIP Path : ${ZIP_PATH}"
echo "Local Keep : ${KEEP_LOCAL} (now ${local_cnt})"
echo "OSS Keep : ${KEEP_REMOTE} (now ${oss_cnt})"
echo "Remote Dir : ${REMOTE_DIR}/"
echo
echo "===== LOG BEGIN ====="
cat "$LOG_FILE"
echo "===== LOG END ====="
} | msmtp -t || true
}
on_exit() {
local exit_code=$?
local end_at
end_at="$(date '+%F %T')"
# 不管成功失败,都尽量把容器拉起来
docker start "$CONTAINER_NAME" >/dev/null 2>&1 || true
local local_cnt oss_cnt
local_cnt="$(ls -1 "${LOCAL_DIR}"/VaultWarden-full-*.zip 2>/dev/null | wc -l || true)"
oss_cnt="$(rclone lsf "${REMOTE_DIR}" --include "VaultWarden-full-*.zip" 2>/dev/null | wc -l || true)"
local status="SUCCESS"
[ "$exit_code" -ne 0 ] && status="FAILED"
send_report_mail "$status" "$exit_code" "$end_at" "$local_cnt" "$oss_cnt"
rm -f "$LOG_FILE" || true
exit "$exit_code"
}
trap on_exit EXIT
trap 'echo "[ERR] something failed, try start container..."; docker start "$CONTAINER_NAME" >/dev/null 2>&1 || true' ERR INT TERM
echo "[1/7] Stop container ${CONTAINER_NAME}..."
docker stop "${CONTAINER_NAME}"
echo "[2/7] Zip directory to local..."
PARENT_DIR="$(dirname "$SRC_DIR")"
BASE_DIR="$(basename "$SRC_DIR")"
( cd "$PARENT_DIR" && zip -9 -r -q "$ZIP_PATH" "$BASE_DIR" )
echo "[3/7] Start container ${CONTAINER_NAME}..."
docker start "${CONTAINER_NAME}"
echo "[4/7] Upload to OSS..."
rclone copy "${ZIP_PATH}" "${REMOTE_DIR}/" -P
UPLOAD_OK="YES"
echo "[5/7] Keep only latest ${KEEP_LOCAL} local backups..."
ls -1t "${LOCAL_DIR}"/VaultWarden-full-*.zip 2>/dev/null | tail -n +$((KEEP_LOCAL+1)) | xargs -r rm -f
echo "[6/7] Keep only latest ${KEEP_REMOTE} OSS backups..."
rclone lsf "${REMOTE_DIR}" --include "VaultWarden-full-*.zip" | sort | head -n -${KEEP_REMOTE} \
| while read -r f; do
[ -n "$f" ] && rclone deletefile "${REMOTE_DIR}/${f}"
done
echo "[7/7] Done. Local: ${ZIP_PATH}"
echo "Local backups count: $(ls -1 "${LOCAL_DIR}"/VaultWarden-full-*.zip 2>/dev/null | wc -l)"
echo "OSS backups count: $(rclone lsf "${REMOTE_DIR}" --include "VaultWarden-full-*.zip" | wc -l)"
六、定时任务怎么跑(飞牛任务计划)
在飞牛 应用中心 安装【任务计划】软件新增一个定时任务,Cron 例如每天 03:00:
0 3 * * *
任务内容处->把上面的脚本粘进去保存即可。建议第一次手动点“运行”测试一遍。
运行结果示例:


[1/7] Stop container vaultwarden...
vaultwarden
[2/7] Zip directory to local...
[3/7] Start container vaultwarden...
vaultwarden
[4/7] Upload to OSS...
Transferred: 2.415 MiB / 2.415 MiB, 100%, 0 B/s, ETA -
Transferred: 0 / 1, 0%
Elapsed time: 0.5s
Transferring:
* VaultWarden-full-2026-02-10_113017.zip:100% /2.415Mi, 0/s, -Transferred: 2.415 MiB / 2.415 MiB, 100%, 0 B/s, ETA -
Transferred: 1 / 1, 100%
Elapsed time: 0.6s
[5/7] Keep only latest 7 local backups...
[6/7] Keep only latest 30 OSS backups...
[7/7] Done. Local: /vol1/1000/SSD_Files/ProgramFiles/backups/vaultwarden/VaultWarden-full-2026-02-10_113017.zip
Local backups count: 4
OSS backups count: 6
七、注意事项-(定期做恢复测试)
1)endpoint 填错:要填 oss-cn-xxx.aliyuncs.com,不是 bucket 域名。
2)ACL 不是读写权限:备份建议 private;读写删权限靠 RAM 策略。
3)deletefile 不能删目录:只删对象;清空前缀用 delete/purge。
4)QQ 邮箱要用授权码:不是登录密码.
5)脚本中断容器没起来:我脚本里用 trap 尽量自动拉起容器。