12 - 备份恢复
12 - 备份恢复
建立完善的备份恢复体系:自动备份、增量备份、快照管理与灾难恢复方案。
12.1 备份策略概述
需要备份的内容
| 组件 | 路径 | 重要性 | 说明 |
|---|---|---|---|
| 数据目录 | data/ 或自定义路径 | 🔴 关键 | 用户所有文件 |
| 配置文件 | config/config.php | 🔴 关键 | 含密钥、数据库凭据 |
| 数据库 | MySQL/PostgreSQL | 🔴 关键 | 文件索引、分享、用户信息 |
| 应用目录 | apps/ | 🟡 重要 | 自安装的应用 |
| 主题目录 | themes/ | 🟡 重要 | 自定义主题 |
| SSL 证书 | /etc/letsencrypt/ | 🟢 可选 | 可重新申请 |
备份策略对比
| 策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 全量备份 | 恢复简单 | 占用空间大,耗时长 | 小规模部署 |
| 增量备份 | 节省空间,速度快 | 恢复较复杂 | 中大型部署 |
| 快照备份 | 一致性好,恢复快 | 依赖存储系统 | 虚拟化/容器环境 |
| 异地备份 | 灾难恢复 | 网络带宽需求 | 生产环境必选 |
12.2 全量备份
完整备份脚本
#!/bin/bash
# nextcloud-backup.sh - Nextcloud 全量备份脚本
set -euo pipefail
# ======== 配置 ========
BACKUP_ROOT="/backup/nextcloud"
NC_ROOT="/var/www/nextcloud"
NC_DATA="/data/nextcloud-data"
DB_TYPE="mysql"
DB_NAME="nextcloud"
DB_USER="ncuser"
DB_PASS="StrongPassword123!"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_ROOT/$DATE"
RETENTION_DAYS=30
# ======== 函数 ========
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
cleanup() {
if [ $? -ne 0 ]; then
log "ERROR: Backup failed!"
rm -rf "$BACKUP_DIR"
fi
}
trap cleanup EXIT
# ======== 开始备份 ========
log "Starting Nextcloud backup..."
# 创建备份目录
mkdir -p "$BACKUP_DIR"/{config,data,database,apps,themes}
# 1. 开启维护模式
log "Enabling maintenance mode..."
sudo -u www-data php "$NC_ROOT/occ" maintenance:mode --on
# 2. 备份配置文件
log "Backing up configuration..."
cp -a "$NC_ROOT/config/" "$BACKUP_DIR/config/"
# 3. 备份数据库
log "Backing up database..."
case "$DB_TYPE" in
mysql)
mysqldump \
--single-transaction \
--routines \
--triggers \
--quick \
--lock-tables=false \
-u "$DB_USER" \
-p"$DB_PASS" \
"$DB_NAME" | gzip > "$BACKUP_DIR/database/nextcloud.sql.gz"
;;
pgsql)
PGPASSWORD="$DB_PASS" pg_dump \
-U "$DB_USER" \
-Fc \
"$DB_NAME" > "$BACKUP_DIR/database/nextcloud.dump"
;;
esac
# 4. 备份数据目录(使用 rsync 增量同步)
log "Backing up data directory..."
rsync -a --delete \
"$NC_DATA/" "$BACKUP_DIR/data/" \
--exclude='*.part' \
--exclude='.cache'
# 5. 备份应用和主题
log "Backing up apps and themes..."
rsync -a "$NC_ROOT/apps/" "$BACKUP_DIR/apps/"
rsync -a "$NC_ROOT/themes/" "$BACKUP_DIR/themes/"
# 6. 关闭维护模式
log "Disabling maintenance mode..."
sudo -u www-data php "$NC_ROOT/occ" maintenance:mode --off
# 7. 创建备份清单
cat > "$BACKUP_DIR/manifest.txt" << EOF
Backup Date: $DATE
Nextcloud Version: $(sudo -u www-data php "$NC_ROOT/occ" status --output=json | jq -r '.version')
Database Type: $DB_TYPE
Data Directory: $NC_DATA
EOF
# 8. 压缩备份
log "Compressing backup..."
tar czf "$BACKUP_ROOT/nextcloud_$DATE.tar.gz" -C "$BACKUP_ROOT" "$DATE"
rm -rf "$BACKUP_DIR"
# 9. 清理旧备份
log "Cleaning up old backups..."
find "$BACKUP_ROOT" -name "nextcloud_*.tar.gz" -mtime +$RETENTION_DAYS -delete
# 10. 计算备份大小
BACKUP_SIZE=$(du -sh "$BACKUP_ROOT/nextcloud_$DATE.tar.gz" | cut -f1)
log "Backup completed: nextcloud_$DATE.tar.gz ($BACKUP_SIZE)"
设置定时备份
# 保存脚本
sudo cp nextcloud-backup.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/nextcloud-backup.sh
# 设置 crontab(每天凌晨 2:00)
sudo crontab -e
0 2 * * * /usr/local/bin/nextcloud-backup.sh >> /var/log/nextcloud-backup.log 2>&1
12.3 增量备份
使用 rsync 增量备份
#!/bin/bash
# nextcloud-incremental-backup.sh
BACKUP_ROOT="/backup/nextcloud"
NC_DATA="/data/nextcloud-data"
DATE=$(date +%Y%m%d)
FULL_BACKUP="$BACKUP_ROOT/full"
INCREMENTAL_DIR="$BACKUP_ROOT/incremental/$DATE"
# 创建硬链接增量备份(节省空间)
rsync -a --delete \
--link-dest="$FULL_BACKUP" \
"$NC_DATA/" "$INCREMENTAL_DIR/"
echo "Incremental backup: $INCREMENTAL_DIR"
使用 BorgBackup
# 安装 BorgBackup
sudo apt install -y borgbackup
# 初始化仓库
borg init --encryption=repokey /backup/borg-nextcloud
# 创建备份
borg create \
--stats \
--compression zstd \
/backup/borg-nextcloud::nextcloud-{now:%Y%m%d-%H%M%S} \
/var/www/nextcloud \
/data/nextcloud-data
# 列出备份
borg list /backup/borg-nextcloud
# 恢复特定备份
borg extract /backup/borg-nextcloud::nextcloud-20260510-020000
# 自动清理旧备份
borg prune \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12 \
/backup/borg-nextcloud
BorgBackup 自动备份脚本:
#!/bin/bash
# borg-nextcloud-backup.sh
export BORG_REPO="/backup/borg-nextcloud"
export BORG_PASSPHRASE="YourBorgPassword"
# 开启维护模式
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on
# 备份数据库
mysqldump -u ncuser -pStrongPassword123! nextcloud | gzip > /tmp/nextcloud-db.sql.gz
# 创建 Borg 备份
borg create --stats --compression zstd \
::nextcloud-{now:%Y%m%d-%H%M%S} \
/var/www/nextcloud \
/data/nextcloud-data \
/tmp/nextcloud-db.sql.gz
# 清理
rm /tmp/nextcloud-db.sql.gz
sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off
# 清理旧备份
borg prune --keep-daily=7 --keep-weekly=4 --keep-monthly=12
# 检查仓库完整性
borg check
12.4 快照备份
LVM 快照
# 假设数据目录在 LVM 卷 /dev/vg0/ncdata
# 创建快照(10GB 快照空间)
sudo lvcreate -s -n ncdata_snap -L 10G /dev/vg0/ncdata
# 挂载快照
sudo mkdir -p /mnt/snapshot
sudo mount /dev/vg0/ncdata_snap /mnt/snapshot
# 备份快照
tar czf /backup/ncdata_snapshot.tar.gz -C /mnt/snapshot .
# 卸载并删除快照
sudo umount /mnt/snapshot
sudo lvremove -f /dev/vg0/ncdata_snap
Btrfs 快照
# 如果数据目录在 Btrfs 分区上
# 创建快照
sudo btrfs subvolume snapshot /data/nextcloud-data /data/snapshots/ncdata-$(date +%Y%m%d)
# 列出快照
sudo btrfs subvolume list /data
# 删除旧快照
sudo btrfs subvolume delete /data/snapshots/ncdata-20260501
ZFS 快照
# 创建 ZFS 快照
sudo zfs snapshot tank/nextcloud@$(date +%Y%m%d)
# 列出快照
sudo zfs list -t snapshot
# 回滚到快照
sudo zfs rollback tank/nextcloud@20260510
# 发送快照到远程
sudo zfs send tank/nextcloud@20260510 | ssh remotehost "zfs recv backup/nextcloud"
12.5 恢复流程
全量恢复
#!/bin/bash
# nextcloud-restore.sh
set -euo pipefail
BACKUP_FILE="/backup/nextcloud/nextcloud_20260510_020000.tar.gz"
NC_ROOT="/var/www/nextcloud"
NC_DATA="/data/nextcloud-data"
DB_TYPE="mysql"
DB_NAME="nextcloud"
DB_USER="ncuser"
DB_PASS="StrongPassword123!"
echo "=== Nextcloud 恢复流程 ==="
echo "备份文件: $BACKUP_FILE"
echo ""
# 1. 解压备份
echo "1. 解压备份..."
RESTORE_DIR="/tmp/nextcloud-restore"
mkdir -p "$RESTORE_DIR"
tar xzf "$BACKUP_FILE" -C "$RESTORE_DIR"
BACKUP_DIR="$RESTORE_DIR/$(ls $RESTORE_DIR)"
# 2. 停止 Web 服务器
echo "2. 停止 Web 服务器..."
sudo systemctl stop nginx
# 3. 恢复配置文件
echo "3. 恢复配置文件..."
sudo rm -rf "$NC_ROOT/config"
sudo cp -a "$BACKUP_DIR/config/" "$NC_ROOT/config/"
# 4. 恢复数据目录
echo "4. 恢复数据目录..."
sudo rm -rf "$NC_DATA"
sudo mkdir -p "$NC_DATA"
sudo rsync -a "$BACKUP_DIR/data/" "$NC_DATA/"
# 5. 恢复应用和主题
echo "5. 恢复应用和主题..."
sudo rsync -a "$BACKUP_DIR/apps/" "$NC_ROOT/apps/"
sudo rsync -a "$BACKUP_DIR/themes/" "$NC_ROOT/themes/"
# 6. 恢复数据库
echo "6. 恢复数据库..."
case "$DB_TYPE" in
mysql)
# 删除旧数据库
mysql -u root -p"$DB_PASS" -e "DROP DATABASE IF EXISTS $DB_NAME;"
mysql -u root -p"$DB_PASS" -e "CREATE DATABASE $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
# 恢复数据库
gunzip < "$BACKUP_DIR/database/nextcloud.sql.gz" | mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"
;;
pgsql)
dropdb -U "$DB_USER" "$DB_NAME"
createdb -U "$DB_USER" -O "$DB_USER" "$DB_NAME"
PGPASSWORD="$DB_PASS" pg_restore -U "$DB_USER" -d "$DB_NAME" "$BACKUP_DIR/database/nextcloud.dump"
;;
esac
# 7. 修复权限
echo "7. 修复权限..."
sudo chown -R www-data:www-data "$NC_ROOT"
sudo chown -R www-data:www-data "$NC_DATA"
sudo chmod 750 "$NC_DATA"
# 8. 运行修复命令
echo "8. 运行修复命令..."
sudo -u www-data php "$NC_ROOT/occ" maintenance:repair
sudo -u www-data php "$NC_ROOT/occ" db:add-missing-indices
sudo -u www-data php "$NC_ROOT/occ" db:add-missing-columns
# 9. 关闭维护模式
echo "9. 关闭维护模式..."
sudo -u www-data php "$NC_ROOT/occ" maintenance:mode --off
# 10. 启动 Web 服务器
echo "10. 启动 Web 服务器..."
sudo systemctl start nginx
# 11. 扫描文件
echo "11. 扫描文件..."
sudo -u www-data php "$NC_ROOT/occ" files:scan --all
# 12. 清理临时文件
rm -rf "$RESTORE_DIR"
echo ""
echo "=== 恢复完成 ==="
12.6 异地备份
使用 rclone 同步到云存储
# 安装 rclone
curl https://rclone.org/install.sh | sudo bash
# 配置远程存储(如 S3、Backblaze B2、Google Drive 等)
rclone config
# 同步备份到远程
rclone sync /backup/nextcloud remote:nextcloud-backup/ \
--progress \
--transfers 4 \
--checkers 8
# 自动化(cron)
# 0 4 * * * rclone sync /backup/nextcloud remote:nextcloud-backup/ --log-file /var/log/rclone.log
使用 rsync 同步到远程服务器
# SSH 密钥认证
ssh-keygen -t ed25519 -f ~/.ssh/nextcloud-backup
ssh-copy-id -i ~/.ssh/nextcloud-backup backup@remote-server
# 同步备份
rsync -avz --delete \
-e "ssh -i ~/.ssh/nextcloud-backup" \
/backup/nextcloud/ \
backup@remote-server:/backup/nextcloud/
12.7 备份验证
定期恢复测试
#!/bin/bash
# backup-verify.sh - 备份验证脚本
BACKUP_FILE="$1"
VERIFY_DIR="/tmp/nextcloud-verify"
echo "验证备份文件: $BACKUP_FILE"
# 1. 检查文件完整性
echo "1. 检查文件完整性..."
if ! tar tzf "$BACKUP_FILE" > /dev/null 2>&1; then
echo "ERROR: 备份文件损坏!"
exit 1
fi
# 2. 解压并检查关键文件
echo "2. 检查关键文件..."
mkdir -p "$VERIFY_DIR"
tar xzf "$BACKUP_FILE" -C "$VERIFY_DIR"
BACKUP_DIR="$VERIFY_DIR/$(ls $VERIFY_DIR)"
# 检查必要文件
for f in config/config.php manifest.txt; do
if [ ! -f "$BACKUP_DIR/$f" ]; then
echo "ERROR: 缺少关键文件: $f"
exit 1
fi
done
# 3. 检查数据库备份
echo "3. 检查数据库备份..."
if [ -f "$BACKUP_DIR/database/nextcloud.sql.gz" ]; then
if ! gunzip -t "$BACKUP_DIR/database/nextcloud.sql.gz"; then
echo "ERROR: 数据库备份损坏!"
exit 1
fi
fi
# 4. 检查数据目录
echo "4. 检查数据目录..."
DATA_COUNT=$(find "$BACKUP_DIR/data" -type f | wc -l)
echo "数据文件数量: $DATA_COUNT"
# 清理
rm -rf "$VERIFY_DIR"
echo "备份验证通过 ✓"
12.8 数据迁移
迁移到新服务器
迁移步骤:
1. 旧服务器: 完整备份(数据 + 数据库 + 配置)
2. 新服务器: 安装相同版本的 Nextcloud
3. 新服务器: 恢复备份
4. 新服务器: 修改 config.php 中的域名和路径
5. DNS 切换: 将域名指向新服务器 IP
6. 验证: 确认所有功能正常
# 迁移检查清单
# 1. Nextcloud 版本一致
# 2. PHP 版本一致
# 3. 数据库版本一致
# 4. 文件权限正确
# 5. 数据目录路径正确
# 6. 可信域名更新
# 7. SSL 证书配置
# 8. Cron 任务配置
# 9. Redis 连接配置
12.9 注意事项
- 备份一致性: 备份前必须开启维护模式,确保数据一致性
- 密钥备份:
config.php中的secret和加密密钥必须安全备份 - 定期验证: 每月至少进行一次备份恢复测试
- 异地备份: 至少保留一份异地备份,防范物理灾难
- 备份加密: 异地备份建议加密后再传输
- 恢复时间: 记录恢复所需时间,确保满足 RTO 要求
12.10 扩展阅读
上一章: 11 - 性能优化 下一章: 13 - Docker 部署 — Docker/Docker Compose 部署与 AIO 集成。