fix(1panel): grant nexus@% for Docker MySQL 1045 on install

Add fix-1panel-mysql-grant.sh and clearer install wizard errors when
1Panel MySQL only allows nexus@localhost.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Nexus Deploy
2026-06-06 06:19:19 +08:00
parent 3f5eacae60
commit d0544c9bd2
4 changed files with 141 additions and 0 deletions
+21
View File
@@ -9,6 +9,7 @@
| `install-nexus-fresh.sh` | 全新空库安装 | `bash deploy/install-nexus-fresh.sh --skip-clone` |
| **`update.sh`** | **一键更新** | `curl -fsSL ".../update.sh" \| bash` |
| `nexus-1panel.sh` | 底层 install / upgrade | `bash deploy/nexus-1panel.sh upgrade` |
| `fix-1panel-mysql-grant.sh` | 修复 1045 nexus@Docker | `bash deploy/fix-1panel-mysql-grant.sh` |
| **`nx`** | **统一运维菜单** | `nx` |
档位:`--profile 1c4g` · `2c8g`(默认)· `4c16g`
@@ -120,6 +121,26 @@ Docker 栈**仅含 Nexus 容器**。MySQL / Redis 在 **1Panel 应用商店**安
3. `nx update` 后打开安装向导步骤 3(主机应已预填 `1Panel-mysql-…`
4. 填写 MySQL 密码;Redis 若设了密码一并填写
### 常见错误 1045Access denied for 'nexus'@'172.18.x.x'
TCP 已通,但 MySQL 用户多为 **`nexus@localhost`**Docker 内 Nexus 从 **172.x** 连接会被拒绝。
在服务器执行(按提示输入 root 密码与 nexus 密码):
```bash
cd /opt/nexus && bash deploy/fix-1panel-mysql-grant.sh
```
或一次性:
```bash
MYSQL_ROOT_PASSWORD='1Panel里MySQL的root密码' \
NEXUS_DB_PASSWORD='向导里要填的nexus密码' \
bash /opt/nexus/deploy/fix-1panel-mysql-grant.sh
```
然后安装向导步骤 3**库名/用户 `nexus`**,主机为 `1Panel-mysql-xxxx`,密码与上面一致。
若仍报 `Can't connect to MySQL/Redis on 'host.docker.internal'`:说明 Nexus **未接入 1panel-network** 或未探测到容器名,在服务器执行:
```bash
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Grant nexus@'%' on 1Panel App Store MySQL for Docker (1panel-network) install wizard.
# Fixes: Access denied for user 'nexus'@'172.18.x.x' (1045)
#
# Usage:
# MYSQL_ROOT_PASSWORD='root密码' NEXUS_DB_PASSWORD='nexus密码' bash deploy/fix-1panel-mysql-grant.sh
# bash deploy/fix-1panel-mysql-grant.sh # prompts
set -euo pipefail
NEXUS_DB_NAME="${NEXUS_DB_NAME:-nexus}"
NEXUS_DB_USER="${NEXUS_DB_USER:-nexus}"
info() { echo -e "\033[0;32m[INFO]\033[0m $*"; }
warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; exit 1; }
pick_mysql_container() {
local name
if [[ -n "${MYSQL_CONTAINER:-}" ]]; then
echo "$MYSQL_CONTAINER"
return 0
fi
if docker network inspect 1panel-network >/dev/null 2>&1; then
name="$(docker network inspect 1panel-network --format '{{range .Containers}}{{.Name}} {{end}}' \
| tr ' ' '\n' | grep -iE '^1Panel-mysql-' | head -1 || true)"
[[ -n "$name" ]] && echo "$name" && return 0
fi
name="$(docker ps --format '{{.Names}}' | grep -iE '^1Panel-mysql-' | head -1 || true)"
[[ -n "$name" ]] && echo "$name" && return 0
error "未找到 1Panel MySQL 容器(可设 MYSQL_CONTAINER=名称)"
}
prompt_secret() {
local var="$1" prompt="$2"
if [[ -n "${!var:-}" ]]; then
return 0
fi
read -r -s -p "$prompt: " "$var"
echo ""
if [[ -z "${!var:-}" ]]; then
error "$var 不能为空"
fi
}
main() {
[[ "${EUID:-$(id -u)}" -eq 0 ]] || error "请用 root 运行"
local mysql_c
mysql_c="$(pick_mysql_container)"
info "MySQL 容器: $mysql_c"
prompt_secret MYSQL_ROOT_PASSWORD "1Panel MySQL root 密码"
prompt_secret NEXUS_DB_PASSWORD "nexus 用户密码(与安装向导步骤 3 一致)"
info "创建库/用户并授权 ${NEXUS_DB_USER}@'%' → ${NEXUS_DB_NAME}.* ..."
docker exec -i "$mysql_c" mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" <<SQL
CREATE DATABASE IF NOT EXISTS \`${NEXUS_DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${NEXUS_DB_USER}'@'%' IDENTIFIED BY '${NEXUS_DB_PASSWORD}';
ALTER USER '${NEXUS_DB_USER}'@'%' IDENTIFIED BY '${NEXUS_DB_PASSWORD}';
GRANT ALL PRIVILEGES ON \`${NEXUS_DB_NAME}\`.* TO '${NEXUS_DB_USER}'@'%';
FLUSH PRIVILEGES;
SELECT user, host FROM mysql.user WHERE user = '${NEXUS_DB_USER}';
SQL
info "完成。请在安装向导步骤 3 使用: 库/用户=${NEXUS_DB_NAME}/${NEXUS_DB_USER},密码与上面一致"
info "若已改 install.py,执行: bash deploy/sync-install-wizard-to-container.sh"
}
main "$@"
@@ -0,0 +1,27 @@
# 2026-06-06 — 1Panel MySQL 1045 授权修复
## 摘要
安装向导步骤 3 报 `Access denied for user 'nexus'@'172.18.x.x'`1Panel 常见仅 `nexus@localhost`Docker 网段连接被拒。新增 `fix-1panel-mysql-grant.sh` 与安装 API 明确错误提示。
## 动机
验收脚本已通过但 init-db 1045;需在仓库内提供可重复修复路径,避免手工 SQL 易错。
## 涉及文件
- `deploy/fix-1panel-mysql-grant.sh` — 创建/授权 `nexus@'%'`
- `server/api/install.py` — 1045 友好错误与 connection-check
- `deploy/README-1panel.md` — 1045 排障节
## 验证
```bash
MYSQL_ROOT_PASSWORD='...' NEXUS_DB_PASSWORD='...' bash deploy/fix-1panel-mysql-grant.sh
# 安装向导步骤 3 初始化成功
bash deploy/sync-install-wizard-to-container.sh # 同步 install.py 到运行中容器
```
## 迁移 / 重启
无 DB 迁移。`install.py` 变更需 `sync-install-wizard-to-container.sh``nx update --no-cache`
+23
View File
@@ -196,6 +196,22 @@ def _service_tcp_reachable(host: str, port: int, timeout: float = 3.0) -> bool:
return False
def _mysql_auth_error_detail(db_user: str) -> str:
"""1045 Access denied — common on 1Panel when user is only nexus@localhost."""
if os.environ.get("NEXUS_DOCKER_WRITE_ENV") != "1":
return (
f"MySQL 拒绝用户 {db_user!r} 的密码或主机权限。"
"请核对库名/用户名/密码,并确认该用户允许从应用主机连接(非仅 localhost)。"
)
return (
f"MySQL 拒绝用户 {db_user!r}(错误 1045)。Nexus 在 Docker 内通过 1panel-network 连接,"
"来源 IP 为容器网段(如 172.18.x.x),不是 localhost。\n"
"请在 1Panel MySQL 中确保:① 库 nexus、用户 nexus 已创建 ② 密码与向导一致 "
"③ 存在 nexus@'%' 或允许 Docker 网段(仅 nexus@localhost 会失败)。\n"
"服务器执行: cd /opt/nexus && bash deploy/fix-1panel-mysql-grant.sh"
)
def _mysql_connect_error_detail(host: str, port: int) -> str:
if os.environ.get("NEXUS_DOCKER_WRITE_ENV") != "1":
return ""
@@ -265,6 +281,11 @@ async def _test_mysql_url(db_url: str) -> tuple[bool, str]:
await engine.dispose()
return True, "✓ MySQL 连接正常"
except Exception as e:
err = str(e)
if "1045" in err or "Access denied" in err:
return False, _mysql_auth_error_detail(
urlparse(db_url).username or "nexus"
)
return False, f"✗ MySQL 连接失败: {e}"
@@ -805,6 +826,8 @@ async def init_db(req: InitDbRequest):
except Exception as e:
await engine.dispose()
err = str(e)
if "1045" in err or "Access denied" in err:
raise HTTPException(400, _mysql_auth_error_detail(req.db_user)) from e
if "2003" in err or "Can't connect to MySQL" in err:
extra = _mysql_connect_error_detail(req.db_host, db_port)
if extra: