310 lines
13 KiB
Bash
310 lines
13 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
# =============================================================================
|
|||
|
|
# Nexus 6.0 — 全新安装脚本(1Panel + Docker Compose)
|
|||
|
|
#
|
|||
|
|
# 适用:新机已装 1Panel / Docker,空库,走 /app/install.html 安装向导
|
|||
|
|
# 风格参考 1Panel quick_start.sh:分阶段检查 + 结束输出访问地址
|
|||
|
|
#
|
|||
|
|
# 用法(公共仓库,root 下一条命令,参考 1Panel):
|
|||
|
|
#
|
|||
|
|
# curl -fsSL "http://66.154.115.8:3000/admin/Nexus/raw/branch/main/deploy/quick-install.sh" | bash
|
|||
|
|
#
|
|||
|
|
# 已 clone 到 /opt/nexus:
|
|||
|
|
# cd /opt/nexus && bash deploy/install-nexus-fresh.sh --skip-clone
|
|||
|
|
#
|
|||
|
|
# bash deploy/install-nexus-fresh.sh --profile 4c16g
|
|||
|
|
#
|
|||
|
|
# 公共仓库匿名 clone,无需 Gitea 令牌。NEXUS 密钥由安装脚本按机自动生成。
|
|||
|
|
# =============================================================================
|
|||
|
|
|
|||
|
|
set -euo pipefail
|
|||
|
|
|
|||
|
|
_install_self="$(readlink -f "${BASH_SOURCE[0]}")"
|
|||
|
|
if ! head -1 "$_install_self" | grep -q '^#!/'; then
|
|||
|
|
echo "[ERROR] 脚本文件无效。若用 curl 下载,请改用: bash deploy/download-install-fresh.sh" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
if grep -qiE '^(Not found|404)' "$_install_self" 2>/dev/null; then
|
|||
|
|
echo "[ERROR] 下载到的是 Gitea 404 页面,不是安装脚本。" >&2
|
|||
|
|
echo " 请: cd /opt/nexus && git pull && sudo bash deploy/install-nexus-fresh.sh --skip-clone" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# ── 默认配置(与 SECRETS.md / nexus-1panel 一致)──
|
|||
|
|
NEXUS_ROOT="${NEXUS_ROOT:-/opt/nexus}"
|
|||
|
|
NEXUS_GITEA_HOST="${NEXUS_GITEA_HOST:-66.154.115.8:3000}"
|
|||
|
|
NEXUS_GITEA_REPO="${NEXUS_GITEA_REPO:-admin/Nexus.git}"
|
|||
|
|
NEXUS_DOMAIN="${NEXUS_DOMAIN:-api.synaglobal.vip}"
|
|||
|
|
NEXUS_PROFILE="${NEXUS_PROFILE:-2c8g}"
|
|||
|
|
NEXUS_GIT_BRANCH="${NEXUS_GIT_BRANCH:-main}"
|
|||
|
|
NEXUS_RAW_BASE="${NEXUS_RAW_BASE:-http://66.154.115.8:3000/admin/Nexus/raw/branch/main}"
|
|||
|
|
|
|||
|
|
RED='\033[0;31m'
|
|||
|
|
GREEN='\033[0;32m'
|
|||
|
|
YELLOW='\033[1;33m'
|
|||
|
|
CYAN='\033[0;36m'
|
|||
|
|
BLUE='\033[0;34m'
|
|||
|
|
NC='\033[0m'
|
|||
|
|
|
|||
|
|
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
|||
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|||
|
|
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
|||
|
|
step() { echo -e "${CYAN}[STEP]${NC} $*"; }
|
|||
|
|
|
|||
|
|
usage() {
|
|||
|
|
cat <<EOF
|
|||
|
|
Nexus 6.0 全新安装(1Panel + Docker)
|
|||
|
|
|
|||
|
|
sudo bash install-nexus-fresh.sh [选项]
|
|||
|
|
|
|||
|
|
选项:
|
|||
|
|
--domain NAME 公网域名(默认: ${NEXUS_DOMAIN})
|
|||
|
|
--profile NAME 资源档位 1c4g|2c8g|4c16g(默认: 2c8g)
|
|||
|
|
--root PATH 安装目录(默认: /opt/nexus)
|
|||
|
|
--skip-clone 已在 /opt/nexus,不重新 clone
|
|||
|
|
--skip-1panel-check 不检测 1Panel 是否已安装
|
|||
|
|
-h, --help 显示帮助
|
|||
|
|
|
|||
|
|
安装后请用浏览器打开: https://域名/app/install.html
|
|||
|
|
root 下全局命令: nexus-fresh | nexus-update | nx
|
|||
|
|
EOF
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SKIP_1PANEL_CHECK=false
|
|||
|
|
SKIP_CLONE=false
|
|||
|
|
|
|||
|
|
while [[ $# -gt 0 ]]; do
|
|||
|
|
case "$1" in
|
|||
|
|
-h|--help) usage; exit 0 ;;
|
|||
|
|
--domain) NEXUS_DOMAIN="$2"; shift 2 ;;
|
|||
|
|
--profile) NEXUS_PROFILE="$2"; shift 2 ;;
|
|||
|
|
--root) NEXUS_ROOT="$2"; shift 2 ;;
|
|||
|
|
--skip-clone) SKIP_CLONE=true; shift ;;
|
|||
|
|
--skip-1panel-check) SKIP_1PANEL_CHECK=true; shift ;;
|
|||
|
|
*) error "未知参数: $1"; usage; exit 1 ;;
|
|||
|
|
esac
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
banner() {
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
|||
|
|
echo -e "${BLUE}║${NC} Nexus 6.0 — 全新安装(1Panel + Docker Compose) ${BLUE}║${NC}"
|
|||
|
|
echo -e "${BLUE}║${NC} 域名: ${NEXUS_DOMAIN} ${BLUE}║${NC}"
|
|||
|
|
echo -e "${BLUE}║${NC} 档位: ${NEXUS_PROFILE} 目录: ${NEXUS_ROOT} ${BLUE}║${NC}"
|
|||
|
|
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
|
|||
|
|
echo ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
load_credentials() {
|
|||
|
|
step "加载凭据..."
|
|||
|
|
local f
|
|||
|
|
for f in /root/.nexus-deploy.env /root/.nexus-secrets/nexus.env; do
|
|||
|
|
if [[ -f "$f" ]]; then
|
|||
|
|
# shellcheck disable=SC1090
|
|||
|
|
set -a
|
|||
|
|
source "$f"
|
|||
|
|
set +a
|
|||
|
|
info "已加载 $f"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
if [[ -f "${NEXUS_ROOT}/deploy/nexus-1panel.secrets.sh" ]]; then
|
|||
|
|
# shellcheck disable=SC1090
|
|||
|
|
set -a
|
|||
|
|
source "${NEXUS_ROOT}/deploy/nexus-1panel.secrets.sh"
|
|||
|
|
set +a
|
|||
|
|
info "已加载 ${NEXUS_ROOT}/deploy/nexus-1panel.secrets.sh(可选)"
|
|||
|
|
fi
|
|||
|
|
unset NEXUS_SECRET_KEY NEXUS_API_KEY NEXUS_ENCRYPTION_KEY
|
|||
|
|
info "全新安装:NEXUS 密钥将在 docker/.env.prod 中按本机自动生成"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
install_root_commands() {
|
|||
|
|
[[ -d "${NEXUS_ROOT}/deploy" ]] || return 0
|
|||
|
|
NEXUS_ROOT="$NEXUS_ROOT" bash "${NEXUS_ROOT}/deploy/install-nx-cli.sh" || true
|
|||
|
|
info "全局命令: nx · nexus-update · nexus-fresh · nexus-install · nexus-1panel"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_preflight() {
|
|||
|
|
step "阶段 1/6 — 环境检查"
|
|||
|
|
if [[ "$(id -u)" -ne 0 ]]; then
|
|||
|
|
error "请切换到 root 再执行(不要用 sudo 包一层):"
|
|||
|
|
error " su -"
|
|||
|
|
error " bash $0 ..."
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
info "运行用户: root(无需 sudo)"
|
|||
|
|
|
|||
|
|
if [[ ! -f /etc/os-release ]]; then
|
|||
|
|
error "无法识别操作系统"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
# shellcheck disable=SC1091
|
|||
|
|
source /etc/os-release
|
|||
|
|
info "系统: ${NAME:-Linux} ${VERSION_ID:-}"
|
|||
|
|
case "${ID:-}" in
|
|||
|
|
ubuntu|debian) info "受支持的分支: Debian/Ubuntu ✓" ;;
|
|||
|
|
centos|rhel|rocky|almalinux) info "受支持的分支: RHEL 系 ✓" ;;
|
|||
|
|
*) warn "未在官方列表中测试,可能仍可运行" ;;
|
|||
|
|
esac
|
|||
|
|
|
|||
|
|
local mem_kb
|
|||
|
|
mem_kb="$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)"
|
|||
|
|
if [[ "$mem_kb" -lt 3500000 ]]; then
|
|||
|
|
warn "内存 < 4GB,建议档位 1c4g: --profile 1c4g"
|
|||
|
|
else
|
|||
|
|
info "内存: $((mem_kb / 1024 / 1024)) GiB 量级"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_1panel() {
|
|||
|
|
step "阶段 2/6 — 1Panel / Docker"
|
|||
|
|
if [[ "$SKIP_1PANEL_CHECK" != true ]]; then
|
|||
|
|
if command -v 1pctl >/dev/null 2>&1; then
|
|||
|
|
info "检测到 1Panel (1pctl)"
|
|||
|
|
if 1pctl version >/dev/null 2>&1; then
|
|||
|
|
info "1Panel: $(1pctl version 2>/dev/null | head -1 || true)"
|
|||
|
|
fi
|
|||
|
|
else
|
|||
|
|
warn "未检测到 1pctl — 若尚未安装 1Panel,可先执行:"
|
|||
|
|
warn " curl -sSL https://resource.1panel.pro/v2/quick_start.sh -o quick_start.sh"
|
|||
|
|
warn " bash quick_start.sh"
|
|||
|
|
read -r -p "继续安装 Nexus? [y/N]: " cont
|
|||
|
|
[[ "$cont" == "y" || "$cont" == "Y" ]] || exit 0
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if ! docker compose version >/dev/null 2>&1; then
|
|||
|
|
error "未检测到 docker compose"
|
|||
|
|
error "请在 1Panel → 容器 中安装 Docker,或: apt install -y docker.io docker-compose-v2"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
info "Docker Compose: $(docker compose version --short 2>/dev/null || docker compose version | head -1)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_packages() {
|
|||
|
|
step "阶段 3/6 — 依赖包"
|
|||
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|||
|
|
export DEBIAN_FRONTEND=noninteractive
|
|||
|
|
apt-get update -qq
|
|||
|
|
apt-get install -y -qq git curl openssl ca-certificates iproute2 >/dev/null 2>&1 || true
|
|||
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|||
|
|
dnf install -y -q git curl openssl ca-certificates iproute >/dev/null 2>&1 || true
|
|||
|
|
fi
|
|||
|
|
info "git / curl 就绪"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
git_clone_url() {
|
|||
|
|
if [[ -z "${NEXUS_GITEA_TOKEN:-}" ]]; then
|
|||
|
|
echo "http://${NEXUS_GITEA_HOST}/${NEXUS_GITEA_REPO}"
|
|||
|
|
else
|
|||
|
|
echo "http://admin:${NEXUS_GITEA_TOKEN}@${NEXUS_GITEA_HOST}/${NEXUS_GITEA_REPO}"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_clone() {
|
|||
|
|
step "阶段 4/6 — 获取 Nexus 代码"
|
|||
|
|
if [[ "$SKIP_CLONE" == true ]]; then
|
|||
|
|
if [[ ! -d "${NEXUS_ROOT}/.git" ]]; then
|
|||
|
|
error "--skip-clone 但 ${NEXUS_ROOT} 不是 git 仓库"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
load_credentials
|
|||
|
|
info "跳过 clone,使用现有 ${NEXUS_ROOT}"
|
|||
|
|
info "版本: $(git -C "$NEXUS_ROOT" log -1 --oneline 2>/dev/null || echo '?')"
|
|||
|
|
chmod +x "${NEXUS_ROOT}/deploy/"*.sh 2>/dev/null || true
|
|||
|
|
return 0
|
|||
|
|
fi
|
|||
|
|
load_credentials
|
|||
|
|
local url
|
|||
|
|
url="$(git_clone_url)"
|
|||
|
|
if [[ -z "${NEXUS_GITEA_TOKEN:-}" ]]; then
|
|||
|
|
info "公共仓库:匿名 git clone(无需令牌)"
|
|||
|
|
fi
|
|||
|
|
mkdir -p "$(dirname "$NEXUS_ROOT")"
|
|||
|
|
|
|||
|
|
if [[ -d "${NEXUS_ROOT}/.git" ]]; then
|
|||
|
|
info "仓库已存在,同步 ${NEXUS_GIT_BRANCH}..."
|
|||
|
|
git -C "$NEXUS_ROOT" remote set-url origin "$url" 2>/dev/null || true
|
|||
|
|
git -C "$NEXUS_ROOT" fetch origin "$NEXUS_GIT_BRANCH" --prune
|
|||
|
|
git -C "$NEXUS_ROOT" reset --hard "origin/${NEXUS_GIT_BRANCH}"
|
|||
|
|
else
|
|||
|
|
if [[ -d "$NEXUS_ROOT" ]] && [[ -n "$(ls -A "$NEXUS_ROOT" 2>/dev/null)" ]]; then
|
|||
|
|
error "目录非空且不是 git 仓库: $NEXUS_ROOT"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
rm -rf "$NEXUS_ROOT"
|
|||
|
|
info "克隆 → $NEXUS_ROOT"
|
|||
|
|
git clone "$url" "$NEXUS_ROOT"
|
|||
|
|
git -C "$NEXUS_ROOT" checkout "$NEXUS_GIT_BRANCH" 2>/dev/null || true
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
load_credentials
|
|||
|
|
info "版本: $(git -C "$NEXUS_ROOT" log -1 --oneline)"
|
|||
|
|
chmod +x "${NEXUS_ROOT}/deploy/"*.sh 2>/dev/null || true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_install_stack() {
|
|||
|
|
step "阶段 5/6 — Docker 构建与启动(全新库,约 10~20 分钟)"
|
|||
|
|
export NEXUS_ROOT NEXUS_DOMAIN NEXUS_PROFILE
|
|||
|
|
bash "${NEXUS_ROOT}/deploy/nexus-1panel.sh" install \
|
|||
|
|
--fresh \
|
|||
|
|
--skip-clone \
|
|||
|
|
--profile "$NEXUS_PROFILE" \
|
|||
|
|
--domain "$NEXUS_DOMAIN"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
phase_post() {
|
|||
|
|
step "阶段 6/6 — 收尾"
|
|||
|
|
install_root_commands
|
|||
|
|
|
|||
|
|
local port health
|
|||
|
|
port="8600"
|
|||
|
|
health="$(curl -sf "http://127.0.0.1:${port}/health" 2>/dev/null || echo "pending")"
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${GREEN}Nexus 全新安装完成${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}╠══════════════════════════════════════════════════════════════╣${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} 本地健康: http://127.0.0.1:${port}/health → ${health} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${YELLOW}① 浏览器完成安装向导(必做)${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} https://${NEXUS_DOMAIN}/app/install.html ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${YELLOW}② 1Panel 创建网站并反代${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} 目标: http://127.0.0.1:${port} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} 示例: ${NEXUS_ROOT}/deploy/1panel/openresty-nexus.conf.example ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} ${YELLOW}③ 日常运维${NC} ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} nx # 统一菜单(一键更新 / 重启 / 日志) ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}║${NC} nexus-update # 等同 deploy/update.sh ${GREEN}║${NC}"
|
|||
|
|
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
|
|||
|
|
echo ""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
warn_if_already_installed() {
|
|||
|
|
local env_prod="${NEXUS_ROOT}/docker/.env.prod" cname
|
|||
|
|
[[ -f "$env_prod" ]] || return 0
|
|||
|
|
cname="$(docker ps --format '{{.Names}}' 2>/dev/null | grep -E 'nexus-prod-nexus|nexus-nexus-1' | head -1 || true)"
|
|||
|
|
if [[ -n "$cname" ]] && docker exec "$cname" test -f /var/lib/nexus/.install_locked 2>/dev/null; then
|
|||
|
|
warn "检测到已安装并锁定的 Nexus(将清除 nexus-state 卷内配置并重建)"
|
|||
|
|
read -r -p "确认继续全新安装? [y/N]: " ok
|
|||
|
|
[[ "$ok" == "y" || "$ok" == "Y" ]] || exit 0
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main() {
|
|||
|
|
banner
|
|||
|
|
if [[ "$SKIP_CLONE" == true && -d "${NEXUS_ROOT}/deploy" ]]; then
|
|||
|
|
install_root_commands
|
|||
|
|
fi
|
|||
|
|
warn_if_already_installed
|
|||
|
|
phase_preflight
|
|||
|
|
phase_1panel
|
|||
|
|
phase_packages
|
|||
|
|
phase_clone
|
|||
|
|
phase_install_stack
|
|||
|
|
phase_post
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
main "$@"
|