跳到主要内容
警告

本教程由社区贡献,不获得 Open WebUI 团队的支持。它仅作为演示,说明如何根据您的特定用例定制 Open WebUI。想要贡献?请查看贡献教程。

备份您的实例

没有人喜欢丢失数据!

如果您是Open WebUI的自托管用户,您可能希望制定某种正式的备份计划,以确保保留配置的第二份和第三份副本。

本指南旨在为用户提供一些关于如何进行备份的基本建议。

本指南假设用户已通过Docker安装Open WebUI(或打算这样做)

确保数据持久性

首先,在使用Docker部署堆栈之前,请确保您的Docker Compose使用持久性数据存储。如果您使用的是Github仓库中的Docker Compose,这一点已经处理好了。但是,很容易创建自己的变体并忘记验证这一点。

Docker容器是短暂的,数据必须持久化才能确保其在宿主文件系统上的存活。

使用Docker卷

如果您使用项目仓库中的Docker Compose,您将使用Docker卷部署Open Web UI。

对于Ollama和Open WebUI,挂载点是

ollama:
volumes:
- ollama:/root/.ollama
open-webui:
volumes:
- open-webui:/app/backend/data

要查找主机上的实际绑定路径,请运行

docker volume inspect ollama

以及

docker volume inspect open-webui

使用直接主机绑定

一些用户通过直接(固定)绑定到主机文件系统来部署Open Web UI,如下所示

services:
ollama:
container_name: ollama
image: ollama/ollama:${OLLAMA_DOCKER_TAG-latest}
volumes:
- /opt/ollama:/root/.ollama
open-webui:
container_name: open-webui
image: ghcr.io/open-webui/open-webui:${WEBUI_DOCKER_TAG-main}
volumes:
- /opt/open-webui:/app/backend/data

如果这是您部署实例的方式,您需要记下根目录上的路径。

编写备份脚本

无论您的实例是如何配置的,都值得检查服务器上的应用程序数据存储,以了解您将要备份哪些数据。您应该会看到类似以下内容:

├── audit.log
├── cache/
├── uploads/
├── vector_db/
└── webui.db

持久化数据存储中的文件

文件/目录描述
audit.log用于审计事件的日志文件。
cache/用于存储缓存数据的目录。
uploads/用于存储用户上传文件的目录。
vector_db/包含ChromaDB向量数据库的目录。
webui.db用于持久存储其他实例数据的SQLite数据库

文件级备份方法

备份应用程序数据的首选方法是采用文件级备份,确保Open Web UI的持久性数据得到妥善备份。

技术服务有几乎无限种备份方式,但rsync仍然是增量任务的流行选择,因此将用作演示。

用户可以针对整个data目录一次性备份所有实例数据,或者创建更具选择性的备份任务,针对单个组件进行备份。您还可以为目标添加更具描述性的名称。

一个典型的rsync任务可能如下所示

#!/bin/bash

# Configuration
SOURCE_DIR="." # Current directory (where the file structure resides)
B2_BUCKET="b2://OpenWebUI-backups" # Your Backblaze B2 bucket
B2_PROFILE="your_rclone_profile" # Your rclone profile name
# Ensure rclone is configured with your B2 credentials

# Define source and destination directories
SOURCE_UPLOADS="$SOURCE_DIR/uploads"
SOURCE_VECTORDB="$SOURCE_DIR/vector_db"
SOURCE_WEBUI_DB="$SOURCE_DIR/webui.db"

DEST_UPLOADS="$B2_BUCKET/user_uploads"
DEST_CHROMADB="$B2_BUCKET/ChromaDB"
DEST_MAIN_DB="$B2_BUCKET/main_database"

# Exclude cache and audit.log
EXCLUDE_LIST=(
"cache/"
"audit.log"
)

# Construct exclude arguments for rclone
EXCLUDE_ARGS=""
for EXCLUDE in "${EXCLUDE_LIST[@]}"; do
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude '$EXCLUDE'"
done

# Function to perform rclone sync with error checking
rclone_sync() {
SOURCE="$1"
DEST="$2"
echo "Syncing '$SOURCE' to '$DEST'..."
rclone sync "$SOURCE" "$DEST" $EXCLUDE_ARGS --progress --transfers=32 --checkers=16 --profile "$B2_PROFILE"
if [ $? -ne 0 ]; then
echo "Error: rclone sync failed for '$SOURCE' to '$DEST'"
exit 1
fi
}

# Perform rclone sync for each directory/file
rclone_sync "$SOURCE_UPLOADS" "$DEST_UPLOADS"
rclone_sync "$SOURCE_VECTORDB" "$DEST_CHROMADB"
rclone_sync "$SOURCE_WEBUI_DB" "$DEST_MAIN_DB"

echo "Backup completed successfully."
exit 0

