1
This commit is contained in:
+247
-17
@@ -207,35 +207,249 @@ npm run build # 产物直接覆盖 admin/dist/,即 vm 站点根目录
|
||||
|
||||
## 6. nginx 配置(宝塔管理)
|
||||
|
||||
配置文件:`/www/server/panel/vhost/nginx/{h5,vm,vapi,codeserver}.256kb.top.conf`。
|
||||
配置文件:`/www/server/panel/vhost/nginx/{h5,vm,vapi}.256kb.top.conf`。
|
||||
改配置在宝塔面板「网站 → 设置 → 配置文件」编辑,或改文件后 `nginx -t && nginx -s reload`。
|
||||
|
||||
关键规则摘要:
|
||||
证书路径(acme.sh ECC 证书,自动续期):
|
||||
- `/www/server/panel/vhost/cert/<域名>/fullchain.pem`
|
||||
- `/www/server/panel/vhost/cert/<域名>/privkey.pem`
|
||||
|
||||
**h5.256kb.top**
|
||||
站点日志在 `/www/wwwlogs/<域名>.log` 和 `/www/wwwlogs/<域名>.error.log`(排查 App 接口 401/500 时非常管用)。
|
||||
|
||||
### 6.1 h5.256kb.top(用户下载页 + HLS 资源)
|
||||
|
||||
```nginx
|
||||
root /root/project/video/h5; # index.html 下载页
|
||||
location /downloads/ { alias /root/project/video/runtime/downloads/; } # APK
|
||||
location /videos/ { alias /root/project/video/runtime/videos/; }
|
||||
location /uploads/ { alias /root/project/video/runtime/uploads/; }
|
||||
location /r/ { proxy_pass http://127.0.0.1:8000; } # 邀请落地
|
||||
location /api/v1/invite/ { proxy_pass http://127.0.0.1:8000; }
|
||||
server {
|
||||
listen 80;
|
||||
server_name h5.256kb.top;
|
||||
# ACME 验证保留在 80,其余跳 HTTPS
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name h5.256kb.top;
|
||||
ssl_certificate /www/server/panel/vhost/cert/h5.256kb.top/fullchain.pem;
|
||||
ssl_certificate_key /www/server/panel/vhost/cert/h5.256kb.top/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
index index.html;
|
||||
root /root/project/video/h5;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
|
||||
# 禁止访问隐藏文件
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# APK 下载
|
||||
location /downloads/ {
|
||||
alias /root/project/video/runtime/downloads/;
|
||||
autoindex off;
|
||||
}
|
||||
|
||||
# HLS 视频(hls.js 需要跨域 + 正确 MIME)
|
||||
location /videos/ {
|
||||
alias /root/project/video/runtime/videos/;
|
||||
autoindex off;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
location ~* \.m3u8$ {
|
||||
add_header Content-Type application/vnd.apple.mpegurl;
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
location ~* \.ts$ {
|
||||
add_header Content-Type video/mp2t;
|
||||
add_header Cache-Control "max-age=86400";
|
||||
}
|
||||
}
|
||||
|
||||
# 上传资源
|
||||
location /uploads/ {
|
||||
alias /root/project/video/runtime/uploads/;
|
||||
autoindex off;
|
||||
}
|
||||
|
||||
# 邀请注册落地页 → 后端
|
||||
location /r/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# 邀请相关 API → 后端
|
||||
location /api/v1/invite/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/h5.256kb.top.log;
|
||||
error_log /www/wwwlogs/h5.256kb.top.error.log;
|
||||
}
|
||||
```
|
||||
|
||||
**vm.256kb.top**
|
||||
### 6.2 vm.256kb.top(管理后台 Vue SPA + 后端 API)
|
||||
|
||||
```nginx
|
||||
root /root/project/video/admin/dist;
|
||||
location / { try_files $uri $uri/ /index.html; } # SPA 回退
|
||||
location /api/ { proxy_pass http://127.0.0.1:8000; }
|
||||
location /static/ { proxy_pass http://127.0.0.1:8000; }
|
||||
location /r/ { proxy_pass http://127.0.0.1:8000; }
|
||||
server {
|
||||
listen 80;
|
||||
server_name vm.256kb.top;
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name vm.256kb.top;
|
||||
ssl_certificate /www/server/panel/vhost/cert/vm.256kb.top/fullchain.pem;
|
||||
ssl_certificate_key /www/server/panel/vhost/cert/vm.256kb.top/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
index index.html;
|
||||
root /root/project/video/admin/dist;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# 后端 API
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# 后端本地静态资源(uploads 挂载点)
|
||||
location /static/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# 邀请落地页
|
||||
location /r/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
}
|
||||
|
||||
# Vue SPA history 路由回退
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/vm.256kb.top.log;
|
||||
error_log /www/wwwlogs/vm.256kb.top.error.log;
|
||||
}
|
||||
```
|
||||
|
||||
**vapi.256kb.top**:`location / { proxy_pass http://127.0.0.1:8000; }` 全量反代。
|
||||
### 6.3 vapi.256kb.top(App 接口域名,全量反代)
|
||||
|
||||
站点日志在 `/www/wwwlogs/<域名>.log`(排查 App 接口 401/500 时非常管用)。
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name vapi.256kb.top;
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name vapi.256kb.top;
|
||||
ssl_certificate /www/server/panel/vhost/cert/vapi.256kb.top/fullchain.pem;
|
||||
ssl_certificate_key /www/server/panel/vhost/cert/vapi.256kb.top/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /www/wwwroot/acme-challenge/;
|
||||
}
|
||||
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# 全部反代到 FastAPI
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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;
|
||||
# 上传大视频需要
|
||||
client_max_body_size 500m;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/vapi.256kb.top.log;
|
||||
error_log /www/wwwlogs/vapi.256kb.top.error.log;
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 证书签发与续期(acme.sh)
|
||||
|
||||
```bash
|
||||
# 首次签发(三个域名各一次,ECC 证书)
|
||||
~/.acme.sh/acme.sh --issue -d h5.256kb.top --webroot /www/wwwroot/acme-challenge/ --keylength ec-256
|
||||
~/.acme.sh/acme.sh --issue -d vm.256kb.top --webroot /www/wwwroot/acme-challenge/ --keylength ec-256
|
||||
~/.acme.sh/acme.sh --issue -d vapi.256kb.top --webroot /www/wwwroot/acme-challenge/ --keylength ec-256
|
||||
|
||||
# 安装到宝塔证书目录(签发后 acme.sh 会自动 deploy 到 reloadcmd)
|
||||
~/.acme.sh/acme.sh --install-cert -d h5.256kb.top --ecc \
|
||||
--fullchain-file /www/server/panel/vhost/cert/h5.256kb.top/fullchain.pem \
|
||||
--key-file /www/server/panel/vhost/cert/h5.256kb.top/privkey.pem \
|
||||
--reloadcmd "nginx -t && nginx -s reload"
|
||||
# vm / vapi 同理
|
||||
|
||||
# acme.sh 已在 crontab 注册续期任务,可用以下命令查看
|
||||
crontab -l | grep acme
|
||||
```
|
||||
|
||||
### 6.5 检查/排错
|
||||
|
||||
```bash
|
||||
nginx -t # 校验语法
|
||||
nginx -s reload # 平滑重载
|
||||
nginx -T | grep -A 20 'server_name vm' # 看实际生效配置
|
||||
tail -f /www/wwwlogs/vapi.256kb.top.error.log
|
||||
```
|
||||
|
||||
## 7. App 编译与发版
|
||||
|
||||
@@ -339,6 +553,8 @@ curl -I https://h5.256kb.top/downloads/video-app.apk # 200
|
||||
|
||||
## 11. 新环境从零部署速查
|
||||
|
||||
**手动步骤**(理解流程用):
|
||||
|
||||
1. 装 Docker / Python3.11 / Node18+ / Flutter / nginx(或宝塔)
|
||||
2. 建 mysql8、my-redis 容器(§3 命令)
|
||||
3. `server/` 建 venv、装依赖、写 `.env`、`alembic upgrade head`、建超管(§4.3)
|
||||
@@ -347,3 +563,17 @@ curl -I https://h5.256kb.top/downloads/video-app.apk # 200
|
||||
6. App:放入 keystore + key.properties → `deploy.sh` 发版(§7)
|
||||
7. 后台「系统配置」:`app.invite_base_url`、`app.version.android/ios` 等(见 03 接口文档配置键)
|
||||
8. 跑 §10.3 验证清单
|
||||
|
||||
**一键脚本**(推荐,已封装上面 1-6 步):
|
||||
|
||||
```bash
|
||||
bash /root/project/video/deploy-full.sh # 完整执行(首次部署)
|
||||
bash /root/project/video/deploy-full.sh --skip-apk # 已有 APK 跳过 App 编译
|
||||
bash /root/project/video/deploy-full.sh --skip-nginx # nginx 已配好,仅重启服务
|
||||
bash /root/project/video/deploy-full.sh --skip-admin # 跳过 admin 前端构建
|
||||
bash /root/project/video/deploy-full.sh --only-backend # 只重启后端 + 健康检查
|
||||
```
|
||||
|
||||
`deploy-full.sh` 与 `deploy.sh` 的区别:
|
||||
- `deploy.sh`:App 发版专用(编译 APK → 部署 → 同步 DB 版本号),日常迭代用
|
||||
- `deploy-full.sh`:整栈首装/重装/迁移恢复,覆盖 Docker / 后端 / nginx / 后台前端 / 证书 / APK
|
||||
|
||||
Reference in New Issue
Block a user