fix: convert shell scripts to LF line endings for Linux

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-16 08:25:49 +08:00
parent cd0639d55c
commit 7089fa5777
7 changed files with 306 additions and 298 deletions
+13 -13
View File
@@ -1,13 +1,13 @@
# VPS 环境配置(66.hyf2.cc @ 47.76.87.111 # VPS 环境配置(66.hyf2.cc @ 47.76.87.111
# 部署路径:/opt/jiedian # 部署路径:/opt/jiedian
VPS_IP=47.76.87.111 VPS_IP=47.76.87.111
DOMAIN=66.hyf2.cc DOMAIN=66.hyf2.cc
ACME_EMAIL=admin@hyf2.cc ACME_EMAIL=admin@hyf2.cc
REALITY_SERVER_NAME=www.microsoft.com REALITY_SERVER_NAME=www.microsoft.com
UUID=42f5b04d-292d-4f13-b892-b70553a714d5 UUID=42f5b04d-292d-4f13-b892-b70553a714d5
REALITY_PRIVATE_KEY=IPKtaw1aVb4fS0TPcimu8zwaVGml-JJ5H1rj-_TFQHM REALITY_PRIVATE_KEY=IPKtaw1aVb4fS0TPcimu8zwaVGml-JJ5H1rj-_TFQHM
REALITY_PUBLIC_KEY=51H_ikqYdDRgCpjq3pvMYNbqrX8S3zuow1UEjqTN-nI REALITY_PUBLIC_KEY=51H_ikqYdDRgCpjq3pvMYNbqrX8S3zuow1UEjqTN-nI
REALITY_SHORT_ID=e126b4ef9d36adfc REALITY_SHORT_ID=e126b4ef9d36adfc
HY2_PASSWORD=npDFaGfRzAPLS3Hh7iM6TEOk HY2_PASSWORD=npDFaGfRzAPLS3Hh7iM6TEOk
+21 -21
View File
@@ -1,21 +1,21 @@
# 复制为 .env 后填写,部署脚本会读取这些变量 # 复制为 .env 后填写,部署脚本会读取这些变量
# cp .env.example .env # cp .env.example .env
# VPS 公网 IP # VPS 公网 IP
VPS_IP=47.76.87.111 VPS_IP=47.76.87.111
# 域名(Hysteria2 证书用) # 域名(Hysteria2 证书用)
DOMAIN=66.hyf2.cc DOMAIN=66.hyf2.cc
# Let's Encrypt 申请证书邮箱 # Let's Encrypt 申请证书邮箱
ACME_EMAIL=admin@hyf2.cc ACME_EMAIL=admin@hyf2.cc
# Reality 伪装目标(真实大站,不要用你自己的域名) # Reality 伪装目标(真实大站,不要用你自己的域名)
REALITY_SERVER_NAME=www.microsoft.com REALITY_SERVER_NAME=www.microsoft.com
# 以下由 scripts/generate-keys.sh 自动生成,也可手动填写 # 以下由 scripts/generate-keys.sh 自动生成,也可手动填写
# UUID= # UUID=
# REALITY_PRIVATE_KEY= # REALITY_PRIVATE_KEY=
# REALITY_PUBLIC_KEY= # REALITY_PUBLIC_KEY=
# REALITY_SHORT_ID= # REALITY_SHORT_ID=
# HY2_PASSWORD= # HY2_PASSWORD=
+7
View File
@@ -0,0 +1,7 @@
# Shell scripts must use LF on Linux
*.sh text eol=lf
.env text eol=lf
.env.example text eol=lf
# Default: normalize text files
* text=auto
+1
View File
@@ -144,6 +144,7 @@ systemctl restart sing-box
| 问题 | 处理 | | 问题 | 处理 |
|------|------| |------|------|
| `set: pipefail: invalid option` | Windows 换行符问题,执行:`sed -i 's/\r$//' scripts/*.sh .env` 后重试 |
| `dig` 未返回正确 IP | 等待 DNS 生效或检查解析记录 | | `dig` 未返回正确 IP | 等待 DNS 生效或检查解析记录 |
| acme 证书失败 | 确认 80 端口可访问:`curl -I http://66.hyf2.cc` | | acme 证书失败 | 确认 80 端口可访问:`curl -I http://66.hyf2.cc` |
| sing-box 启动失败 | `journalctl -u sing-box -n 50` 查看报错 | | sing-box 启动失败 | `journalctl -u sing-box -n 50` 查看报错 |
+54 -54
View File
@@ -1,54 +1,54 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# 生成 Reality 与 Hysteria2 所需密钥,输出到 stdout 并写入 .env # 生成 Reality 与 Hysteria2 所需密钥,输出到 stdout 并写入 .env
set -euo pipefail set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")" ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="${ROOT_DIR}/.env" ENV_FILE="${ROOT_DIR}/.env"
# 依赖 sing-box 生成 reality 密钥对 # 依赖 sing-box 生成 reality 密钥对
if ! command -v sing-box &>/dev/null; then if ! command -v sing-box &>/dev/null; then
echo "sing-box 未安装,使用临时下载..." >&2 echo "sing-box 未安装,使用临时下载..." >&2
TMP="$(mktemp -d)" TMP="$(mktemp -d)"
ARCH="$(uname -m)" ARCH="$(uname -m)"
case "$ARCH" in case "$ARCH" in
x86_64) SB_ARCH="amd64" ;; x86_64) SB_ARCH="amd64" ;;
aarch64) SB_ARCH="arm64" ;; aarch64) SB_ARCH="arm64" ;;
*) echo "不支持的架构: $ARCH" >&2; exit 1 ;; *) echo "不支持的架构: $ARCH" >&2; exit 1 ;;
esac esac
curl -fsSL "https://github.com/SagerNet/sing-box/releases/latest/download/sing-box-1.11.0-linux-${SB_ARCH}.tar.gz" \ curl -fsSL "https://github.com/SagerNet/sing-box/releases/latest/download/sing-box-1.11.0-linux-${SB_ARCH}.tar.gz" \
| tar -xz -C "$TMP" --strip-components=1 | tar -xz -C "$TMP" --strip-components=1
SB="$TMP/sing-box" SB="$TMP/sing-box"
else else
SB="sing-box" SB="sing-box"
fi fi
UUID="$("$SB" generate uuid)" UUID="$("$SB" generate uuid)"
KEYPAIR="$("$SB" generate reality-keypair)" KEYPAIR="$("$SB" generate reality-keypair)"
PRIVATE_KEY="$(echo "$KEYPAIR" | grep 'PrivateKey:' | awk '{print $2}')" PRIVATE_KEY="$(echo "$KEYPAIR" | grep 'PrivateKey:' | awk '{print $2}')"
PUBLIC_KEY="$(echo "$KEYPAIR" | grep 'PublicKey:' | awk '{print $2}')" PUBLIC_KEY="$(echo "$KEYPAIR" | grep 'PublicKey:' | awk '{print $2}')"
SHORT_ID="$("$SB" generate rand --hex 8)" SHORT_ID="$("$SB" generate rand --hex 8)"
HY2_PASSWORD="$("$SB" generate rand --base64 32 | tr -d '/+=' | head -c 24)" HY2_PASSWORD="$("$SB" generate rand --base64 32 | tr -d '/+=' | head -c 24)"
echo "========== 生成的密钥 ==========" echo "========== 生成的密钥 =========="
echo "UUID: $UUID" echo "UUID: $UUID"
echo "REALITY_PRIVATE_KEY: $PRIVATE_KEY" echo "REALITY_PRIVATE_KEY: $PRIVATE_KEY"
echo "REALITY_PUBLIC_KEY: $PUBLIC_KEY" echo "REALITY_PUBLIC_KEY: $PUBLIC_KEY"
echo "REALITY_SHORT_ID: $SHORT_ID" echo "REALITY_SHORT_ID: $SHORT_ID"
echo "HY2_PASSWORD: $HY2_PASSWORD" echo "HY2_PASSWORD: $HY2_PASSWORD"
echo "================================" echo "================================"
if [[ -f "$ENV_FILE" ]]; then if [[ -f "$ENV_FILE" ]]; then
# 更新或追加 .env 中的密钥字段 # 更新或追加 .env 中的密钥字段
for var in UUID REALITY_PRIVATE_KEY REALITY_PUBLIC_KEY REALITY_SHORT_ID HY2_PASSWORD; do for var in UUID REALITY_PRIVATE_KEY REALITY_PUBLIC_KEY REALITY_SHORT_ID HY2_PASSWORD; do
val="${!var}" val="${!var}"
if grep -q "^${var}=" "$ENV_FILE" 2>/dev/null; then if grep -q "^${var}=" "$ENV_FILE" 2>/dev/null; then
sed -i "s|^${var}=.*|${var}=${val}|" "$ENV_FILE" sed -i "s|^${var}=.*|${var}=${val}|" "$ENV_FILE"
else else
echo "${var}=${val}" >> "$ENV_FILE" echo "${var}=${val}" >> "$ENV_FILE"
fi fi
done done
echo "已写入 $ENV_FILE" echo "已写入 $ENV_FILE"
else else
echo "提示: 先复制 .env.example 为 .env 并填写 VPS_IP、DOMAIN 等,再重新运行本脚本" >&2 echo "提示: 先复制 .env.example 为 .env 并填写 VPS_IP、DOMAIN 等,再重新运行本脚本" >&2
fi fi
+171 -171
View File
@@ -1,171 +1,171 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# VPS 一键部署:sing-box (Reality + Hysteria2) + Nginx fallback # VPS 一键部署:sing-box (Reality + Hysteria2) + Nginx fallback
# 适用:Ubuntu 22.04/24.04、Debian 12 # 适用:Ubuntu 22.04/24.04、Debian 12
# 用法:sudo bash scripts/install.sh # 用法:sudo bash scripts/install.sh
set -euo pipefail set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")" ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="${ROOT_DIR}/.env" ENV_FILE="${ROOT_DIR}/.env"
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
NC='\033[0m' NC='\033[0m'
log() { echo -e "${GREEN}[+]${NC} $*"; } log() { echo -e "${GREEN}[+]${NC} $*"; }
err() { echo -e "${RED}[!]${NC} $*" >&2; exit 1; } err() { echo -e "${RED}[!]${NC} $*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || err "请使用 root 运行: sudo bash scripts/install.sh" [[ $EUID -eq 0 ]] || err "请使用 root 运行: sudo bash scripts/install.sh"
[[ -f "$ENV_FILE" ]] || err "缺少 .env 文件,请先: cp .env.example .env 并填写" [[ -f "$ENV_FILE" ]] || err "缺少 .env 文件,请先: cp .env.example .env 并填写"
# shellcheck disable=SC1090 # shellcheck disable=SC1090
source "$ENV_FILE" source "$ENV_FILE"
: "${VPS_IP:?请在 .env 中设置 VPS_IP}" : "${VPS_IP:?请在 .env 中设置 VPS_IP}"
: "${DOMAIN:?请在 .env 中设置 DOMAIN}" : "${DOMAIN:?请在 .env 中设置 DOMAIN}"
: "${ACME_EMAIL:?请在 .env 中设置 ACME_EMAIL}" : "${ACME_EMAIL:?请在 .env 中设置 ACME_EMAIL}"
: "${REALITY_SERVER_NAME:=www.microsoft.com}" : "${REALITY_SERVER_NAME:=www.microsoft.com}"
if [[ -z "${UUID:-}" || -z "${REALITY_PRIVATE_KEY:-}" ]]; then if [[ -z "${UUID:-}" || -z "${REALITY_PRIVATE_KEY:-}" ]]; then
log "未检测到密钥,运行 generate-keys.sh ..." log "未检测到密钥,运行 generate-keys.sh ..."
bash "$SCRIPT_DIR/generate-keys.sh" bash "$SCRIPT_DIR/generate-keys.sh"
source "$ENV_FILE" source "$ENV_FILE"
fi fi
: "${UUID:?}" : "${UUID:?}"
: "${REALITY_PRIVATE_KEY:?}" : "${REALITY_PRIVATE_KEY:?}"
: "${REALITY_SHORT_ID:?}" : "${REALITY_SHORT_ID:?}"
: "${HY2_PASSWORD:?}" : "${HY2_PASSWORD:?}"
ARCH="$(uname -m)" ARCH="$(uname -m)"
case "$ARCH" in case "$ARCH" in
x86_64) SB_ARCH="amd64" ;; x86_64) SB_ARCH="amd64" ;;
aarch64) SB_ARCH="arm64" ;; aarch64) SB_ARCH="arm64" ;;
*) err "不支持的架构: $ARCH" ;; *) err "不支持的架构: $ARCH" ;;
esac esac
SB_VERSION="1.11.0" SB_VERSION="1.11.0"
SB_URL="https://github.com/SagerNet/sing-box/releases/download/v${SB_VERSION}/sing-box-${SB_VERSION}-linux-${SB_ARCH}.tar.gz" SB_URL="https://github.com/SagerNet/sing-box/releases/download/v${SB_VERSION}/sing-box-${SB_VERSION}-linux-${SB_ARCH}.tar.gz"
log "更新系统包 ..." log "更新系统包 ..."
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
apt-get update -qq apt-get update -qq
apt-get install -y -qq curl wget nginx ufw ca-certificates apt-get install -y -qq curl wget nginx ufw ca-certificates
log "安装 sing-box ${SB_VERSION} ..." log "安装 sing-box ${SB_VERSION} ..."
TMP="$(mktemp -d)" TMP="$(mktemp -d)"
curl -fsSL "$SB_URL" | tar -xz -C "$TMP" --strip-components=1 curl -fsSL "$SB_URL" | tar -xz -C "$TMP" --strip-components=1
install -m 755 "$TMP/sing-box" /usr/local/bin/sing-box install -m 755 "$TMP/sing-box" /usr/local/bin/sing-box
rm -rf "$TMP" rm -rf "$TMP"
log "配置防火墙 ..." log "配置防火墙 ..."
ufw --force reset ufw --force reset
ufw default deny incoming ufw default deny incoming
ufw default allow outgoing ufw default allow outgoing
ufw allow 22/tcp comment 'SSH' ufw allow 22/tcp comment 'SSH'
ufw allow 443/tcp comment 'Reality' ufw allow 443/tcp comment 'Reality'
ufw allow 8443/udp comment 'Hysteria2' ufw allow 8443/udp comment 'Hysteria2'
ufw --force enable ufw --force enable
log "部署 Nginx fallback 站点 ..." log "部署 Nginx fallback 站点 ..."
mkdir -p /var/www/fallback mkdir -p /var/www/fallback
cp "$ROOT_DIR/server/nginx/index.html" /var/www/fallback/ cp "$ROOT_DIR/server/nginx/index.html" /var/www/fallback/
cp "$ROOT_DIR/server/nginx/fallback.conf" /etc/nginx/sites-available/fallback cp "$ROOT_DIR/server/nginx/fallback.conf" /etc/nginx/sites-available/fallback
ln -sf /etc/nginx/sites-available/fallback /etc/nginx/sites-enabled/fallback ln -sf /etc/nginx/sites-available/fallback /etc/nginx/sites-enabled/fallback
rm -f /etc/nginx/sites-enabled/default rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl enable nginx && systemctl restart nginx nginx -t && systemctl enable nginx && systemctl restart nginx
log "申请 TLS 证书 (Let's Encrypt) ..." log "申请 TLS 证书 (Let's Encrypt) ..."
mkdir -p /etc/sing-box/certs mkdir -p /etc/sing-box/certs
if [[ ! -f /root/.acme.sh/acme.sh ]]; then if [[ ! -f /root/.acme.sh/acme.sh ]]; then
curl -fsSL https://get.acme.sh | sh -s email="$ACME_EMAIL" curl -fsSL https://get.acme.sh | sh -s email="$ACME_EMAIL"
fi fi
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source /root/.acme.sh/acme.sh.env || true source /root/.acme.sh/acme.sh.env || true
# 确保域名已解析到本机 # 确保域名已解析到本机
CURRENT_IP="$(curl -4 -fsSL ifconfig.me 2>/dev/null || curl -4 -fsSL ip.sb)" CURRENT_IP="$(curl -4 -fsSL ifconfig.me 2>/dev/null || curl -4 -fsSL ip.sb)"
if [[ "$CURRENT_IP" != "$VPS_IP" ]]; then if [[ "$CURRENT_IP" != "$VPS_IP" ]]; then
err "域名 $DOMAIN 需先解析到 VPS IP ($VPS_IP),当前 VPS 出口 IP 为 $CURRENT_IP" err "域名 $DOMAIN 需先解析到 VPS IP ($VPS_IP),当前 VPS 出口 IP 为 $CURRENT_IP"
fi fi
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt /root/.acme.sh/acme.sh --set-default-ca --server letsencrypt
/root/.acme.sh/acme.sh --issue -d "$DOMAIN" --nginx --force /root/.acme.sh/acme.sh --issue -d "$DOMAIN" --nginx --force
/root/.acme.sh/acme.sh --install-cert -d "$DOMAIN" \ /root/.acme.sh/acme.sh --install-cert -d "$DOMAIN" \
--key-file /etc/sing-box/certs/privkey.pem \ --key-file /etc/sing-box/certs/privkey.pem \
--fullchain-file /etc/sing-box/certs/fullchain.pem \ --fullchain-file /etc/sing-box/certs/fullchain.pem \
--reloadcmd "systemctl restart sing-box" --reloadcmd "systemctl restart sing-box"
log "生成 sing-box 服务端配置 ..." log "生成 sing-box 服务端配置 ..."
mkdir -p /etc/sing-box mkdir -p /etc/sing-box
sed -e "s|\${UUID}|${UUID}|g" \ sed -e "s|\${UUID}|${UUID}|g" \
-e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \ -e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \
-e "s|\${REALITY_PRIVATE_KEY}|${REALITY_PRIVATE_KEY}|g" \ -e "s|\${REALITY_PRIVATE_KEY}|${REALITY_PRIVATE_KEY}|g" \
-e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \ -e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \
-e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \ -e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \
-e "s|\${DOMAIN}|${DOMAIN}|g" \ -e "s|\${DOMAIN}|${DOMAIN}|g" \
"$ROOT_DIR/server/sing-box.json.template" > /etc/sing-box/config.json "$ROOT_DIR/server/sing-box.json.template" > /etc/sing-box/config.json
sing-box check -c /etc/sing-box/config.json sing-box check -c /etc/sing-box/config.json
log "创建 systemd 服务 ..." log "创建 systemd 服务 ..."
cat > /etc/systemd/system/sing-box.service <<'UNIT' cat > /etc/systemd/system/sing-box.service <<'UNIT'
[Unit] [Unit]
Description=sing-box service Description=sing-box service
After=network-online.target nginx.service After=network-online.target nginx.service
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/usr/local/bin/sing-box run -c /etc/sing-box/config.json ExecStart=/usr/local/bin/sing-box run -c /etc/sing-box/config.json
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
LimitNOFILE=1048576 LimitNOFILE=1048576
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
UNIT UNIT
systemctl daemon-reload systemctl daemon-reload
systemctl enable sing-box systemctl enable sing-box
systemctl restart sing-box systemctl restart sing-box
log "生成客户端配置 ..." log "生成客户端配置 ..."
CLIENT_DIR="${ROOT_DIR}/client/generated" CLIENT_DIR="${ROOT_DIR}/client/generated"
mkdir -p "$CLIENT_DIR" mkdir -p "$CLIENT_DIR"
: "${REALITY_PUBLIC_KEY:?请在 .env 中设置 REALITY_PUBLIC_KEY(运行 generate-keys.sh 可自动生成)}" : "${REALITY_PUBLIC_KEY:?请在 .env 中设置 REALITY_PUBLIC_KEY(运行 generate-keys.sh 可自动生成)}"
sed -e "s|\${VPS_IP}|${VPS_IP}|g" \ sed -e "s|\${VPS_IP}|${VPS_IP}|g" \
-e "s|\${DOMAIN}|${DOMAIN}|g" \ -e "s|\${DOMAIN}|${DOMAIN}|g" \
-e "s|\${UUID}|${UUID}|g" \ -e "s|\${UUID}|${UUID}|g" \
-e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \ -e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \
-e "s|\${REALITY_PUBLIC_KEY}|${REALITY_PUBLIC_KEY}|g" \ -e "s|\${REALITY_PUBLIC_KEY}|${REALITY_PUBLIC_KEY}|g" \
-e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \ -e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \
-e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \ -e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \
"$ROOT_DIR/client/sing-box-client.json.template" > "$CLIENT_DIR/sing-box-client.json" "$ROOT_DIR/client/sing-box-client.json.template" > "$CLIENT_DIR/sing-box-client.json"
# 生成分享链接 # 生成分享链接
cat > "$CLIENT_DIR/share-links.txt" <<EOF cat > "$CLIENT_DIR/share-links.txt" <<EOF
========== VLESS + Reality (主力) ========== ========== VLESS + Reality (主力) ==========
vless://${UUID}@${VPS_IP}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SERVER_NAME}&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#Reality-Main vless://${UUID}@${VPS_IP}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SERVER_NAME}&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#Reality-Main
========== Hysteria2 (备用) ========== ========== Hysteria2 (备用) ==========
hy2://${HY2_PASSWORD}@${DOMAIN}:8443?sni=${DOMAIN}#Hysteria2-Backup hy2://${HY2_PASSWORD}@${DOMAIN}:8443?sni=${DOMAIN}#Hysteria2-Backup
========== 参数明细 ========== ========== 参数明细 ==========
VPS IP: ${VPS_IP} VPS IP: ${VPS_IP}
UUID: ${UUID} UUID: ${UUID}
Reality SNI: ${REALITY_SERVER_NAME} Reality SNI: ${REALITY_SERVER_NAME}
Reality PublicKey: ${REALITY_PUBLIC_KEY} Reality PublicKey: ${REALITY_PUBLIC_KEY}
Reality ShortId: ${REALITY_SHORT_ID} Reality ShortId: ${REALITY_SHORT_ID}
Hysteria2 域名: ${DOMAIN} Hysteria2 域名: ${DOMAIN}
Hysteria2 密码: ${HY2_PASSWORD} Hysteria2 密码: ${HY2_PASSWORD}
EOF EOF
log "部署完成!" log "部署完成!"
echo "" echo ""
cat "$CLIENT_DIR/share-links.txt" cat "$CLIENT_DIR/share-links.txt"
echo "" echo ""
log "客户端配置文件: ${CLIENT_DIR}/sing-box-client.json" log "客户端配置文件: ${CLIENT_DIR}/sing-box-client.json"
log "sing-box 状态: systemctl status sing-box" log "sing-box 状态: systemctl status sing-box"
log "查看日志: journalctl -u sing-box -f" log "查看日志: journalctl -u sing-box -f"
+39 -39
View File
@@ -1,39 +1,39 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# 本地根据 .env 渲染客户端配置(无需在 VPS 上运行) # 本地根据 .env 渲染客户端配置(无需在 VPS 上运行)
set -euo pipefail set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")" ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="${ROOT_DIR}/.env" ENV_FILE="${ROOT_DIR}/.env"
OUT_DIR="${ROOT_DIR}/client/generated" OUT_DIR="${ROOT_DIR}/client/generated"
[[ -f "$ENV_FILE" ]] || { echo "缺少 .env,请先 cp .env.example .env 并填写"; exit 1; } [[ -f "$ENV_FILE" ]] || { echo "缺少 .env,请先 cp .env.example .env 并填写"; exit 1; }
# shellcheck disable=SC1090 # shellcheck disable=SC1090
source "$ENV_FILE" source "$ENV_FILE"
for var in VPS_IP DOMAIN UUID REALITY_SERVER_NAME REALITY_PUBLIC_KEY REALITY_SHORT_ID HY2_PASSWORD; do for var in VPS_IP DOMAIN UUID REALITY_SERVER_NAME REALITY_PUBLIC_KEY REALITY_SHORT_ID HY2_PASSWORD; do
[[ -n "${!var:-}" ]] || { echo "缺少 .env 变量: $var"; exit 1; } [[ -n "${!var:-}" ]] || { echo "缺少 .env 变量: $var"; exit 1; }
done done
mkdir -p "$OUT_DIR" mkdir -p "$OUT_DIR"
sed -e "s|\${VPS_IP}|${VPS_IP}|g" \ sed -e "s|\${VPS_IP}|${VPS_IP}|g" \
-e "s|\${DOMAIN}|${DOMAIN}|g" \ -e "s|\${DOMAIN}|${DOMAIN}|g" \
-e "s|\${UUID}|${UUID}|g" \ -e "s|\${UUID}|${UUID}|g" \
-e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \ -e "s|\${REALITY_SERVER_NAME}|${REALITY_SERVER_NAME}|g" \
-e "s|\${REALITY_PUBLIC_KEY}|${REALITY_PUBLIC_KEY}|g" \ -e "s|\${REALITY_PUBLIC_KEY}|${REALITY_PUBLIC_KEY}|g" \
-e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \ -e "s|\${REALITY_SHORT_ID}|${REALITY_SHORT_ID}|g" \
-e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \ -e "s|\${HY2_PASSWORD}|${HY2_PASSWORD}|g" \
"$ROOT_DIR/client/sing-box-client.json.template" > "$OUT_DIR/sing-box-client.json" "$ROOT_DIR/client/sing-box-client.json.template" > "$OUT_DIR/sing-box-client.json"
cat > "$OUT_DIR/share-links.txt" <<EOF cat > "$OUT_DIR/share-links.txt" <<EOF
========== VLESS + Reality (主力) ========== ========== VLESS + Reality (主力) ==========
vless://${UUID}@${VPS_IP}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SERVER_NAME}&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#Reality-Main vless://${UUID}@${VPS_IP}:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SERVER_NAME}&fp=chrome&pbk=${REALITY_PUBLIC_KEY}&sid=${REALITY_SHORT_ID}&type=tcp#Reality-Main
========== Hysteria2 (备用) ========== ========== Hysteria2 (备用) ==========
hy2://${HY2_PASSWORD}@${DOMAIN}:8443?sni=${DOMAIN}#Hysteria2-Backup hy2://${HY2_PASSWORD}@${DOMAIN}:8443?sni=${DOMAIN}#Hysteria2-Backup
EOF EOF
echo "已生成:" echo "已生成:"
echo " $OUT_DIR/sing-box-client.json" echo " $OUT_DIR/sing-box-client.json"
echo " $OUT_DIR/share-links.txt" echo " $OUT_DIR/share-links.txt"