docs: 添加Spanish Diary项目部署方案
@@ -0,0 +1,373 @@
|
|||||||
|
# Spanish Diary 项目部署方案
|
||||||
|
|
||||||
|
## 1. 部署架构
|
||||||
|
|
||||||
|
`spanish-diary` 由前端静态页面和 Flask 后端组成,后端同时负责 API 和静态页面托管,因此只需要把 Python 服务跑起来即可。
|
||||||
|
|
||||||
|
推荐生产部署方式:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ubuntu + Python venv + Gunicorn + systemd + Nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
不依赖 Docker,避免国内服务器无法拉取 Docker Hub 镜像的问题。
|
||||||
|
|
||||||
|
## 2. 项目目录说明
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/spanish-diary
|
||||||
|
├── index.html # 主页面
|
||||||
|
├── login.html # 登录/注册
|
||||||
|
├── admin.html # 管理员用户管理
|
||||||
|
├── knowledge.html # 知识库首页
|
||||||
|
├── knowledge/ # 知识库分类页面
|
||||||
|
├── app.js # 前端应用逻辑
|
||||||
|
├── api.js # 后端 API 客户端
|
||||||
|
├── server/ # Flask 后端
|
||||||
|
│ ├── app.py # 应用入口
|
||||||
|
│ ├── requirements.txt # Python 依赖
|
||||||
|
│ ├── db.py # SQLite 初始化
|
||||||
|
│ └── data/ # SQLite 数据库目录
|
||||||
|
└── venv/ # Python 虚拟环境
|
||||||
|
```
|
||||||
|
|
||||||
|
SQLite 数据库路径:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/spanish-diary/server/data/spanish_diary.db
|
||||||
|
```
|
||||||
|
|
||||||
|
首次启动时后端会自动创建数据库、数据表和管理员账号。
|
||||||
|
|
||||||
|
## 3. Windows 本地运行
|
||||||
|
|
||||||
|
Windows PowerShell:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cd C:\Users\Administrator\Documents\Codex\2026-07-30\build-web-apps-plugin-build-web\spanish-diary
|
||||||
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\Activate.ps1
|
||||||
|
python -m pip install -r server\requirements.txt
|
||||||
|
python server\app.py
|
||||||
|
```
|
||||||
|
|
||||||
|
访问:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:5000
|
||||||
|
```
|
||||||
|
|
||||||
|
默认管理员:
|
||||||
|
|
||||||
|
```text
|
||||||
|
用户名:admin
|
||||||
|
密码:admin123
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Ubuntu 生产部署
|
||||||
|
|
||||||
|
### 4.1 安装基础软件
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y git python3-venv python3-pip nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 创建运行用户并拉取代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo useradd --system --no-create-home --home /opt/spanish-diary --shell /usr/sbin/nologin spanish-diary || true
|
||||||
|
sudo mkdir -p /opt/spanish-diary
|
||||||
|
sudo git clone https://git.youzhilian.cn/guoqingshan/spanish-diary.git /opt/spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
如果仓库是私有的,在服务器上使用 Gitea Access Token 作为密码,或配置 SSH Key。不要把令牌长期写入 shell 历史。
|
||||||
|
|
||||||
|
### 4.3 创建 Python 虚拟环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/spanish-diary
|
||||||
|
sudo python3 -m venv venv
|
||||||
|
sudo venv/bin/pip install --upgrade pip
|
||||||
|
sudo venv/bin/pip install -r server/requirements.txt
|
||||||
|
sudo venv/bin/pip install gunicorn
|
||||||
|
sudo chown -R spanish-diary:spanish-diary /opt/spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 生成 SECRET_KEY
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||||
|
```
|
||||||
|
|
||||||
|
把输出保存下来,后面写入 systemd 服务。
|
||||||
|
|
||||||
|
### 4.5 手动测试启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/spanish-diary
|
||||||
|
sudo -u spanish-diary env SECRET_KEY='替换为生成的密钥' \
|
||||||
|
/opt/spanish-diary/venv/bin/gunicorn \
|
||||||
|
--workers 2 --threads 2 \
|
||||||
|
--bind 127.0.0.1:5000 \
|
||||||
|
server.app:app
|
||||||
|
```
|
||||||
|
|
||||||
|
另开一个终端验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://127.0.0.1:5000/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.6 创建 systemd 服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tee /etc/systemd/system/spanish-diary.service > /dev/null <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=Spanish Diary Flask App
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=spanish-diary
|
||||||
|
Group=spanish-diary
|
||||||
|
WorkingDirectory=/opt/spanish-diary
|
||||||
|
Environment=SECRET_KEY=替换为生成的密钥
|
||||||
|
Environment=COOKIE_SECURE=0
|
||||||
|
Environment=PYTHONUNBUFFERED=1
|
||||||
|
ExecStart=/opt/spanish-diary/venv/bin/gunicorn --workers 2 --threads 2 --bind 127.0.0.1:5000 server.app:app
|
||||||
|
Restart=always
|
||||||
|
RestartSec=3
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now spanish-diary
|
||||||
|
sudo systemctl status spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
查看日志:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo journalctl -u spanish-diary -f
|
||||||
|
```
|
||||||
|
|
||||||
|
常用命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl start spanish-diary
|
||||||
|
sudo systemctl stop spanish-diary
|
||||||
|
sudo systemctl restart spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.7 配置 Nginx 反向代理
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tee /etc/nginx/sites-available/spanish-diary > /dev/null <<'EOF'
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name your-domain.com;
|
||||||
|
|
||||||
|
client_max_body_size 2m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:5000;
|
||||||
|
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_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo ln -s /etc/nginx/sites-available/spanish-diary /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
没有域名时,可以先把 `server_name` 改为 `_`,使用服务器 IP 访问。
|
||||||
|
|
||||||
|
### 4.8 配置 HTTPS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install -y certbot python3-certbot-nginx
|
||||||
|
sudo certbot --nginx -d your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
启用 HTTPS 后,把 systemd 服务中的环境变量改为:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
Environment=COOKIE_SECURE=1
|
||||||
|
```
|
||||||
|
|
||||||
|
然后重启:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl restart spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.9 配置防火墙
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ufw allow OpenSSH
|
||||||
|
sudo ufw allow 80/tcp
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
sudo ufw enable
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. 数据库备份与恢复
|
||||||
|
|
||||||
|
### 5.1 备份
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /backup
|
||||||
|
sudo systemctl stop spanish-diary
|
||||||
|
sudo cp /opt/spanish-diary/server/data/spanish_diary.db /backup/spanish-diary-$(date +%F).db
|
||||||
|
sudo systemctl start spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
建议把 `/backup` 同步到其他服务器、对象存储或本机。
|
||||||
|
|
||||||
|
### 5.2 恢复
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl stop spanish-diary
|
||||||
|
sudo cp /backup/spanish-diary-YYYY-MM-DD.db /opt/spanish-diary/server/data/spanish_diary.db
|
||||||
|
sudo chown spanish-diary:spanish-diary /opt/spanish-diary/server/data/spanish_diary.db
|
||||||
|
sudo systemctl start spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. 升级项目
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u spanish-diary git -C /opt/spanish-diary pull origin master
|
||||||
|
sudo systemctl restart spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
升级前建议先备份数据库。
|
||||||
|
|
||||||
|
## 7. 修改默认管理员密码
|
||||||
|
|
||||||
|
项目当前没有管理员修改密码页面,生产环境首次启动后建议手动修改 `admin` 密码。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/spanish-diary
|
||||||
|
sudo -u spanish-diary venv/bin/python - <<'EOF'
|
||||||
|
import sqlite3
|
||||||
|
from werkzeug.security import generate_password_hash
|
||||||
|
|
||||||
|
conn = sqlite3.connect("server/data/spanish_diary.db")
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE users SET password_hash=? WHERE username='admin'",
|
||||||
|
(generate_password_hash("你的新密码"),),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
print("admin password updated")
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. 接入翻译服务
|
||||||
|
|
||||||
|
项目支持三种翻译方式:
|
||||||
|
|
||||||
|
- 本地词典:前端完成,无需额外服务
|
||||||
|
- MyMemory:免费在线接口,无需部署
|
||||||
|
- 自定义接口:可对接自建 LibreTranslate
|
||||||
|
|
||||||
|
如果使用 LibreTranslate,请先参考百科中的《LibreTranslate Conda 部署方案(Ubuntu)》。
|
||||||
|
|
||||||
|
在项目“翻译设置”中选择“自定义接口”:
|
||||||
|
|
||||||
|
```text
|
||||||
|
接口地址:http://127.0.0.1:5001/translate
|
||||||
|
接口密钥:你的APIKey
|
||||||
|
```
|
||||||
|
|
||||||
|
扩展配置:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"result_key": "translatedText",
|
||||||
|
"headers": {
|
||||||
|
"Authorization": "Bearer 你的APIKey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. 环境变量说明
|
||||||
|
|
||||||
|
```text
|
||||||
|
SECRET_KEY 会话加密密钥,必须设置为随机长字符串
|
||||||
|
COOKIE_SECURE 使用 HTTPS 时设置为 1
|
||||||
|
PYTHONUNBUFFERED 设置为 1,便于日志实时输出
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. 常见问题
|
||||||
|
|
||||||
|
### 10.1 服务启动失败
|
||||||
|
|
||||||
|
查看日志:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo journalctl -u spanish-diary -e
|
||||||
|
```
|
||||||
|
|
||||||
|
检查代码目录和数据库目录权限:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chown -R spanish-diary:spanish-diary /opt/spanish-diary
|
||||||
|
sudo systemctl restart spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 Gunicorn 找不到 server.app
|
||||||
|
|
||||||
|
确保工作目录是项目根目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/spanish-diary
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.3 登录后会话失效
|
||||||
|
|
||||||
|
确认 `SECRET_KEY` 已设置,并且没有频繁更换。
|
||||||
|
|
||||||
|
### 10.4 HTTPS 下无法登录或会话不稳定
|
||||||
|
|
||||||
|
确认 systemd 中已设置:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
Environment=COOKIE_SECURE=1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.5 端口 5000 被占用
|
||||||
|
|
||||||
|
修改 Gunicorn 绑定端口:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
--bind 127.0.0.1:5001
|
||||||
|
```
|
||||||
|
|
||||||
|
同时修改 Nginx 的 `proxy_pass`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
proxy_pass http://127.0.0.1:5001;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. 部署完成检查
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://127.0.0.1:5000/
|
||||||
|
sudo systemctl is-active spanish-diary
|
||||||
|
sudo nginx -t
|
||||||
|
```
|
||||||
|
|
||||||
|
浏览器访问:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
使用默认管理员登录后,应立即修改管理员密码。
|
||||||
Reference in New Issue
Block a user