带容器中断的Rsync任务

为维护数据完整性,通常建议在冷文件系统上运行数据库备份。我们的默认模型备份任务可以稍微修改,以便在运行备份脚本之前关闭堆栈,并在之后重新启动。

当然,这种方法的缺点是会导致实例停机。考虑在不使用实例时运行此任务,或进行“软件”每日备份(对运行中的数据)以及更可靠的每周备份(对冷数据)。

#!/bin/bash

# Configuration
COMPOSE_FILE="docker-compose.yml" # Path to your docker-compose.yml file
B2_BUCKET="b2://OpenWebUI-backups" # Your Backblaze B2 bucket
B2_PROFILE="your_rclone_profile" # Your rclone profile name
SOURCE_DIR="." # Current directory (where the file structure resides)

# Define source and destination directories
SOURCE_UPLOADS="$SOURCE_DIR/uploads"
SOURCE_VECTORDB="$SOURCE_DIR/vector_db"
SOURCE_WEBUI_DB="$SOURCE_DIR/webui.db"

DEST_UPLOADS="$B2_BUCKET/user_uploads"
DEST_CHROMADB="$B2_BUCKET/ChromaDB"
DEST_MAIN_DB="$B2_BUCKET/main_database"

# Exclude cache and audit.log
EXCLUDE_LIST=(
"cache/"
"audit.log"
)

# Construct exclude arguments for rclone
EXCLUDE_ARGS=""
for EXCLUDE in "${EXCLUDE_LIST[@]}"; do
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude '$EXCLUDE'"
done

# Function to perform rclone sync with error checking
rclone_sync() {
SOURCE="$1"
DEST="$2"
echo "Syncing '$SOURCE' to '$DEST'..."
rclone sync "$SOURCE" "$DEST" $EXCLUDE_ARGS --progress --transfers=32 --checkers=16 --profile "$B2_PROFILE"
if [ $? -ne 0 ]; then
echo "Error: rclone sync failed for '$SOURCE' to '$DEST'"
exit 1
fi
}

# 1. Stop the Docker Compose environment
echo "Stopping Docker Compose environment..."
docker-compose -f "$COMPOSE_FILE" down

# 2. Perform the backup
echo "Starting backup..."
rclone_sync "$SOURCE_UPLOADS" "$DEST_UPLOADS"
rclone_sync "$SOURCE_VECTORDB" "$DEST_CHROMADB"
rclone_sync "$SOURCE_WEBUI_DB" "$DEST_MAIN_DB"

# 3. Start the Docker Compose environment
echo "Starting Docker Compose environment..."
docker-compose -f "$COMPOSE_FILE" up -d

echo "Backup completed successfully."
exit 0

使用SQLite和ChromaDB备份功能到B2远程的模型备份脚本

#!/bin/bash
#
# Backup script to back up ChromaDB and SQLite to Backblaze B2 bucket
# openwebuiweeklies, maintaining 3 weekly snapshots.
# Snapshots are independent and fully restorable.
# Uses ChromaDB and SQLite native backup mechanisms.
# Excludes audit.log, cache, and uploads directories.
#
# Ensure rclone is installed and configured correctly.
# Install rclone: https://rclone.org/install/
# Configure rclone: https://rclone.org/b2/

# Source directory (containing ChromaDB and SQLite data)
SOURCE="/var/lib/open-webui/data"

# B2 bucket name and remote name
B2_REMOTE="openwebuiweeklies"
B2_BUCKET="b2:$B2_REMOTE"

# Timestamp for the backup directory
TIMESTAMP=$(date +%Y-%m-%d)

# Backup directory name
BACKUP_DIR="open-webui-backup-$TIMESTAMP"

# Full path to the backup directory in the B2 bucket
DESTINATION="$B2_BUCKET/$BACKUP_DIR"

# Number of weekly snapshots to keep
NUM_SNAPSHOTS=3

# Exclude filters (applied *after* database backups)
EXCLUDE_FILTERS="--exclude audit.log --exclude cache/** --exclude uploads/** --exclude vector_db"

# ChromaDB Backup Settings (Adjust as needed)
CHROMADB_DATA_DIR="$SOURCE/vector_db" # Path to ChromaDB data directory
CHROMADB_BACKUP_FILE="$SOURCE/chromadb_backup.tar.gz" # Archive file for ChromaDB backup

# SQLite Backup Settings (Adjust as needed)
SQLITE_DB_FILE="$SOURCE/webui.db" # Path to the SQLite database file
SQLITE_BACKUP_FILE="$SOURCE/webui.db.backup" # Temporary file for SQLite backup

# Function to backup ChromaDB
backup_chromadb() {
echo "Backing up ChromaDB..."

# Create a tar archive of the vector_db directory
tar -czvf "$CHROMADB_BACKUP_FILE" -C "$SOURCE" vector_db

echo "ChromaDB backup complete."
}

