feat: rename system to 有音个性化教学系统; update docs
This commit is contained in:
+262
-4
@@ -1,11 +1,219 @@
|
||||
# 钢琴练习方案系统 - 部署 SOP
|
||||
|
||||
> 版本:v1.5.2
|
||||
> 日期:2026-04-28
|
||||
> 版本:v1.5.6
|
||||
> 日期:2026-04-30
|
||||
> 核心原则:**不删除,只备份后新增/替换**
|
||||
|
||||
---
|
||||
|
||||
## 重要更新(v1.5.6)
|
||||
|
||||
### 🔒 安全防护:Nginx 限流配置
|
||||
|
||||
新增 Nginx 限流规则,防止爬虫和恶意请求:
|
||||
|
||||
**限流规则:**
|
||||
|
||||
| 路由 | 限流规则 | 说明 |
|
||||
|------|----------|------|
|
||||
| `/` (全站) | 30请求/秒, burst=50 | 正常用户够用 |
|
||||
| `/api/generate-plan` | 10请求/秒, burst=20 | 重点防护(AI生成接口) |
|
||||
|
||||
**超过限制返回:** `429 Too Many Requests`
|
||||
|
||||
**配置文件:**
|
||||
- 主配置:`/etc/nginx/nginx.conf`(限流zone定义)
|
||||
- 站点配置:`/etc/nginx/conf.d/piano.yoin.fun.conf`(限流规则应用)
|
||||
|
||||
**完整的 nginx.conf 限流部分(http{} 块中添加):**
|
||||
```nginx
|
||||
# 限流配置 - 防止爬虫和恶意请求
|
||||
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
|
||||
limit_req_zone $binary_remote_addr zone=general_limit:10m rate=30r/s;
|
||||
limit_req_log_level warn;
|
||||
limit_req_status 429;
|
||||
```
|
||||
|
||||
**完整的站点配置(piano.yoin.fun.conf):**
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name piano.yoin.fun;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name piano.yoin.fun;
|
||||
location / {
|
||||
limit_req zone=general_limit burst=50 nodelay;
|
||||
proxy_pass http://172.17.0.1:5001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
tcp_nodelay on;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection '';
|
||||
}
|
||||
location /api/generate-plan {
|
||||
limit_req zone=api_limit burst=20 nodelay;
|
||||
proxy_pass http://172.17.0.1:5001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
tcp_nodelay on;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection '';
|
||||
proxy_buffers 8 32k;
|
||||
proxy_buffer_size 32k;
|
||||
proxy_max_temp_file_size 1024m;
|
||||
}
|
||||
listen 443 ssl;
|
||||
ssl_certificate /etc/letsencrypt/live/piano.yoin.fun/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/piano.yoin.fun/privkey.pem;
|
||||
}
|
||||
```
|
||||
|
||||
**部署/修改方法:**
|
||||
```bash
|
||||
# 1. 备份当前配置
|
||||
docker exec nginx_server cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
|
||||
docker exec nginx_server cp /etc/nginx/conf.d/piano.yoin.fun.conf /etc/nginx/conf.d/piano.yoin.fun.conf.bak
|
||||
|
||||
# 2. 使用 sed 或直接编辑修改配置
|
||||
# 主配置:在 http{} 块中插入限流zone定义
|
||||
# 站点配置:在 location{} 块中添加 limit_req 指令
|
||||
|
||||
# 3. 测试配置
|
||||
docker exec nginx_server nginx -t -c /etc/nginx/nginx.conf
|
||||
|
||||
# 4. 重载nginx
|
||||
docker exec nginx_server nginx -s reload
|
||||
```
|
||||
|
||||
**常用命令:**
|
||||
```bash
|
||||
# 查看限流配置
|
||||
docker exec nginx_server cat /etc/nginx/conf.d/piano.yoin.fun.conf | grep limit_req
|
||||
|
||||
# 检查nginx状态
|
||||
docker exec nginx_server nginx -t
|
||||
|
||||
# 重载配置
|
||||
docker exec nginx_server nginx -s reload
|
||||
|
||||
# 查看nginx日志(限流日志)
|
||||
docker exec nginx_server tail -50 /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 💾 数据备份:每日自动备份
|
||||
|
||||
新增服务器本地每日自动备份机制:
|
||||
|
||||
**备份配置:**
|
||||
- 备份路径:`/opt/backups/piano-db/`
|
||||
- 执行时间:每天凌晨 3:00
|
||||
- 保留期限:30 天
|
||||
- 备份方式:SQLite `.backup` 命令(保证一致性)
|
||||
- 服务状态:crond 运行中
|
||||
|
||||
**备份脚本位置:** `/opt/backups/backup_piano_db.sh`(宿主机,不受容器重建影响)
|
||||
|
||||
**完整脚本内容:**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Piano Plan 数据库每日备份脚本
|
||||
# 保留30天
|
||||
# 自包含:部署后依然有效,不依赖容器内预存文件
|
||||
|
||||
BACKUP_DIR="/opt/backups/piano-db"
|
||||
RETENTION_DAYS=30
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_FILE="piano_plans_${TIMESTAMP}.db"
|
||||
SCRIPT_FILE="/tmp/backup_piano_$$.py"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# 创建临时Python脚本(写在宿主机,然后复制到容器)
|
||||
cat > "$SCRIPT_FILE" << 'PYEOF'
|
||||
import sqlite3
|
||||
conn = sqlite3.connect('/app/data/piano_plans.db')
|
||||
backup = sqlite3.connect('/tmp/piano_backup.db')
|
||||
conn.backup(backup)
|
||||
backup.close()
|
||||
conn.close()
|
||||
PYEOF
|
||||
|
||||
# 复制到容器并执行
|
||||
docker cp "$SCRIPT_FILE" piano-plan:/tmp/backup_piano.py
|
||||
rm -f "$SCRIPT_FILE"
|
||||
docker exec piano-plan python3 /tmp/backup_piano.py
|
||||
|
||||
# 复制备份到宿主机
|
||||
docker cp piano-plan:/tmp/piano_backup.db "$BACKUP_DIR/$BACKUP_FILE"
|
||||
|
||||
# 清理容器内文件
|
||||
docker exec piano-plan rm -f /tmp/backup_piano.py /tmp/piano_backup.db
|
||||
|
||||
# 验证
|
||||
if [ -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
|
||||
SIZE=$(du -h "$BACKUP_DIR/$BACKUP_FILE" | cut -f1)
|
||||
echo "[$(date)] Backup OK: $BACKUP_FILE ($SIZE)"
|
||||
|
||||
# 删除30天前的备份
|
||||
find "$BACKUP_DIR" -name "piano_plans_*.db" -mtime +${RETENTION_DAYS} -delete
|
||||
echo "[$(date)] Cleanup done (retained $RETENTION_DAYS days)"
|
||||
else
|
||||
echo "[$(date)] Backup FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ls -lh "$BACKUP_DIR"
|
||||
```
|
||||
|
||||
**设置 cron 任务:**
|
||||
```bash
|
||||
# 添加到 crontab
|
||||
(crontab -l 2>/dev/null; echo '0 3 * * * /opt/backups/backup_piano_db.sh >> /opt/backups/backup.log 2>&1') | crontab -
|
||||
|
||||
# 验证
|
||||
crontab -l
|
||||
```
|
||||
|
||||
**常用命令:**
|
||||
```bash
|
||||
# 查看备份
|
||||
ls -lh /opt/backups/piano-db/
|
||||
|
||||
# 手动执行备份
|
||||
/opt/backups/backup_piano_db.sh
|
||||
|
||||
# 查看 cron 配置
|
||||
crontab -l
|
||||
|
||||
# 删除旧的 cron 任务(如果需要)
|
||||
crontab -e # 编辑模式删除对应行
|
||||
```
|
||||
|
||||
**备份恢复:**
|
||||
```bash
|
||||
# 停止容器
|
||||
docker stop piano-plan
|
||||
|
||||
# 复制备份文件到容器
|
||||
docker cp /opt/backups/piano-db/piano_plans_XXXXXXXX_XXXXXX.db piano-plan:/app/data/piano_plans.db
|
||||
|
||||
# 启动容器
|
||||
docker start piano-plan
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 重要更新(v1.5.2)
|
||||
|
||||
### ✨ 导出预览功能
|
||||
@@ -447,6 +655,7 @@ A: 检查是否执行了 migrate_goals_v3.py 迁移脚本,该脚本创建 stud
|
||||
|
||||
| 版本 | 日期 | 变更 |
|
||||
|------|------|------|
|
||||
| v1.5.6 | 2026-04-30 | Nginx限流配置(防爬虫/恶意请求);每日自动备份(30天保留) |
|
||||
| v1.5.5 | 2026-04-28 | 修复容器时区(TZ=Asia/Shanghai);学员列表"x个方案"可点击跳转最新方案详情 |
|
||||
| v1.5.4 | 2026-04-28 | PDF正文字体12pt、表格11pt |
|
||||
| v1.5.3 | 2026-04-28 | PDF行间距修复(7mm→2mm) |
|
||||
@@ -467,5 +676,54 @@ A: 检查是否执行了 migrate_goals_v3.py 迁移脚本,该脚本创建 stud
|
||||
|
||||
---
|
||||
|
||||
> **最后更新**:2026-04-28
|
||||
> **更新原因**:v1.5.2 - 导出预览功能;目标换行修复;居中语法支持
|
||||
## 十二、Ops 运维脚本
|
||||
|
||||
### 12.1 备份脚本 (scripts/ops/backup_piano_db.sh)
|
||||
|
||||
**位置**:`scripts/ops/backup_piano_db.sh`(项目目录)
|
||||
|
||||
**上传到服务器**:
|
||||
```bash
|
||||
scp -i ~/.ssh/id_rsa scripts/ops/backup_piano_db.sh root@47.115.32.206:/opt/backups/backup_piano_db.sh
|
||||
chmod +x /opt/backups/backup_piano_db.sh
|
||||
```
|
||||
|
||||
**设置定时任务**:
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_rsa root@47.115.32.206
|
||||
(crontab -l 2>/dev/null; echo '0 3 * * * /opt/backups/backup_piano_db.sh >> /opt/backups/backup.log 2>&1') | crontab -
|
||||
```
|
||||
|
||||
**验证设置**:
|
||||
```bash
|
||||
crontab -l
|
||||
ls -lh /opt/backups/piano-db/
|
||||
```
|
||||
|
||||
### 12.2 脚本特性
|
||||
|
||||
- **自包含**:不依赖容器内预存文件
|
||||
- **幂等性**:可重复执行
|
||||
- **验证**:备份后自动验证文件存在
|
||||
- **清理**:自动删除 30 天前的备份
|
||||
|
||||
### 12.3 恢复备份
|
||||
|
||||
```bash
|
||||
# 1. 停止容器
|
||||
docker stop piano-plan
|
||||
|
||||
# 2. 列出可用备份
|
||||
ls -lh /opt/backups/piano-db/
|
||||
|
||||
# 3. 复制备份到容器
|
||||
docker cp /opt/backups/piano-db/piano_plans_XXXXXXXX_XXXXXX.db piano-plan:/app/data/piano_plans.db
|
||||
|
||||
# 4. 启动容器
|
||||
docker start piano-plan
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **最后更新**:2026-04-30
|
||||
> **更新原因**:v1.5.6 - Nginx限流配置;每日自动备份
|
||||
|
||||
Reference in New Issue
Block a user