Files
NexusGate/scripts/install.sh
T
Muse 084afeb8f4 3x-ui 式共享节点改造:nodes 状态机 + nodeClients 各自凭据
- 移除 VMess 协议
- VLESS/SS2022 按用户流量统计(AnyTLS 日志解析,SS 节点级)
- sing-box v2ray_api stats 支持
- 内存优化:面板 128M,agent 64M,sing-box 64M
2026-10-19 22:23:40 +08:00

199 lines
6.7 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:-a2899882/NexusGate}"
BRANCH="${NG_BRANCH:-main}"
DOMAIN=""
EMAIL=""
die() { printf '错误:%s\n' "$*" >&2; exit 1; }
info() { printf '\033[1;36m[NexusGate]\033[0m %s\n' "$*"; }
ask() {
local prompt="$1" value=""
if [[ -r /dev/tty ]]; then read -r -p "$prompt" value </dev/tty; fi
printf '%s' "$value"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) DOMAIN="${2:-}"; shift 2 ;;
--email) EMAIL="${2:-}"; shift 2 ;;
--repo) REPO="${2:-}"; shift 2 ;;
--branch) BRANCH="${2:-}"; shift 2 ;;
*) die "未知参数:$1" ;;
esac
done
[[ "${EUID}" -eq 0 ]] || die "请使用 root 运行"
[[ ! -e /opt/nexusgate ]] || die "检测到已有安装,请运行 nexusgate update"
IS_OPENWRT=false
if [[ -f /etc/openwrt_release ]]; then
IS_OPENWRT=true
elif [[ ! -f /etc/debian_version ]]; then
die "控制面一键安装器当前支持 Debian 12 / Ubuntu 22.04+ 和 OpenWrt"
fi
if [[ -z "$DOMAIN" ]]; then
if $IS_OPENWRT; then
DOMAIN="$(ask '面板域名(OpenWrt 上可留空,留空则仅内网访问、不配置 Caddy):')"
else
DOMAIN="$(ask '请输入面板域名(如 gate.example.com):')"
fi
fi
if [[ -n "$DOMAIN" ]]; then
[[ "$DOMAIN" =~ ^[A-Za-z0-9.-]+$ ]] || die "域名格式不正确"
elif ! $IS_OPENWRT; then
die "域名不能为空"
fi
if [[ -z "$EMAIL" ]]; then EMAIL="$(ask '证书邮箱(可留空):')"; fi
info "安装系统依赖"
if $IS_OPENWRT; then
# 注意:OpenWrt 上需预先装好 bash(本脚本依赖 bash):opkg update && opkg install bash
opkg update
# OpenWrt 上 openssl 命令行工具在 openssl-util 包里;部分精简固件没有 install 命令,需 coreutils-install
opkg install node caddy curl ca-certificates openssl-util tar coreutils-install
else
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq ca-certificates curl tar openssl nodejs caddy
fi
node_major="$(node -p 'process.versions.node.split(`.`)[0]')"
[[ "$node_major" -ge 18 ]] || die "需要 Node.js 18 或更高版本"
# NG_LOCAL_SRC 指向本地源码目录时跳过 GitHub 下载(本地改动尚未 push 时的全新安装用这个)
src_dir=""
if [[ -n "${NG_LOCAL_SRC:-}" ]]; then
[[ -f "${NG_LOCAL_SRC}/server.js" ]] || die "NG_LOCAL_SRC 目录不完整(缺少 server.js)"
info "使用本地源码 ${NG_LOCAL_SRC}"
src_dir="${NG_LOCAL_SRC}"
else
tmp_dir="$(mktemp -d /tmp/nexusgate-install.XXXXXX)"
trap 'rm -rf -- "$tmp_dir"' EXIT
info "下载 ${REPO}@${BRANCH}"
curl -fL --retry 3 "https://github.com/${REPO}/archive/refs/heads/${BRANCH}.tar.gz" -o "$tmp_dir/source.tgz"
mkdir -p "$tmp_dir/source"
tar -xzf "$tmp_dir/source.tgz" -C "$tmp_dir/source"
# GitHub tarball 解包后只有一层顶层目录;不用 --strip-components(BusyBox tar 不支持)
src_dir="$(echo "$tmp_dir/source"/*/)"
[[ -f "${src_dir}server.js" ]] || die "安装包不完整"
fi
if $IS_OPENWRT; then
# OpenWrt 是单用户系统,不建专用账号;/var 是内存盘,数据必须放闪存
DATA_DIR=/etc/nexusgate/data
install -d -m 0755 /opt/nexusgate
cp -a "${src_dir}/." /opt/nexusgate/
install -d -m 0700 "$DATA_DIR"
else
DATA_DIR=/var/lib/nexusgate
getent group nexusgate >/dev/null || groupadd --system nexusgate
id nexusgate >/dev/null 2>&1 || useradd --system --gid nexusgate --home-dir /var/lib/nexusgate --shell /usr/sbin/nologin nexusgate
install -d -o root -g root -m 0755 /opt/nexusgate
cp -a "${src_dir}/." /opt/nexusgate/
install -d -o nexusgate -g nexusgate -m 0700 "$DATA_DIR"
fi
if $IS_OPENWRT && [[ -z "$DOMAIN" ]]; then
# 无域名:直接监听内网(OpenWrt 防火墙默认拦截 WAN 入站),纯 HTTP
NG_HOST=0.0.0.0
NG_COOKIE_SECURE=false
else
NG_HOST=127.0.0.1
NG_COOKIE_SECURE=true
fi
admin_password="$(openssl rand -base64 24 | tr -d '\n')"
session_secret="$(openssl rand -hex 32)"
cat > /etc/nexusgate.env <<EOF
NODE_ENV=production
NG_HOST=${NG_HOST}
NG_PORT=8787
NG_DATA_FILE=${DATA_DIR}/nexusgate.json
NG_COOKIE_SECURE=${NG_COOKIE_SECURE}
NG_ADMIN_USERNAME=admin
NG_ADMIN_PASSWORD=${admin_password}
NG_SESSION_SECRET=${session_secret}
EOF
chmod 0600 /etc/nexusgate.env
install -d -m 0755 /usr/local/sbin
install -m 0755 /opt/nexusgate/scripts/nexusgate.sh /usr/local/sbin/nexusgate
ln -sf /usr/local/sbin/nexusgate /usr/local/sbin/ng
if $IS_OPENWRT; then
install -m 0755 /opt/nexusgate/openrc/nexusgate /etc/init.d/nexusgate
else
install -m 0644 /opt/nexusgate/systemd/nexusgate.service /etc/systemd/system/nexusgate.service
fi
if [[ -n "$DOMAIN" ]]; then
install -d -m 0755 /etc/caddy/Caddyfile.d
cat > /etc/caddy/Caddyfile.d/nexusgate.caddy <<EOF
${DOMAIN} {
encode zstd gzip
reverse_proxy 127.0.0.1:8787
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
-Server
}
log {
output file /var/log/caddy/nexusgate-access.log {
roll_size 20MiB
roll_keep 5
roll_keep_for 168h
}
}
EOF
if [[ -n "$EMAIL" ]]; then printf ' tls %s\n' "$EMAIL" >> /etc/caddy/Caddyfile.d/nexusgate.caddy; fi
printf '}\n' >> /etc/caddy/Caddyfile.d/nexusgate.caddy
if ! grep -qF 'import /etc/caddy/Caddyfile.d/*' /etc/caddy/Caddyfile; then
printf '\nimport /etc/caddy/Caddyfile.d/*\n' >> /etc/caddy/Caddyfile
fi
caddy fmt --overwrite /etc/caddy/Caddyfile
caddy fmt --overwrite /etc/caddy/Caddyfile.d/nexusgate.caddy
caddy validate --config /etc/caddy/Caddyfile
fi
if $IS_OPENWRT; then
/etc/init.d/nexusgate enable
/etc/init.d/nexusgate start
else
systemctl daemon-reload
systemctl enable --now nexusgate.service
fi
healthy=false
for _ in {1..30}; do
if curl -fsS http://127.0.0.1:8787/healthz >/dev/null 2>&1; then healthy=true; break; fi
sleep 1
done
if [[ "$healthy" != true ]]; then
if $IS_OPENWRT; then
logread 2>/dev/null | grep -a nexusgate | tail -n 100 || true
else
systemctl status nexusgate --no-pager || true
journalctl -u nexusgate -n 100 --no-pager || true
fi
die "控制面启动失败,诊断信息已输出"
fi
if $IS_OPENWRT && [[ "$NG_HOST" == "0.0.0.0" ]] && ! netstat -tln 2>/dev/null | grep -q "0.0.0.0:8787"; then
die "控制面未监听 0.0.0.0:8787(环境变量未正确传递),请检查 /etc/init.d/nexusgate"
fi
sed -i '/^NG_ADMIN_PASSWORD=/d' /etc/nexusgate.env
if [[ -n "$DOMAIN" ]]; then
if $IS_OPENWRT; then
/etc/init.d/caddy enable
/etc/init.d/caddy restart
else
systemctl enable --now caddy
systemctl reload caddy
fi
fi
printf '\n\033[1;32m安装完成\033[0m\n'
if [[ -n "$DOMAIN" ]]; then
printf '地址:https://%s\n' "$DOMAIN"
else
printf '地址:http://<路由器 LAN IP>:8787(内网访问)\n'
fi
printf '账号:admin\n密码:%s\n' "$admin_password"
printf '管理命令:nexusgate 或 ng\n请立即登录并妥善保存密码。\n'