Files
Nexus/docs/project/nexus-1panel-operations-knowledge.md
T
Nexus Deploy 5a56e5a8cb fix(1panel): 安装向导脱敏、配置一致性与 nx update 门控回滚
- /state 白名单脱敏;init-db db_port 修复;connection-check 后清空 redis_pass
- install.html sessionStorage token 与无 token 友好提示
- nx update: 镜像 import 门控、健康失败自动回滚、PENDING=0 回写、卷双写
- Redis 容器改名密码迁移;备份失败默认 WARN;update.sh 管道 ROOT 回退
2026-06-06 17:40:30 +08:00

415 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Nexus 6.0 — 1Panel + Docker 运维知识文档
| 项 | 内容 |
|----|------|
| 版本 | 2026-06-06 |
| 读者 | 运维、接续开发、AI Agent |
| 定位 | **1Panel 生产部署 SSOT**(安装向导、网络、MySQL/Redis、日常 nx update |
| 关联 | [deploy/README-1panel.md](../../deploy/README-1panel.md) · [nexus-functional-development-guide.md](nexus-functional-development-guide.md) · [2026-06-04-1panel-docker-production.md](../design/plans/2026-06-04-1panel-docker-production.md) |
---
## 1. 架构总览
### 1.1 生产拓扑(1Panel
```mermaid
flowchart LR
Internet --> OpenResty["OpenResty (host)"]
OpenResty -->|"127.0.0.1:8600"| Nexus["Nexus 容器"]
Nexus -->|"1Panel-mysql-xxxx:3306"| MySQL["1Panel MySQL"]
Nexus -->|"1Panel-redis-xxxx:6379"| Redis["1Panel Redis"]
Nexus --- VolState["卷 nexus-state (.env)"]
Nexus --- VolData["卷 nexus-web-data"]
MySQL --- Net["1panel-network"]
Redis --- Net
Nexus --- Net
```
**铁律**[1Panel 官方说明](https://github.com/1Panel-dev/1Panel/issues/11676)):
- 应用商店 MySQL/Redis 在 **`1panel-network`** 上,容器间用 **容器名** 通信。
- **禁止**在 Nexus 容器内用 `127.0.0.1``localhost``host.docker.internal` 连 1Panel MySQL/Redis。
- OpenResty 在宿主机网络,反代目标为 **`http://127.0.0.1:8600`**。
### 1.2 仓库关键目录
| 路径 | 职责 |
|------|------|
| `server/` | FastAPI 后端;`api/install.py` = 安装向导 API |
| `frontend/` | Vue 3 SPA 源码(14 页) |
| `web/app/` | 构建产物;**`install.html` 为独立静态页**Alpine.js,不经 Vite 路由) |
| `web/data/` | 运行时:`config.json``1panel-hosts.json` |
| `deploy/` | 1Panel 安装/升级、`nx`、验收与修复脚本 |
| `docker/` | `docker-compose.prod.yml``entrypoint.sh``.env.prod` |
| `Dockerfile.prod` | 多阶段:npm build + Python 镜像 |
### 1.3 两套 Compose
| 文件 | 服务 |
|------|------|
| `docker-compose.yml` | 本地 devnexus + mysql + redis |
| `docker-compose.prod.yml` | **生产:仅 nexus** |
| `docker-compose.1panel.yml` | 叠加:nexus 加入 `1panel-network` |
---
## 2. 启动模式与 `.env` 生命周期
### 2.1 安装模式 vs 正常模式
`server/main.py``is_install_mode()`**运行时**检测 `/app/.env` 是否存在。
| 模式 | 条件 | 可用能力 |
|------|------|----------|
| 安装模式 | 无 `/app/.env` | `/api/install/*``/app/install.html`、静态、`/health` |
| 正常模式 | 有完整 `.env` | 全 API、WebSocket、后台任务 |
### 2.2 配置存储四层
| 层级 | 位置 | 写入方 |
|------|------|--------|
| Compose 环境 | 宿主机 `docker/.env.prod` | `nexus-1panel.sh install` / `generate_nexus_secrets.py` |
| 应用根 | 容器 `/app/.env` | 安装向导步骤 3 `init-db` |
| 持久卷 | `nexus-state``/var/lib/nexus/.env` | `entrypoint.sh` 退出时同步 |
| Web 数据 | `nexus-web-data``/app/web/data/` | `config.json``1panel-hosts.json` |
**不可从 DB settings 覆盖**`SECRET_KEY``API_KEY``ENCRYPTION_KEY``DATABASE_URL`
### 2.3 Docker 安装状态机
```
install --fresh
→ docker/.env.prod: NEXUS_INSTALL_WIZARD_PENDING=1 + 预生成三密钥
→ entrypoint 不写 /app/.env,不阻塞等待 MySQL/Redis
浏览器步骤 3 init-db
→ 写 /app/.env、config.json、settings、.install_state.json
步骤 4 create-admin
→ 写 admins,自动 lock.install_locked
entrypoint EXIT trap
→ /app/.env 复制到 nexus-state
```
**重要**:仅删除 1Panel 里的 MySQL 库 **不会** 清除 `/app/.env`;向导会提示「系统已初始化,无法重复执行数据库安装」。重装需删卷内 `.env` 并设 `NEXUS_INSTALL_WIZARD_PENDING=1`(见 §7.6)。
---
## 3. 安装向导(5 步)
### 3.1 流程与 API
| 步 | UI | API | 说明 |
|----|-----|-----|------|
| 1 | 欢迎 | — | 准备项 |
| 2 | 环境检测 | `GET /api/install/env-check` | TCP 探测 MySQL/Redis;返回 `docker_defaults` |
| 3 | 数据库配置 | `POST /api/install/test-credentials` | **必须先检测账号密码** |
| 3 | 初始化 | `POST /api/install/init-db` | 建表、三写、发 `install_token`**.env 已存在则 403** |
| 4 | 管理员 | `GET /api/install/connection-check` | 读 `.env` 验 MySQL+Redis |
| 4 | 创建 admin | `POST /api/install/create-admin` | 需 `install_token` |
| 5 | 完成 | `POST /api/install/lock`(兜底) | 写 `.install_locked`**Docker 模式展示 1Panel 守护清单** |
辅助:`GET /status``GET /state`(断点续装;**白名单脱敏**,不含 `install_token`/`redis_pass`,有 token 时仅 `has_token: true`)。
实现文件:`server/api/install.py``web/app/install.html`
### 3.2 步骤 3 表单(1Panel 正确填法)
| 字段 | MySQL | Redis |
|------|-------|-------|
| 主机 | `1Panel-mysql-xxxx` | `1Panel-redis-xxxx` |
| 端口 | `3306` | `6379` |
| 库名 | `nexus` | 库号 `0` |
| 用户名 | `nexus` | **无**1Panel Redis 无账号;向导仅填密码) |
| 密码 | 1Panel「数据库」里建的 nexus 密码 | 1Panel Redis **应用参数**中的口令 |
### 3.3 进程守护(1Panel Docker
| 层级 | 机制 | 说明 |
|------|------|------|
| Layer 1 | Compose `restart: unless-stopped` + `healthcheck` | 容器崩溃自动拉起 |
| Layer 2 | Python `self_monitor`(30s) | 向导完成后正常模式自动运行 |
| Layer 3 | 宿主机 OpenResty + 可选 `health_monitor.sh` | 反代 `127.0.0.1:8600`;见 `deploy/1panel/openresty-nexus.conf.example` |
`init-db``NEXUS_DOCKER_WRITE_ENV=1` 时调用 `_configure_docker_guardian`**不**在容器内写 Supervisor)。
### 3.4 Docker 预填来源
优先级(`_onepanel_service_host`):
1. 环境变量 `NEXUS_1PANEL_DB_HOST` / `NEXUS_1PANEL_REDIS_HOST`
2. `/app/web/data/1panel-hosts.json``nx update` 写入卷)
3. 回退 `host.docker.internal`**1Panel 场景错误**
`env-check``NEXUS_DOCKER_WRITE_ENV=1` 时返回 `docker_defaults`(主机/端口/库名,**不含** Redis 用户名)。前端会覆盖 stale 的 `127.0.0.1` / `host.docker.internal`,并隐藏 Redis 用户名字段。
### 3.5 连接 URL 格式(必读)
**MySQL**(写入 `NEXUS_DATABASE_URL`):
```
mysql+aiomysql://nexus:密码@1Panel-mysql-xxxx:3306/nexus
```
**Redis**(写入 `NEXUS_REDIS_URL`)— `server/api/install.py` `_build_redis_url`
| 场景 | URL 格式 |
|------|----------|
| 1Panel(常见,推荐) | `redis://:密码@1Panel-redis-xxxx:6379/0`(向导用户名留空) |
| 1Panel ACL default | `redis://default:密码@1Panel-redis-xxxx:6379/0` |
| 无密码 | `redis://1Panel-redis-xxxx:6379/0` |
**历史 bug807f4c2 前)**:生成 `redis://密码@host` 会把密码当成**用户名**,导致 `invalid username-password pair or user is disabled`。升级后须 `git pull` + `sync-install-wizard-to-container.sh`
---
## 4. 1Panel 部署流程
### 4.1 前置
1. 安装 1Panel + Docker
2. 应用商店安装 **MySQL**、**Redis**(自动创建 `1panel-network`
3. 1Panel「数据库」:库 `nexus`、用户 `nexus`(仅授权 `nexus` 库)
4. 记录 Redis 应用参数中的 **连接口令**(不是 MySQL 式账号)
### 4.2 安装 Nexus
```bash
# 新机(curl
curl -fsSL "http://66.154.115.8:3000/admin/Nexus/raw/branch/main/deploy/quick-install.sh" | bash
# 或已有仓库
cd /opt/nexus && bash deploy/install-nexus-fresh.sh --skip-clone
```
完成后:`https://<域名>/app/install.html`
### 4.3 `nx update` 自动 sync2026-06-06 根治版)
`deploy/nexus-1panel.sh` 在 install/upgrade 时:
1. `detect-1panel-services.sh` 探测容器名
2. 写入 `docker/.env.prod``NEXUS_1PANEL_*_HOST``NEXUS_REDIS_URL` 优先保留卷/向导中的 `redis://:pass@host`**不经 Compose 注入容器**
3. `write_1panel_hosts_volume``1panel-hosts.json`
4. 若存在 `1panel-network`,叠加 `docker-compose.1panel.yml`(仅 networks,无重复 environment
5. **已锁定**`sync_env_prod_to_volume``docker/.env.prod` 三密钥 + `NEXUS_REDIS_URL`/`NEXUS_DATABASE_URL` 双写至 `nexus-state`
6. **已锁定**`set_install_complete``NEXUS_INSTALL_WIZARD_PENDING=0` 回写 `docker/.env.prod`
### 4.4 OpenResty
- 1Panel → 网站 → 反代 `http://127.0.0.1:8600`
- HTTPS Let's Encrypt
- 参考:`deploy/1panel/openresty-nexus.conf.example``/ws/` 超时 ≥ 3600s
- **禁止**脚本修改 `/opt/1panel/apps/openresty/`
### 4.5 资源档位
| Profile | 说明 |
|---------|------|
| `1c4g` | 小机 |
| `2c8g` | 默认 |
| `4c16g` | `--profile 4c16g` |
持久化:`docker/.host-profile`
---
## 5. 日常运维:`nx` 与 `update`
| 命令 | 等价 |
|------|------|
| `nx` | 交互菜单 |
| `nx update` | `deploy/update.sh``nexus-1panel.sh upgrade` |
| `nexus-update` | 同上 |
**upgrade 顺序**2026-06-06+):
```
git fetch → MySQL 备份(失败默认 WARN)→ git reset --hard
→ sync_1panel_service_hosts → sync_env_prod_to_volume
→ tag 当前镜像为 nexus-prod-nexus:rollback
→ compose build → 镜像门控 (import server.main)
→ compose up -d --no-build
→(仅 install.html 非 200 时)sync-install-wizard-to-container.sh
→ set_install_complete → verify_health(端口 NEXUS_PUBLISH_PORT
→ 健康失败:自动 tag rollback + up -d 回滚
```
| 参数 | 含义 |
|------|------|
| `--check` | 仅查 Git |
| `--no-cache` | 无缓存重建镜像 |
| `--no-backup` | 跳过 mysqldump |
| `--require-backup` | mysqldump 失败则中止升级 |
| `--prune` | 清理悬空镜像 |
**推荐更新方式**`cd /opt/nexus && bash deploy/update.sh``curl \| bash` 会回退 `/opt/nexus` 并打印警告)。
### 5.1 密钥 / Redis URL 轮换(双写)
已锁定生产环境运行时以 **卷内** `/var/lib/nexus/.env` 为准。轮换步骤:
1. 修改宿主机 `docker/.env.prod``NEXUS_SECRET_KEY` / `NEXUS_API_KEY` / `NEXUS_ENCRYPTION_KEY``NEXUS_REDIS_URL`
2. 执行 `sudo nx update` — 脚本 `sync_env_prod_to_volume` 会同步至卷
3. 验收:`docker exec <nexus> redis-cli -u "$URL" ping``PONG``/health``ok`
Redis 容器改名时,`resolve_nexus_redis_url` 会尝试将旧 URL 中的密码迁移到新 host。
---
## 6. 脚本速查
| 脚本 | 用途 |
|------|------|
| [deploy/README-1panel.md](../../deploy/README-1panel.md) | 速查表 |
| `verify-1panel-install-wizard.sh` | 服务器一键验收 |
| `detect-1panel-services.sh` | 输出 `NEXUS_1PANEL_*_HOST` |
| `fix-1panel-mysql-grant.sh` | 修复 MySQL 1045`nexus@'%'` |
| `test-1panel-redis.sh` | **Redis 多格式认证诊断** |
| `sync-install-wizard-to-container.sh` | 热同步 `install.html` + `install.py` |
| `uninstall-mysql-compose.sh` | 清理旧内置 MySQL 栈 |
---
## 7. 故障排查决策树
### 7.1 Redis 认证失败
**症状**`invalid username-password pair` / `NOAUTH` / `wrongpass`
```
1. 主机是否为 1Panel-redis-xxxx?(不是 127.0.0.1
2. 是否误把口令当成「root 用户名」?(1Panel Redis **无账号**,只填密码)
3. 密码是否与 1Panel → Redis → 参数 一致?
4. 运行 `bash deploy/test-1panel-redis.sh` 看哪种 URL 可用
5. 运行诊断:
cd /opt/nexus && bash deploy/test-1panel-redis.sh
```
**在 Redis 容器内验证**
```bash
REDIS=$(docker ps --format '{{.Names}}' | grep -i '1Panel-redis' | head -1)
docker exec -it "$REDIS" redis-cli -u "redis://:你的密码@127.0.0.1:6379" ping
# 期望 PONG
```
**查真实配置**(密码与 ACL):
```bash
ls /opt/1panel/apps/redis/
grep -E 'requirepass|user ' /opt/1panel/apps/redis/*/conf/redis.conf 2>/dev/null
```
**修正已有 `.env`(步骤 3 已执行过)**
```bash
NEXUS=$(docker ps --format '{{.Names}}' | grep nexus-prod-nexus | head -1)
REDIS=$(grep '^NEXUS_1PANEL_REDIS_HOST=' /opt/nexus/docker/.env.prod | cut -d= -f2)
docker exec "$NEXUS" sed -i "s|^NEXUS_REDIS_URL=.*|NEXUS_REDIS_URL=\"redis://:你的密码@${REDIS}:6379/0\"|" /app/.env
docker restart "$NEXUS"
# 向导步骤 4 → 重新检测连接
```
### 7.2 MySQL 1045
**症状**`Access denied for user 'nexus'@'172.18.x.x'`
- TCP 已通,但用户仅 `nexus@localhost`
- 修复:`bash deploy/fix-1panel-mysql-grant.sh`(需 1Panel MySQL **root** 密码,非 nexus 用户)
### 7.3 host.docker.internal
**症状**`Can't connect to MySQL/Redis on 'host.docker.internal'`
```bash
cd /opt/nexus
bash deploy/detect-1panel-services.sh
nx update --no-cache
bash deploy/verify-1panel-install-wizard.sh
```
### 7.4 系统已初始化,无法重复执行数据库安装
- `/app/.env` 已存在,**不要**再点步骤 3 初始化
- 若 Redis 错:改 `.env``NEXUS_REDIS_URL`(§7.1)→ 步骤 4 重检
- 若需完全重装:
```bash
NEXUS=$(docker ps --format '{{.Names}}' | grep nexus-prod-nexus | head -1)
docker exec "$NEXUS" rm -f /app/.env /app/.install_state.json /app/.install_locked
docker run --rm -v nexus-prod_nexus-state:/data alpine:3.19 rm -f /data/.env
# 确认 docker/.env.prod 中 NEXUS_INSTALL_WIZARD_PENDING=1
nx update --no-cache
```
### 7.5 外网 HTTPS 失败、本机 8600 正常
- 配置 OpenResty 反代 + SSL
- `curl -s http://127.0.0.1:8600/health``ok`
- `curl -sk https://域名/health` → 应 `ok`
### 7.6 install.html 非 200
```bash
bash deploy/sync-install-wizard-to-container.sh
# 或 nx update --no-cache
```
---
## 8. 验收清单
```bash
cd /opt/nexus && bash deploy/verify-1panel-install-wizard.sh
```
关键 `[PASS]`
- Git ≥ `b25d079`1Panel sync
- `NEXUS_1PANEL_DB_HOST` / `NEXUS_1PANEL_REDIS_HOST`
- Nexus 在 `1panel-network`
- `/app/.env` 不存在(安装模式)或连接检测全绿
- `env-check``docker_defaults.db_host``1Panel-mysql-*`
浏览器:步骤 3 **先检测** → 初始化 → 步骤 4 创建 admin → `/app/` 登录。
---
## 9. 提交修复索引
| 提交 | 主题 |
|------|------|
| `b25d079` | `nx update` sync 1Panel 容器名;upgrade 补 `sync_1panel_service_hosts` |
| `d0544c9` | `fix-1panel-mysql-grant.sh`MySQL 1045 友好错误 |
| `da061d3` | 步骤 3 `test-credentials` 门禁 |
| `807f4c2` | Redis URL `redis://:pass@` 修复(曾误加 root,已废弃) |
| `3b2856f+` | 自动解析 `:pass@` / `default`;步骤 4 connection-check 可自愈 `.env` |
---
## 10. 与功能开发 SSOT 的差异
| 点 | `nexus-functional-development-guide.md` §16 | 1Panel 实装 |
|----|---------------------------------------------|-------------|
| 步骤 2/3 | 与 init-db 合并描述 | 步骤 2 仅 env-check;步骤 3 含 test-credentials |
| 配置三写 | 提及 `config.php` | 现为 `config.json` |
| 生产部署 §18 | Supervisor + 宝塔 | 以 `nexus-1panel.sh` / `nx` 为主 |
| Redis 主机 | 泛化为 localhost | **1Panel 必须容器名 + 仅密码(`:pass@`** |
---
## 11. 相关文档
- [nexus-functional-development-guide.md](nexus-functional-development-guide.md) — 全栈功能 SSOT
- [nexus-functional-development-guide-appendix.md](nexus-functional-development-guide-appendix.md) — API 附录
- [production-verification-checklist.md](production-verification-checklist.md) — L5
- [linux-dev-paths.md](linux-dev-paths.md) — 本地路径
- [../changelog/](../changelog/) — 按日变更记录
---
*本文档随 1Panel 部署实践更新;代码行为以 `server/api/install.py` 与 `deploy/nexus-1panel.sh` 为准。*