e7fba5abe5
- fix(storage): StorageOut 增加 config 字段并解密返回,编辑时可回填
- fix(storage): Storage ORM 模型添加 config property 支持序列化
- fix(env): 修正 SECRET_KEY 截断、FERNET_KEY 非法占位符问题
- fix(deploy): 后端从 Docker 容器迁移到 systemd 服务,存储目标路径改为宿主机真实路径
- feat(api): 新增 GET /api/storages/{id}/files 文件浏览端点
- feat(frontend): 新增 listFiles API 调用
- docs: 更新 README 反映部署方式变更
6.0 KiB
6.0 KiB
数据备份管理系统
一个带 Web 操作界面的备份系统,支持将 MySQL 数据库、服务器目录、InfluxDB、ETCD 备份到 本地目录 或 S3 兼容对象存储(AWS S3 / MinIO / Ceph)。支持手动触发、Cron 定时调度、备份保留策略,以及从备份还原。
功能
- 📦 多数据源:MySQL 数据库(mysqldump)、服务器目录(tar.gz)、InfluxDB、ETCD
- ☁️ 多存储目标:本地目录、S3 兼容对象存储
- ⏰ Cron 定时调度:标准 5 段 cron 表达式
- 🔁 备份还原:从备份恢复 MySQL 库 / 解压目录
- 🗂️ 保留策略:保留最近 N 个 + 保留 N 天
- 👤 JWT 登录认证:RBAC 权限管理(admin/operator)
- 📊 运行历史与日志:每次备份的执行详情、SHA256 校验、大小、耗时
- 🔐 敏感字段加密:密码、Token 在数据库中 Fernet 加密存储
- 📁 文件浏览:存储目标下的备份文件列表查看
技术栈
- 后端:Python 3.11、FastAPI、SQLAlchemy 2、APScheduler、aiofiles / aioboto3
- 前端:Vite + React 18 + TypeScript + Ant Design 5
- 数据库:SQLite(可平滑迁移 PostgreSQL)
- 部署:后端 systemd 服务 + 前端 Docker 容器(Nginx)
架构
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ 浏览器 │────▶│ 前端容器 │────▶│ 后端服务 │
│ :5173 │ │ Nginx 反代 │ │ systemd :8765 │
└─────────────┘ └─────────────┘ └──────┬───────┘
│
┌─────────▼─────────┐
│ SQLite DB │
│ backup files (本地) │
└─────────────────────┘
部署方式
环境要求
- 后端:Python 3.11+(已在
/root/system-backu/backend/venv中创建 venv) - 前端:Docker(仅前端容器,运行于端口 5173)
- 依赖工具:
mysqldump(备份 MySQL)、etcdctl(备份 ETCD)、influxCLI(备份 InfluxDB)
1. 准备环境变量
cd /root/system-backu
cp .env.example .env
# 编辑 .env,至少设置以下三项:
# SECRET_KEY — openssl rand -hex 32
# FERNET_KEY — python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# INITIAL_ADMIN_PASSWORD — 管理员密码(登录后可通过页面修改)
2. 启动服务
后端(systemd 托管,开机自启):
systemctl start backup-backend
systemctl enable backup-backend
journalctl -u backup-backend -f # 查看日志
前端(Docker 容器):
cd /root/system-backu
docker compose up -d frontend
3. 访问
| 服务 | 地址 |
|---|---|
| 前端管理界面 | http://10.168.1.209:5173 |
| 后端 API | http://10.168.1.209:8765 |
| API 文档 | http://10.168.1.209:8765/docs |
4. 首次使用
- 打开前端地址,用
admin/INITIAL_ADMIN_PASSWORD登录(首次登录后建议修改密码) - Storages → 新建存储目标(本地路径建议用已映射到宿主机的目录)
- Jobs → 新建 → 选择数据源类型 → 填写源信息 → 选存储目标 → 保存
- Job 列表点 Run Now 立即触发,或填写
cron_expression启用定时调度
项目结构
.
├── docker-compose.yml # 仅前端容器
├── .env.example # 环境变量模板
├── backend/
│ ├── app/ # FastAPI 应用代码
│ │ ├── api/ # API 端点
│ │ ├── core/ # 核心逻辑(备份、存储、恢复)
│ │ ├── models/ # SQLAlchemy 模型
│ │ ├── schemas/ # Pydantic 数据模型
│ │ └── utils/ # 工具函数(加密等)
│ ├── alembic/ # 数据库迁移
│ └── venv/ # Python 虚拟环境(.gitignore)
└── frontend/
├── src/ # React 源码
│ ├── pages/ # 页面组件
│ ├── api/ # API 调用
│ └── types/ # TypeScript 类型定义
└── nginx.conf # Nginx 反代配置
存储与持久化
- 数据库:
/root/system-backu/data/backend/backup.db(SQLite) - 备份文件:
/root/system-backu/data/backend/backups/(按 任务名/日期/ 组织) - 日志:
/root/system-backu/data/logs/
所有数据均在宿主机上,容器重启不会丢失。备份文件通过文件系统直接访问和下载。
API 概览
| 端点 | 说明 |
|---|---|
POST /api/auth/login |
登录获取 JWT |
GET /api/storages |
存储目标列表 |
POST /api/storages |
创建存储目标 |
GET /api/storages/{id}/files |
列出存储目标下的备份文件 |
POST /api/storages/{id}/test |
测试存储目标连通性 |
GET /api/jobs |
备份任务列表 |
POST /api/jobs |
创建备份任务 |
POST /api/jobs/{id}/run |
手动触发备份 |
GET /api/runs |
运行历史 |
POST /api/restore |
从备份恢复 |
完整 API 文档请访问 /docs。
注意事项
- ⚠️ 单实例部署:内置 APScheduler,不要启动多个 backend 进程,否则出现重复调度
- 🔐 敏感字段加密:数据源密码、Token 在数据库中以 Fernet 加密,前端永远看不到明文(编辑时回显
***) - 💾 存储目标路径:本地存储的 path 必须是在宿主机上实际存在的目录,且后端进程有读写权限
- 🗄️ mysqldump:备份 MySQL 需要宿主机安装
mysql-client
License
MIT