This repository has been archived on 2026-10-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
NeteaseUrl/部署文档.md
T
snowy-yang 8446166120 refactor!: uv 管理环境 + 彻底删除技术债(Flask 与 requests 全部移除)
## uv 环境管理
- pyproject.toml 声明 dependencies + [dependency-groups].dev,uv.lock 精确锁定
- 删除 requirements.txt / requirements-fastapi.txt / requirements-dev.txt
- .python-version = 3.12;Dockerfile 改用 uv sync --frozen(可复现构建)
- 新增 jinja2(首页渲染)

## 删除 Flask 技术债
- 从 main.py 用 ast 精确剥离 56 个 Flask 节点(路由/中间件/错误处理/启动),
  框架无关的服务层落为 services/runtime.py(MusicAPIService、下载/打包 worker、
  任务监控、缓存清扫),零 Flask 依赖
- 删除 main.py(4527 行)与 auth_routes.py(1050 行)
- auth_system.py 移除会话/请求上下文层(login_session/current_user/login_required/
  admin_required/_client_ip 等),保留数据与业务层
- 新增 core/net.py(IP 解析)、web/auth_state.py(登录锁定/2FA 票据/发码限流)
- FastAPI 侧改直接依赖 services.runtime,不再 import main
- web/app.py 去掉 Flask fallback;入口默认根路径模式(API_PREFIX 可选)

## 删除 requests 技术债
- 新增 core/sync_http.py:requests 风格的同步门面(底层 aiohttp 连接池,
  流式读取经有界队列背压),含 Session/headers/(connect,read) 元组超时兼容
- core/utils、auth_system、podcast_api、music_downloader、services 全部切换
- 实测真实下载 5.2MB 音频完整成功

## 质量门禁归零
- ruff:0 错误(B904 全部修复,不再忽略)
- pyright:0 错误(类型收窄修复)
- pytest:140/140(含 golden 契约回归、root 模式 66 项路径覆盖)
- 真实 uvicorn 启动:/health、/、/static、受保护端鉴权全部正确

新增 tests/golden/responses.json:删除 Flask 前捕获的 32 例响应快照,
FastAPI 逐字段复现——删除巨石后行为回归仍有硬证据。
2026-09-26 11:10:17 +08:00

