使用BorgBackup备份数据

我之前一直使用Duplicati 备份各种数据,但是因为这个软件一直在Beta, 经常性的出问题,漏文件,备份失败之类的。 于是我决定完全切换到BorgBackup,一个命令行基于SSH的client-server模式的备份解决方案。

首先我们需要在备份服务器上面安装Borg服务端,很简单,例如我用debian, 于是只需要运行下面的命令即可:

sudo apt update
sudo apt install borgbackup #安装
sudo useradd -m -s /bin/bash borg-backup #创建独立的用户,这个用户用来运行borg相关进程,你可以换个用户名
sudo passwd borg-backup #设置密码
sudo mkdir -p /backup/repos #创建备份仓库目录
sudo chown borg-backup:borg-backup /backup/repos #修改仓库的所有者

至此服务端(Server)就基本搭好了,接下来需要在客户端(即需要备份的机器)执行:

su #切换到root,因为我需要备份一些需要root才能读取的数据
apt install borgbackup
ssh-keygen -t ed25519 #生成用于远程登录的ssh key
ssh-copy-id borg-backup@server-ip #把公钥复制到服务端

ssh登录的安全问题可以在服务端(server)上的把下面这段复制到authorized_keys 中每一个公钥前面:

command="borg serve --restrict-to-path /backup/repos",restrict 

例如:

command="borg serve --restrict-to-path /backup/repos",restrict ssh-ed25519 AAAAC3NzaC1lZDI1N... root@client

这段内容给borg-backup用户设置一个限制,即他使用ssh只能运行borg server命令,并且它只能读写/backup/repos目录。
至此我们的服务器和客户端就安装设置好了,接下来我们需要在客户端运行下面的命令以创建一个备份仓库:

borg init -e repokey-blake2 ssh://borg-backup@ip/backup/repos/[仓库名]

跟着写一个bash脚本,并把它放到crontab里面即可以完成自动备份了。
这里附一个我自用的脚本:

#!/bin/bash

# Borg settings
export BORG_REPO='ssh://borg-backup@ip:port/backup/repos/gl-win2'
export BORG_PASSPHRASE='repo password here'


# Parse command line arguments
# --with-mysql will use mysqldump to create a mysql backup
BACKUP_MYSQL=false
while [[ $# -gt 0 ]]; do
    case $1 in
        --with-mysql)
            BACKUP_MYSQL=true
            shift
            ;;
        *)
            echo "Unknown option: $1"
            echo "Usage: $0 [--with-mysql]"
            exit 1
            ;;
    esac
done

# Handle MySQL backup if requested
if [ "$BACKUP_MYSQL" = true ]; then
    echo "Starting MySQL backup..."
    BACKUP_DIR="/tmp/mysql_backup"
    mkdir -p $BACKUP_DIR
    mysqldump -u root -p'mysql database password' --all-databases --single-transaction > $BACKUP_DIR/all_databases.sql
    echo "MySQL backup completed"
fi

# Common exclusion patterns
EXCLUDE_PATTERNS=(
    '/home/**/.cache/**'
    '**/*.pyc'
    '/var/lib/docker/volumes/**/._*'
    '/var/lib/docker/overlay2/**'    # Docker images
    '/var/lib/docker/image/**'       # Docker image metadata
    '/var/lib/docker/containers/**'  # Docker container data
    '**/go/pkg/mod/**'
    '**/node_modules/**'
    '**/.git/**'
    '**/vendor/**'
    '**/*.log'
    '**/*.log.gz'
    '**/podsync/data/**'
    '/home/**/.npm/**'
    '/home/**/.cargo/**'
    '/home/**/.rustup/**'
    '**/__pycache__/**'
    '**/tmp/**'
    '/var/log/**'
    '/var/cache/**'
    '**/.idea/**'
    '**/.vscode/**'
    '**/build/**'
    '**/dist/**'
    '**/pihole-FTL.db'
    '**/venv/**'                    # Python virtual environments
    '**/env/**'                     # Another common Python venv name
    '/home/**/.local/lib/python**/**'  # User-installed Python packages
    '/usr/local/lib/python**/**'    # System Python packages
    '/usr/lib/python**/**'          # System Python packages
    '**/*.pyc'                      # Python compiled files
    '**/*.pyo'                      # Python optimized files
    '**/*.pyd'                      # Python DLL files
    '**/.pytest_cache/**'           # Pytest cache
    '**/site-packages/**'           # Python site-packages
    '**/dist-packages/**'           # Debian/Ubuntu Python packages
)

# Build exclude arguments
EXCLUDE_ARGS=""
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
    EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude '$pattern'"
done

# Create backup command
BACKUP_PATHS="/home /var/lib/docker/volumes" # backup source folders
if [ "$BACKUP_MYSQL" = true ]; then
    BACKUP_PATHS="$BACKUP_PATHS /tmp/mysql_backup"
fi

# Execute borg create with all exclusions
eval borg create \
    --verbose \
    --filter AME \
    --list \
    --stats \
    --compression lz4 \
    ::'client-machine-name-{now}' \
    $BACKUP_PATHS \
    $EXCLUDE_ARGS

# Clean up MySQL dump if it exists
if [ "$BACKUP_MYSQL" = true ]; then
    rm -rf /tmp/mysql_backup
fi

# Prune old backups
borg prune \
    --keep-daily 7 \
    --keep-weekly 4 \
    --keep-monthly 6

echo "Backup completed at $(date)" >> /var/log/borg-backup.log