# Function to backup SQLite
backup_sqlite() {
echo "Backing up SQLite database..."
# Backup the SQLite database using the .backup command
sqlite3 "$SQLITE_DB_FILE" ".backup '$SQLITE_BACKUP_FILE'"

# Move the backup file to the source directory
mv "$SQLITE_BACKUP_FILE" "$SOURCE/"

echo "SQLite backup complete."
}

# Perform database backups
backup_chromadb
backup_sqlite

# Perform the backup with exclusions
rclone copy "$SOURCE" "$DESTINATION" $EXCLUDE_FILTERS --progress

# Remove old backups, keeping the most recent NUM_SNAPSHOTS
find "$B2_BUCKET" -type d -name "open-webui-backup-*" | sort -r | tail -n +$((NUM_SNAPSHOTS + 1)) | while read dir; do
rclone purge "$dir"
done

echo "Backup completed to $DESTINATION"

时间点快照

除了进行备份,用户可能还希望创建时间点快照,这些快照可以存储在本地(服务器上)、远程或两者兼有。

#!/bin/bash

# Configuration
SOURCE_DIR="." # Directory to snapshot (current directory)
SNAPSHOT_DIR="/snapshots" # Directory to store snapshots
TIMESTAMP=$(date +%Y%m%d%H%M%S) # Generate timestamp

# Create the snapshot directory if it doesn't exist
mkdir -p "$SNAPSHOT_DIR"

# Create the snapshot name
SNAPSHOT_NAME="snapshot_$TIMESTAMP"
SNAPSHOT_PATH="$SNAPSHOT_DIR/$SNAPSHOT_NAME"

# Perform the rsync snapshot
echo "Creating snapshot: $SNAPSHOT_PATH"
rsync -av --delete --link-dest="$SNAPSHOT_DIR/$(ls -t "$SNAPSHOT_DIR" | head -n 1)" "$SOURCE_DIR/" "$SNAPSHOT_PATH"

# Check if rsync was successful
if [ $? -eq 0 ]; then
echo "Snapshot created successfully."
else
echo "Error: Snapshot creation failed."
exit 1
fi

exit 0

用于调度的Crontab

添加备份脚本并配置好备份存储后,您需要对脚本进行质量保证,以确保它们按预期运行。强烈建议进行日志记录。

根据您希望的运行频率,使用crontabs设置新的脚本来运行。

商业工具

除了编写自己的备份任务脚本外,您还可以找到商业产品,它们通常通过在服务器上安装代理来简化备份运行的复杂性。这些超出了本文的范围,但提供了方便的解决方案。


主机级备份

您的Open WebUI实例可能部署在您控制的主机(物理或虚拟化)上。

主机级备份涉及创建快照或备份,但备份的是整个虚拟机而非运行中的应用程序。

有些人可能希望将其作为主要或唯一的保护措施,而另一些人则可能希望将其作为额外的数据保护层。

我需要多少个备份?

您希望进行的备份数量取决于您的个人风险承受能力。但是,请记住,最佳实践是*不要*将应用程序本身视为备份副本(即使它存在于云端!)。这意味着,如果您已在VPS上配置了实例,仍然合理建议保留两份(独立)备份副本。

一个可以满足许多家庭用户需求的备份计划示例

模型备份计划1(主副本 + 2个副本)

频率目标技术描述
每日增量云存储 (S3/B2)rsync每日增量备份推送到云存储桶(S3或B2)。
每周增量本地存储 (家用NAS)rsync每周增量备份从服务器拉取到本地存储(例如,家用NAS)。

模型备份计划2(主副本 + 3个副本)

此备份计划稍微复杂一些,但也更全面……它涉及每日推送到两个云存储提供商以获得额外的冗余。

频率目标技术描述
每日增量云存储 (S3)rsync每日增量备份推送到S3云存储桶。
每日增量云存储 (B2)rsync每日增量备份推送到Backblaze B2云存储桶。
每周增量本地存储 (家用NAS)rsync每周增量备份从服务器拉取到本地存储(例如,家用NAS)。

其他主题

为了使本指南保持合理详尽,以下额外主题被省略,但根据您有多少时间投入到为实例设置和维护数据保护计划中,这些主题可能值得您考虑。

主题描述
SQLite内置备份考虑使用SQLite的.backup命令来实现一致的数据库备份解决方案。
加密修改备份脚本以集成静态加密,增强安全性。
灾难恢复与测试制定灾难恢复计划并定期测试备份和恢复过程。
替代备份工具探索其他命令行备份工具,如borgbackuprestic,以获取高级功能。
电子邮件通知和Webhook实现电子邮件通知或webhook以监控备份的成功或失败。