212 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 云村小助手 · 部署文档(仅 Docker/Linux 轨道)
> **轨道定位(2026-09-25)**:本文档**只覆盖 Docker/Linux 一键部署**这一条轨道。
> 正式部署轨道(Windows 工作站 + NSSM 服务 + PassNAT/Caddy HTTPS)以 `交接文档.md` 第 5/6 节为准——两份文档不要混用。
> 涵盖:Docker 一键部署、站点配置、安全机制说明与常见问题。
---
## 一、环境要求
| 项目 | 要求 |
| ---- | ---- |
| 操作系统 | Linux(推荐 CentOS 7+ / Ubuntu 18+ / Debian 10+) |
| Docker | 20.10+ |
| Docker Compose | v2.24+(`docker compose` 命令;compose 文件用了 env_file.path/required 语法,v2.24 以下请删掉 docker-compose.yml 中该两行) |
| 内存 | ≥ 1GB(含 ffmpeg 元数据写入建议 2GB) |
| 磁盘 | ≥ 5GB(下载文件与数据库备份) |
| 网络 | 服务器需能访问网易 API 与外网(IP 归属地检测、音频代理) |
---
## 二、文件说明
```
NeteaseUrl/
├── web/ # FastAPI 应用(唯一服务端)
│ ├── main.py # uvicorn 入口(python web/main.py)
│ ├── app.py # create_app 工厂(挂路由 / 静态资源 / 中间件)
│ ├── deps.py # 会话解析、当前用户、登录/管理员依赖
│ ├── billing.py # 计费依赖(预扣+开账同事务、只退 open 行)
│ ├── tasks_registry.py # 任务登记/启动(容量闸、账本承接)
│ ├── middleware.py # 安全头 + 音频直链签名保护
│ ├── ratelimit.py # 按 IP 滑动窗限流(与 core.state 共享桶)
│ ├── auth_state.py # 登录失败锁定 / 管理员 2FA 票据 / 发码限流
│ └── routers/ # 各领域路由(music/podcast/download/auth/admin…)
├── core/ # 框架无关核心层
│ ├── config.py # 常量与配置
│ ├── state.py # 进程内运行时状态(任务表/限流桶/缓存)
│ ├── db.py / repo.py # 异步 SQLite(WAL:读并发、写串行)
│ ├── http_client.py # aiohttp 连接池客户端
│ ├── aiohttp_compat.py # requests 同形异步垫片
│ ├── async_bridge.py # 同步↔异步桥(遗留同步调用点)
│ ├── session.py # itsdangerous 兼容会话编解码
│ ├── security.py # 音频 HMAC 签名
│ ├── net.py / media.py / utils.py / serializers… # 纯工具
├── services/runtime.py # 服务层(MusicAPIService、下载/打包 worker、任务监控)
├── auth_system.py # 站点账号系统(SQLite:用户/卡密/公告/日志/封禁/顶号)
├── music_api.py # 网易云音乐 API 封装(全异步)
├── music_downloader.py # 下载器(ffmpeg 元数据 / ZIP 打包)
├── podcast_api.py # 播客解析 API
├── qr_login.py # 网易云扫码登录
├── templates/index.html # 前端页面(原生 HTML/CSS/JS)
├── static/site_auth.js # 前端认证 / 个人中心 / 管理后台交互
├── pyproject.toml # 依赖与工具配置(uv 管理)
├── uv.lock # 精确锁定依赖版本
├── tests/ # 测试(含 golden 契约回归)
├── Dockerfile # 镜像构建文件(uv sync)
├── docker-compose.yml # 编排配置(端口 / 持久卷)
├── entrypoint.sh # 容器启动脚本
├── cookie.txt # 全局网易云账号 Cookie(部署后扫码生成,勿提交)
├── user_cookie.txt # 游客个人 Cookie(浏览器端,勿提交)
├── data/ # 站点数据库 site.db 与备份(运行时生成)
├── downloads/ # 下载文件目录(运行时生成)
├── 功能介绍.md # 功能清单
└── 部署文档.md # 本文档
```
---
## 三、快速部署(Docker Compose)
### 1. 上传源码
将整个项目目录上传至服务器,例如 `/www/wwwroot/Netease_url`。
### 2. 配置环境变量
项目根目录创建 `.env` 文件(也可直接使用,默认即可运行):
```ini
TZ=Asia/Shanghai
```
### 3. 构建并启动
```bash
cd /www/wwwroot/Netease_url
docker compose up -d --build
```
首次构建约 3-5 分钟(已配置阿里云加速源)。启动后检查:
```bash
curl http://127.0.0.1:5001/health
# 返回 {"status":200,...} 即部署成功
```
### 4. 访问
浏览器打开 `http://服务器IP:5001`(对外端口 5001,容器内 5000;勿改用 6000——浏览器会拦截 `ERR_UNSAFE_PORT`)。
---
## 四、初始配置(必读)
### 1. 管理员账号
新装实例的服务**首次启动时会在控制台随机打印初始管理员密码**(账号 `admin`,请翻阅启动日志获取)。
登录后自动进入后台 → 请立即在「用户管理」中**重置密码**。
**注意:管理员账号已升级两步验证登录(2026-09-24)**——输入正确的用户名+密码后,还需输入管理员绑定的邮箱并通过邮箱验证码验证,才能进入后台;请先在数据库或后台为管理员账号绑定可用邮箱。
### 2. 网易云全局账号
后台 →「全局 Cookie」→ 生成二维码 → 用网易云 App 扫码登录。
全局账号负责默认解析与下载,黑胶/SVIP 账号可解析更高音质。
### 3. SMTP 邮箱(开启用户注册必须配置)
后台 →「邮箱注册管理」→ 填写:
| 项 | 说明(以 QQ 邮箱为例) |
| ---- | ---- |
| SMTP 服务器 | `smtp.qq.com` |
| 端口 | `587` |
| 发件邮箱 | 你的 QQ 邮箱 |
| 邮箱密码/授权码 | QQ 邮箱「设置 → 账户 → 开启 SMTP」获取的**授权码**(非 QQ 密码) |
保存后用「发送测试邮件」验证。
### 4. 公告与卡密
- 后台 →「公告设置」:编辑公告内容与弹出策略(每次登录弹出 / 仅一次 / 不弹出)。
- 后台 →「次数卡密」:生成次数卡(张数、类型或自定义次数、前缀、备注、有效天数),用户在个人中心兑换充值。
---
## 五、站点机制说明
| 机制 | 说明 |
| ---- | ---- |
| 强制登录 | 所有解析 / 下载接口需登录;未登录弹窗引导注册/登录 |
| 按次计费 | 解析 / 试听 / 浏览免费;**下载扣次数**:单曲 1 次,打包按歌曲数(100 首歌单 = 100 次);失败不扣费;管理员不限 |
| 注册赠送 | 注册成功自动赠送 3 次下载次数 |
| 批量预检 | 打包下载前检查次数,不足可选择「仅下载前 N 首(集)」或取消 |
| 顶号机制 | 同一账号新设备登录后旧会话立即失效 |
| 防倒卖封禁 | 登录记录 IP 归属省份,24h 内 ≥3 个不同省份自动封禁;管理员可手动封禁 / 解封 |
| 音频防护 | 音频直链经服务器签名代理(HMAC + 36 分钟时效),真实 CDN 链接不暴露 |
| 日志审计 | 成功 / 失败日志 10 条每页分页,可清除;记录封禁、顶号、扣费等关键事件(不含普通登录注册) |
---
## 六、数据持久化
`docker-compose.yml` 已配置挂载,**重建容器数据不丢失**:
| 宿主机路径 | 容器路径 | 内容 |
| ---- | ---- | ---- |
| `./cookie.txt` | `/app/cookie.txt` | 全局网易云 Cookie |
| `./user_cookie.txt` | `/app/user_cookie.txt` | 游客个人 Cookie(兼容) |
| `./downloads/` | `/app/downloads` | 下载文件 |
| `./data/` | `/app/data` | 站点数据库 `site.db`(用户/卡密/日志/公告)与自动备份 |
> 建议定期在 后台 →「数据库管理」下载备份;更换服务器时将整个目录拷贝即可完整迁移。
---
## 七、常用运维命令
```bash
# 启动 / 重建(代码更新后)
docker compose up -d --build
# 查看运行日志
docker logs -f netease_url-netease-url-1
# 重启
docker compose restart
# 停止
docker compose down # 数据保留(挂载卷)
```
---
## 八、常见问题
**Q1:端口被占用(5001 already allocated)**
`docker ps` 查看占用容器并 `docker rm -f 容器名`,或修改 `docker-compose.yml` 端口映射。
**Q2:页面样式/功能异常**
浏览器 **Ctrl+F5** 强制刷新缓存(前端资源带版本号,一般自动生效)。
**Q3:收不到邮箱验证码**
检查 SMTP 配置与授权码;确认服务器出站 587 端口可用;查看失败日志定位报错。
**Q4:用户反馈「已被封禁」**
后台 →「用户管理」查看该用户最近登录省份与封禁原因,确认无误后可解封。
**Q5:忘记管理员密码**
```bash
docker exec -it netease_url-netease-url-1 python3 -c "
import auth_system as a
# 若实例管理员已由 admin 更名(如 qfbsh),请把 'admin' 替换为实际用户名
a.set_user_password(a.get_user_by_name('qfbsh')['id'], '新密码至少8位')
print('已重置')"
```
**Q6:数据库损坏 / 恢复**
后台 →「数据库管理」→ 上传历史备份文件即可覆盖恢复。
---