Files
NexusGate/scripts/agent-install.sh
T

141 lines
6.6 KiB
Bash
Executable File
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.
#!/usr/bin/env bash
set -Eeuo pipefail
REPO="${NG_REPO:-imamoxilin/NexusGate}"
BRANCH="${NG_BRANCH:-main}"
CONTROLLER=""
TOKEN=""
die() { printf '错误:%s\n' "$*" >&2; exit 1; }
info() { printf '\033[1;36m[NexusGate Agent]\033[0m %s\n' "$*"; }
# NG_LOCAL_SRC 指向本地源码目录时跳过 GitHub 下载(本地改动尚未 push 时用这个)
fetch() {
if [[ -n "${NG_LOCAL_SRC:-}" ]]; then
[[ -f "${NG_LOCAL_SRC}/$1" ]] || die "NG_LOCAL_SRC 目录缺少 $1"
cp -a "${NG_LOCAL_SRC}/$1" "$2"
else
# 加时间戳破坏 GitHub raw 缓存,避免拉到旧版
curl -fL --retry 3 "https://raw.githubusercontent.com/${REPO}/${BRANCH}/$1?t=$(date +%s)" -o "$2"
fi
}
while [[ $# -gt 0 ]]; do
case "$1" in
--server) CONTROLLER="${2:-}"; shift 2 ;;
--token) TOKEN="${2:-}"; shift 2 ;;
--repo) REPO="${2:-}"; shift 2 ;;
--branch) BRANCH="${2:-}"; shift 2 ;;
*) die "未知参数:$1" ;;
esac
done
[[ "${EUID}" -eq 0 ]] || die "请使用 root 运行"
[[ "$CONTROLLER" =~ ^https?:// ]] || die "--server 必须是完整的 HTTP(S) 地址"
[[ -n "$TOKEN" ]] || die "缺少 --token"
if command -v apt-get >/dev/null; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq && apt-get install -y -qq ca-certificates curl unzip nodejs openssl logrotate
elif command -v dnf >/dev/null; then
dnf install -y ca-certificates curl unzip nodejs openssl logrotate
elif command -v apk >/dev/null; then
apk add --no-cache bash ca-certificates curl unzip nodejs openrc openssl logrotate
else
die "当前安装器支持 Debian/Ubuntu、RHEL 系和 Alpine"
fi
node_major="$(node -p 'process.versions.node.split(`.`)[0]')"
[[ "$node_major" -ge 18 ]] || die "需要 Node.js 18 或更高版本"
tmp_dir="$(mktemp -d /tmp/nexusgate-agent.XXXXXX)"
trap 'rm -rf -- "$tmp_dir"' EXIT
install -d -m 0755 /opt/nexusgate-agent
fetch agent/agent.js /opt/nexusgate-agent/agent.js
fetch agent/run.sh /opt/nexusgate-agent/run.sh
fetch scripts/agent-update.sh /usr/local/sbin/ng-agent-update
fetch scripts/agent-uninstall.sh /usr/local/sbin/ng-agent-uninstall
fetch scripts/agent-doctor.sh /usr/local/sbin/ng-agent-doctor
fetch scripts/agent-cert.sh /usr/local/sbin/ng-agent-cert
fetch scripts/agent-singbox.sh /usr/local/sbin/ng-agent-singbox
fetch scripts/agent-logrotate.conf "$tmp_dir/logrotate.conf"
fetch scripts/agent-logrotate-setup.sh "$tmp_dir/logrotate-setup.sh"
cat > /usr/local/sbin/ng-agent <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
case "${1:-}" in
update) exec ng-agent-update ;;
uninstall) shift; exec ng-agent-uninstall "$@" ;;
doctor|status) exec ng-agent-doctor ;;
cert) shift; exec ng-agent-cert "$@" ;;
engine) shift; exec ng-agent-singbox "$@" ;;
*) printf 'NexusGate Agent: ng-agent doctor | ng-agent cert | ng-agent engine install | ng-agent update | ng-agent uninstall\n' ;;
esac
EOF
chmod 0644 /opt/nexusgate-agent/agent.js
chmod 0755 /opt/nexusgate-agent/run.sh /usr/local/sbin/ng-agent-update /usr/local/sbin/ng-agent-uninstall /usr/local/sbin/ng-agent-doctor /usr/local/sbin/ng-agent-cert /usr/local/sbin/ng-agent-singbox /usr/local/sbin/ng-agent
install -d -m 0700 /etc/nexusgate /etc/nexusgate/agent /etc/nexusgate/agent/resources /etc/nexusgate/sing-box
install -d -m 0750 /var/log/nexusgate
install -m 0644 "$tmp_dir/logrotate.conf" /etc/nexusgate/agent-logrotate.conf
install -m 0755 "$tmp_dir/logrotate-setup.sh" /usr/local/sbin/ng-agent-logrotate-setup
# sing-box 是唯一的入口引擎,安装时直接构建。
NG_REPO="$REPO" NG_BRANCH="$BRANCH" ng-agent-singbox install || die 'sing-box 引擎安装失败;修复后运行 ng-agent engine install'
info "向控制面注册"
enroll_json="$(TOKEN_VALUE="$TOKEN" node -e 'process.stdout.write(JSON.stringify({token:process.env.TOKEN_VALUE,hostname:require("node:os").hostname(),version:"0.6.8",system:{platform:process.platform,arch:process.arch}}))')"
response="$(curl -fsS -H 'content-type: application/json' --data "$enroll_json" "${CONTROLLER%/}/api/agent/enroll")" || die "注册失败,请检查地址和令牌"
agent_key="$(RESPONSE_VALUE="$response" node -e 'const r=JSON.parse(process.env.RESPONSE_VALUE); if(!r.agentKey) process.exit(1); process.stdout.write(r.agentKey)')" || die "控制面返回无效"
{
printf 'NG_CONTROLLER=%q\n' "${CONTROLLER%/}"
printf 'NG_AGENT_KEY=%q\n' "$agent_key"
printf 'NG_CONFIG_DIR=/etc/nexusgate/agent\n'
printf 'NG_KEY_FILE=/etc/nexusgate/keys.json\n'
} > /etc/nexusgate/agent.env
chmod 0600 /etc/nexusgate/agent.env
if command -v systemctl >/dev/null && [[ -d /run/systemd/system ]]; then
fetch systemd/nexusgate-agent.service /etc/systemd/system/nexusgate-agent.service
fetch systemd/nexusgate-sing-box.service /etc/systemd/system/nexusgate-sing-box.service
systemctl daemon-reload
systemctl enable nexusgate-sing-box.service nexusgate-agent.service
rm -f -- /etc/nexusgate/last-heartbeat.json
systemctl restart nexusgate-sing-box.service
systemctl restart nexusgate-agent.service
service_manager="systemd"
elif command -v rc-service >/dev/null; then
install -d -m 0755 /etc/init.d
fetch openrc/nexusgate-agent /etc/init.d/nexusgate-agent
fetch openrc/nexusgate-sing-box /etc/init.d/nexusgate-sing-box
chmod 0755 /etc/init.d/nexusgate-agent /etc/init.d/nexusgate-sing-box
rc-update add nexusgate-sing-box default >/dev/null
rc-update add nexusgate-agent default >/dev/null
# Alpine runs the dedicated hourly task through BusyBox crond.
if [[ -e /etc/init.d/crond ]]; then
rc-update add crond default >/dev/null 2>&1 || true
rc-service crond start >/dev/null 2>&1 || true
fi
rc-service nexusgate-sing-box restart
rm -f -- /etc/nexusgate/last-heartbeat.json
rc-service nexusgate-agent restart
service_manager="OpenRC"
else
die "未检测到 systemd 或 OpenRC"
fi
ng-agent-logrotate-setup
for _ in {1..35}; do
[[ -s /etc/nexusgate/last-heartbeat.json ]] && break
sleep 1
done
if [[ ! -s /etc/nexusgate/last-heartbeat.json ]]; then
if [[ "$service_manager" == systemd ]]; then journalctl -u nexusgate-agent.service -n 35 --no-pager || true; fi
die 'Agent 注册成功但没有向控制面上报心跳;运行 ng-agent doctor 排查后再重试'
fi
printf '\n\033[1;32mAgent 安装、注册和首次心跳完成(%s)。\033[0m\n' "$service_manager"
printf '后续更新 Agent:ng-agent-update\n'
printf '卸载 Agent:ng-agent uninstall\n'
printf '检查 Agent 与 sing-box:ng-agent doctor\n'
if [[ "$service_manager" == systemd ]] && ! systemctl is-active --quiet nexusgate-agent.service; then
journalctl -u nexusgate-agent.service -n 35 --no-pager || true
die 'Agent 注册已完成,但服务没有运行;请执行 ng-agent doctor 检查原因'
fi