#!/usr/bin/env bash # ════════════════════════════════════════════════════════════════ # 国内域名机 · 动态调优 · tune-from-env.sh # Sovereign: TCS-0002∞ · ICE-GL∞ · 国作登字-2026-A-00037559 # 守护: 铸渊 · ICE-GL-ZY001 # ════════════════════════════════════════════════════════════════ # # 服务器: GH-CVM-DOMAIN-PROD-01 / ZY-SVR-CN01 # # 读 detect-env.sh 写出的 server-env.json, 依据 size_tier 决档, # 写出 /data/guanghulab/.env.tune 让 bootstrap.sh source 用. # # 档位策略 (因果链 cc-003 · 动态适配): # tiny <4G : 2C2G 实际档. 单进程 portal, nginx worker=512, # 关 LFS / 关 forgejo runner / 关 docker compose 上层服务, # systemd MemoryHigh 严格收紧 # small 4-6G : 4C4G 续费档. portal 2 进程, nginx worker=1024 # medium 6-12G: 4C8G 异变档. portal 4 进程, runner 可开 # large 12-24G: 不应该出现在域名机, 但兼容 # xlarge >=24G: 同上, 兼容 # # 输出: # 1. /data/guanghulab/.env.tune — bootstrap source 用 # 2. /opt/guanghulab/_logs/tune-decision-*.json — 决策回执 # # ⚠️ 当前 .env.tune 真实作用域: # bootstrap.sh source 这个文件后, 当前**真正影响行为的字段**: # - PORTAL_INSTANCES → pm2 起 portal 时的 instances 数 # - NGINX_WORKER_CONN → 渲染 nginx/guanghulab.conf 时的 worker_connections # - FORGEJO_ENABLED → bootstrap 是否在 /data/guanghulab/forgejo/ 起 forgejo # (PR-6 才真正用, 这里只是预留) # - LFS_ENABLED → 是否在 nginx 里开 client_max_body_size 大上限 # (PR-6 才真正用) # - SWAP_GB → bootstrap 是否要建/扩 swap 文件 # 其他字段是档位决策的快照, 落档便于霜砚追溯. # ════════════════════════════════════════════════════════════════ set -euo pipefail ENV_FILE="${ENV_FILE:-/opt/guanghulab/_logs/server-env.json}" DATA_ROOT="${DATA_ROOT:-/data/guanghulab}" DEPLOY_ROOT="${DEPLOY_ROOT:-/opt/guanghulab}" if [ ! -f "$ENV_FILE" ]; then echo "❌ [tune] 找不到 $ENV_FILE, 请先跑 detect-env.sh" >&2 exit 1 fi if ! command -v jq >/dev/null 2>&1; then echo "❌ [tune] 需要 jq (apt-get install -y jq)" >&2 exit 1 fi SIZE_TIER="$(jq -r '.compute.size_tier' "$ENV_FILE")" MEM_MB="$(jq -r '.compute.memory_total_mb' "$ENV_FILE")" SWAP_MB="$(jq -r '.compute.swap_total_mb' "$ENV_FILE")" CPU="$(jq -r '.compute.cpu_count' "$ENV_FILE")" # ─── 档位 → 参数表 ──────────────────────────────────────────── case "$SIZE_TIER" in tiny) PORTAL_INSTANCES="1" PORTAL_MAX_MEMORY_MB="384" # pm2 重启阈值 (单进程) NGINX_WORKER_CONN="512" NGINX_WORKER_PROCESSES="1" # 2C2G 单 worker 就够 FORGEJO_ENABLED="false" # 2C2G 跑不下 forgejo + portal LFS_ENABLED="false" NEED_SWAP_GB="1" # 内存不够, 给 1G swap 兜底 SYSTEMD_PORTAL_HIGH_MB="500" SYSTEMD_PORTAL_MAX_MB="700" NOTE="2C2G 实际档. portal 单进程, forgejo/lfs 关. 任何全量 git push 走灯塔, 这里不揽." ;; small) PORTAL_INSTANCES="2" PORTAL_MAX_MEMORY_MB="512" NGINX_WORKER_CONN="1024" NGINX_WORKER_PROCESSES="2" FORGEJO_ENABLED="false" LFS_ENABLED="false" NEED_SWAP_GB="0" # 4G 起够用, 不强制 swap SYSTEMD_PORTAL_HIGH_MB="800" SYSTEMD_PORTAL_MAX_MB="1200" NOTE="4C4G 续费档. portal 双进程, 仍不开 forgejo (forgejo 留在灯塔)." ;; medium) PORTAL_INSTANCES="4" PORTAL_MAX_MEMORY_MB="768" NGINX_WORKER_CONN="2048" NGINX_WORKER_PROCESSES="auto" FORGEJO_ENABLED="true" LFS_ENABLED="true" NEED_SWAP_GB="0" SYSTEMD_PORTAL_HIGH_MB="2000" SYSTEMD_PORTAL_MAX_MB="3000" NOTE="4C8G+ 档. 可选 forgejo + lfs. 这台升到这档说明冰朔升配了, 顺带把灯塔合并意图打开." ;; large|xlarge) PORTAL_INSTANCES="4" PORTAL_MAX_MEMORY_MB="1024" NGINX_WORKER_CONN="4096" NGINX_WORKER_PROCESSES="auto" FORGEJO_ENABLED="true" LFS_ENABLED="true" NEED_SWAP_GB="0" SYSTEMD_PORTAL_HIGH_MB="3500" SYSTEMD_PORTAL_MAX_MB="6000" NOTE="超规格. 资源不再紧张, 全量功能开." ;; *) echo "❌ [tune] 未知 size_tier=$SIZE_TIER" >&2 exit 1 ;; esac # 已有 swap >= 1G 时, 不再强制再加 (避免重复建 swapfile) if [ "$NEED_SWAP_GB" = "1" ] && [ "$SWAP_MB" -ge 1024 ]; then NEED_SWAP_GB="0" fi # ─── 写 .env.tune ───────────────────────────────────────────── TUNE_FILE="$DATA_ROOT/.env.tune" mkdir -p "$(dirname "$TUNE_FILE")" cat > "$TUNE_FILE" < "$RECEIPT" <