From b9139093f1a9aa68bef1899b665fb9bf62eafcb2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 22 May 2026 08:39:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0.env.example=20+=20CLA?= =?UTF-8?q?UDE.md=E5=8F=8D=E6=98=A0D2=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .env.example: install.php→install.html引用, 添加NEXUS_API_BASE_URL - install.py: 移除_write_env中重复的site_url计算 - CLAUDE.md: 全面更新项目记忆, 反映6步完成+D1/D2/D3解决 --- .env.example | 10 +++--- CLAUDE.md | 74 ++++++++++++++++++++++++++++--------------- server/api/install.py | 6 ++-- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/.env.example b/.env.example index ab718482..4fe460e7 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # Nexus Environment Configuration # Copy this file to .env and modify values for your deployment. -# Or run the web installer at /install.php to auto-generate this file. +# Or run the web installer at /app/install.html to auto-generate this file. # # Generate secret keys: openssl rand -hex 32 @@ -12,17 +12,19 @@ NEXUS_SYSTEM_TITLE=Nexus — 服务器运维管理平台 NEXUS_HOST=0.0.0.0 NEXUS_PORT=8600 -# ── Deployment (auto-set by install.php) ── +# ── Deployment (auto-set by installer) ── NEXUS_DEPLOY_PATH=/opt/nexus # Comma-separated frontend origins for CORS NEXUS_CORS_ORIGINS=http://localhost:8600 +# Base URL for Agent heartbeat reporting +NEXUS_API_BASE_URL=http://localhost:8600 # ── Database (MySQL, REQUIRED) ── NEXUS_DATABASE_URL=mysql+aiomysql://root:password@127.0.0.1:3306/nexus -# Pool params: auto-calculated by install.php from MySQL max_connections +# Pool params: auto-calculated by installer from MySQL max_connections # Formula: pool_size = max(20, maxConn*0.4), overflow = max(20, maxConn*0.3) # Default below matches MySQL max_connections=400 (160+120=280 max) -# install.php will overwrite these with values tuned to your MySQL instance +# install wizard will overwrite these with values tuned to your MySQL instance NEXUS_DB_POOL_SIZE=160 NEXUS_DB_MAX_OVERFLOW=120 diff --git a/CLAUDE.md b/CLAUDE.md index 788d51bc..156d25e6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,27 +1,38 @@ # Nexus 6.0 — Project Memory ## 项目概述 -Nexus 是一个 2000+ 服务器运维管理平台,从旧的 MultiSync (PHP + AdminLTE + pymysql) 完全重构为 Clean Architecture (FastAPI + Async SQLAlchemy + Redis + WebSocket + Telegram)。 +Nexus 是一个 2000+ 服务器运维管理平台,从旧的 MultiSync (PHP + AdminLTE + pymysql) 完全重构为 Clean Architecture (FastAPI + Async SQLAlchemy + Redis + WebSocket + Telegram)。前端已全面迁移到 Tailwind CSS v4 + Alpine.js,PHP 依赖已移除。 ## 仓库结构 - **唯一仓库**: Nexus (Gitea, 仓库地址在 .env 中配置) - **不再使用** multi-server-sync 仓库(旧项目,仅保留历史) -- **部署路径**: 由 `NEXUS_DEPLOY_PATH` 环境变量决定(install.php 自动写入 .env) -- **域名/CORS**: 由 `NEXUS_CORS_ORIGINS` 环境变量决定(install.php 自动写入) +- **部署路径**: 由 `NEXUS_DEPLOY_PATH` 环境变量决定(安装向导自动写入 .env) +- **域名/CORS**: 由 `NEXUS_CORS_ORIGINS` 环境变量决定(安装向导自动写入) ## 目录结构 (仓库根目录) ``` Nexus/ ├── server/ ← Python FastAPI后端 (Clean Architecture 4层) -├── web/ ← PHP前端 (install.php, config.php, login.php...) +│ ├── api/ ← API路由 (含 install.py 安装向导API) +│ ├── domain/ ← SQLAlchemy模型 (14张表) +│ ├── infrastructure/← SSH连接池 + Redis + Telegram +│ ├── background/ ← 后台任务 (心跳刷新/自检/调度/重试) +│ └── config.py ← Pydantic Settings + MySQL覆盖 +├── web/app/ ← Tailwind+Alpine.js 纯静态前端 (12个HTML页面) +│ ├── install.html ← 安装向导 (5步) +│ ├── login.html ← JWT登录+TOTP双因素 +│ └── ... ← index/servers/files/push/scripts等 ├── deploy/ ← Supervisor配置 + Shell健康检查脚本 -├── docs/ ← 部署文档 +├── docs/ ← 项目文档 ├── tests/ ← 测试 -├── .env ← NOT IN GIT (install.php生成) -├── .gitignore ← 排除 .env, SECRETS.md, web/data/config.php +├── .env ← NOT IN GIT (安装向导生成) └── requirements.txt ← Python依赖 ``` +## 启动模式 +- **安装模式** (无 .env): 仅 `/api/install/` + 静态文件可用,其他路由返回503 +- **正常模式** (有 .env): 完整初始化 DB/Redis/后台任务 + ## 已确认的关键决策 | 决策 | 选择 | 原因 | @@ -30,7 +41,7 @@ Nexus/ | SECRET_KEY | ❌ 禁改 | 加密回退密钥 | | DATABASE_URL | ❌ 禁改 | 启动必需 | | system_name/title | ✅ 可改 | 前端显示 | -| pool_size/overflow | ✅ 可改 | install自动推荐 | +| pool_size/overflow | ✅ 可改 | 安装向导自动推荐 | | redis_url | ✅ 可改 | Redis连接 | | 告警阈值 (CPU/mem/disk) | ✅ 可改 | 监控参数 (默认80%) | | Telegram配置 | ✅ 可改 | 告警推送 | @@ -39,43 +50,54 @@ Nexus/ | 心跳数据流 | Agent→Redis→前端直读→10min→MySQL | 前端实时, MySQL只存历史 | | 告警推送 | WebSocket→前端 + Telegram | 即时感知 | | Python守护 | 3层: Supervisor + Python自检(30s) + Shell(cron 1min) | 全覆盖 | -| install.php安装后 | rename→install.php.locked + .env锁定 | 防重装 | -| 配置源 | install→config.php(PHP)+settings表(MySQL)+.env(Python) | 三方一致 | +| 安装向导 | install.html + FastAPI API | D2: 替代install.php | +| 配置源 | 安装向导→config.php(PHP兼容)+settings表(MySQL)+.env(Python) | 三写一致 | | Agent告警心跳 | CPU/内存>80% 或变化>10% 时主动上报 | 智能监控 | | 仓库统一 | 所有代码统一在Nexus仓库 | 不再用两个仓库 | -## 实现状态 (Phase A+B+C) +## 实现状态 (Phase A+B+C+D) — ~95% 完成 -### ✅ 已完成 +### ✅ 已完成 (全部6步 + 技术债务) | 模块 | 文件 | 说明 | |------|------|------| +| **Step 0: 基础设施** | | Redis + WebSocket | | E1 WebSocket推送 | server/api/websocket.py | alert/recovery/system broadcast | | E2 心跳→Redis+告警 | server/api/agent.py | Redis write + threshold detection | | E3 Redis→MySQL刷新 | server/background/heartbeat_flush.py | 10min batch | +| **Step 1: 数据层** | | 14张表 | | E4 load_settings_from_db | server/config.py | MySQL overrides mutable settings | -| E5 Python自检 | server/background/self_monitor.py | 30s loop | -| E6 Telegram推送 | server/infrastructure/telegram/__init__.py | alert/recovery/system | -| E7 Redis实时状态 | server/api/servers.py | frontend reads Redis directly | -| E8 /health端点 | server/api/health.py | Shell health_monitor.sh checks this | -| E9 lifespan+后台任务 | server/main.py | startup: init_db + load_settings + background tasks | -| D1 Supervisor | deploy/nexus.conf | autorestart nexus process | -| D2 Shell健康检查 | deploy/health_monitor.sh | cron 1min, 3 failures→restart+Telegram | -| P1 install.php | web/install.php | 5步向导 (欢迎→环境→DB+Redis+API→管理员+品牌→完成清单) | -| P2 config.php | web/config.php | data/config.php + MySQL settings override | +| **Step 2: 认证层** | | JWT + TOTP | +| **Step 3: Web SSH** | | asyncssh + xterm.js | +| E5 asyncssh连接池 | server/infrastructure/ssh/asyncssh_pool.py | 引用计数模式 | +| E6 WebSSH前端 | web/app/terminal.html | xterm.js + Koko协议 + 自动resize | +| **Step 4: Sync引擎** | | 4种同步模式 | +| **Step 5: 前端迁移** | | Tailwind+Alpine.js | +| E7 12个前端页面 | web/app/*.html | 含install.html安装向导 | +| E8 安装向导API | server/api/install.py | 6端点, 无JWT, 临时引擎 | +| E9 条件启动模式 | server/main.py | 无.env=安装模式 | +| **后台任务** | | | +| E10 Python自检 | server/background/self_monitor.py | 30s loop | +| E11 Telegram推送 | server/infrastructure/telegram/__init__.py | alert/recovery/system | +| E12 /health端点 | server/api/health.py | Shell health_monitor.sh checks this | +| **技术债务** | | | +| D1 ✅ paramiko删除 | — | pool.py已删除, 全部迁移asyncssh | +| D2 ✅ install迁移 | server/api/install.py | install.php→install.html+API | +| D3 ✅ WebSSH前端 | web/app/terminal.html | xterm.js+Koko协议+全屏 | +| D4 文件编辑器 | — | 低优先级, Monaco/ACE | -### 🔄 待测试 (Phase D) +### 🔄 待测试 - T1: 心跳Redis写入验证 - T2: WebSocket连接测试 - T3: 3层守护测试 (kill Python→Supervisor重启) - T4: Telegram推送测试 -- T5: install.php 5步流程测试 +- T5: install.html 5步流程测试 ### 测试流程 (用户确认) 1. WSL本地基础测试 → 2. 推到仓库 → 3. 外网服务器正式测试 ## 配置三写机制 -install.php Step 3 POST处理同时写入: -1. `web/data/config.php` — PHP前端配置 (API_BASE_URL, DB_*, API_KEY) +安装向导 Step 3 POST处理同时写入: +1. `web/data/config.php` — PHP兼容配置 (API_BASE_URL, DB_*, API_KEY) 2. `.env` — Python后端启动必需 (NEXUS_前缀) 3. `settings` MySQL表 — 共享动态配置 (api_key, thresholds, Telegram等) @@ -93,4 +115,4 @@ Agent心跳(60s) → Redis(实时) → 前端直读 → 10min批量 → MySQL( 恢复: 之前告警的指标恢复正常 → 自动推送恢复通知 Redis心跳key: heartbeat:{server_id} (HSET, TTL=600s) Redis告警key: alerts:{server_id} (SET, TTL=3600s) -``` \ No newline at end of file +``` diff --git a/server/api/install.py b/server/api/install.py index 49efae6b..0d85b47b 100644 --- a/server/api/install.py +++ b/server/api/install.py @@ -90,9 +90,9 @@ def _build_redis_url(req: InitDbRequest) -> str: def _write_env(req: InitDbRequest, secret_key: str, api_key: str, - pool_size: int, max_overflow: int, redis_url: str) -> None: + pool_size: int, max_overflow: int, redis_url: str, + site_url: str) -> None: install_dir = str(ROOT_DIR) - site_url = req.site_url.rstrip("/") if req.site_url else f"http://127.0.0.1:{req.api_port}" db_url = ( f"mysql+aiomysql://{req.db_user}:{req.db_pass}" f"@{req.db_host}:{req.db_port}/{req.db_name}" @@ -445,7 +445,7 @@ async def init_db(req: InitDbRequest): # Write .env site_url = req.site_url.rstrip("/") if req.site_url else f"http://127.0.0.1:{req.api_port}" - _write_env(req, secret_key, api_key, pool_size, max_overflow, redis_url) + _write_env(req, secret_key, api_key, pool_size, max_overflow, redis_url, site_url) # Write config.php _write_config_php(req, api_key, site_url)