Lyndra's Blog

VPS 搭建脚本

2025-06-03
系统维护网络安全 VPSProxy
21分钟
4098字

之前建立了完整的 VPS 服务器,由于其中的步骤比较繁琐,当更换服务器后,再次恢复成原来的服务会很麻烦。

因此,把其中的固定步骤转换为脚本,通过脚本可快速的重新搭建 VPS。

脚本内容

脚本分为两个,一个是主脚本,包含所有模块,另一个脚本是用于调用主脚本的外壳。脚本也同步分享在 github 仓库 中。

build-all.sh 主脚本
1
#!/usr/bin/env bash
2
#==================================================================
3
# ██╗ ██╗ ██╗███╗ ██╗██████╗ ██████╗ █████╗
4
# ██║ ╚██╗ ██╔╝████╗ ██║██╔══██╗██╔══██╗██╔══██╗
5
# ██║ ╚████╔╝ ██╔██╗ ██║██║ ██║██████╔╝███████║
6
# ██║ ╚██╔╝ ██║╚██╗██║██║ ██║██╔══██╗██╔══██║
7
# ███████╗██║ ██║ ╚████║██████╔╝██║ ██║██║ ██║
8
# ╚══════╝╚═╝ ╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
9
#==================================================================
10
#
11
# 文件名称: build-all.sh
12
# 文件描述: VPS 搭建脚本,包含域名申请,3XUI面板搭建、Sub-Store服务安装、
13
# Hysteria2 安装、Nginx分流配置。需 root 用户运行。
14
# 运行前请自定义修改117-131的端口号。
15
#
722 collapsed lines
16
# 作者: Lyndra <lyndra.hyst@gmail.com>
17
# 版本: 1.0.0
18
# 创建日期: 2025-04-25
19
# 最后修改: 2025-05-29
20
#
21
# 使用许可: GPLv2 or other licenses
22
# Copyright (c) 2025 Lyndra
23
#
24
#==================================================================
25
26
set -eo pipefail
27
28
# 颜色配置
29
RED='\033[0;31m'
30
GREEN='\033[0;32m'
31
YELLOW='\033[1;33m'
32
BLUE='\033[0;34m'
33
NC='\033[0m'
34
35
# 命令配置,格式为:[命令名]="描述::处理函数::选项声明1::选项声明2::..."
36
declare -A COMMAND_MAP=(
37
["setup"]="基础环境设置::handle_setup::-u,--user:指定新建用户名(必须)::-p,--pass:指定新建用户密码(必须)::-s,--ssh-port:指定SSH端口(默认:22222)"
38
["cert"]="证书管理::handle_cert::-d,--domain:指定主域名(必须,建议优先使用二级域名,可免费开启cloudflare代理保护,三级域名不可免费使用)::-e,--email:指定邮箱(必须)::-t,--token:指定Cloudflare API Token(必须)::-z,--zone-id:指定Cloudflare Zone ID(必须)::-a,--account-id:指定Cloudflare Account ID(必须)"
39
["hysteria"]="Hysteria2服务::handle_hysteria::-d,--domain:指定域名(必须,确定证书路径)::-p,--port:指定端口(默认:8443)::-u,--user:指定用户名(必须)::-w,--pass:指定密码(必须)"
40
["xui"]="X-UI面板::handle_xui"
41
["substore"]="Sub-Store服务::handle_substore::-a,--api-key:指定API密钥(必须)"
42
["nginx"]="Nginx分流配置::handle_nginx::-d,--domain:指定域名(必须,确定证书路径)::-x,--xui-domain:指定X-UI域名(必须)::-s,--substore-domain:指定Sub-Store域名(必须)::-p,--port-xui:指定xui访问端口(必须)"
43
)
44
45
# 错误处理函数
46
panic() {
47
echo -e "${RED}[错误]${NC} $1" >&2
48
exit 1
49
}
50
51
# 日志输出函数
52
log_info() {
53
echo -e "${GREEN}[信息]${NC} $1" >&2
54
}
55
56
log_warning() {
57
echo -e "${YELLOW}[警告]${NC} $1" >&2
58
}
59
60
log_success() {
61
echo -e "${GREEN}[成功]${NC} $1" >&2
62
}
63
64
log_debug() {
65
echo -e "${BLUE}[调试]${NC} $1" >&2
66
}
67
68
##############################################
69
# 通用的帮助信息生成函数 #
70
##############################################
71
72
show_command_help() {
73
local cmd="$1"
74
local info="${COMMAND_MAP[$cmd]}"
75
76
# 1) 把所有 "::" 替换成一个不会在脚本中出现的分隔符,比如 '|'
77
info="${info//::/|}"
78
79
# 2) 这时才能安全地用 IFS='|' 来做分割
80
local desc handler options_str
81
IFS="|" read -r desc handler options_str <<<"$info"
82
83
echo -e "${YELLOW}命令: ${GREEN}$cmd${NC}"
84
echo -e "${YELLOW}描述: ${NC}$desc"
85
echo -e "${YELLOW}选项:${NC}"
86
87
# 3) 选项声明里可能有多段「::」分隔,继续替换并拆分
88
options_str="${options_str//::/|}"
89
IFS="|" read -ra opt_lines <<<"$options_str"
90
91
for opt_line in "${opt_lines[@]}"; do
92
[[ -z "$opt_line" ]] && continue
93
94
# opt_line 类似 "-p,--package:指定包名(必须)"
95
# 用 ":" 分割出(短+长选项)和描述
96
IFS=":" read -r flags desc <<<"$opt_line"
97
printf " ${GREEN}%-20s${NC} %s\n" "$flags" "$desc"
98
done
99
}
100
101
# 主帮助信息
102
show_help() {
103
echo -e "${YELLOW}使用方法:${NC}"
104
echo " $0 [命令] [选项]"
105
echo
106
echo -e "${YELLOW}可用命令:${NC}"
107
for cmd in "${!COMMAND_MAP[@]}"; do
108
local desc=${COMMAND_MAP[$cmd]%%::*}
109
printf " ${GREEN}%-15s${NC} %s\n" "$cmd" "$desc"
110
done
111
echo -e "\n使用 ${YELLOW}$0 命令 --help${NC} 查看具体命令帮助"
112
}
113
114
##############################################
115
# 命令处理函数 #
116
##############################################
117
118
119
# ==========================================
120
# 配置信息开始,请根据实际情况修改
121
# ==========================================
122
123
# 新建用户的组id和用户id,默认 1001
124
groupid=1001
125
userid=1001
126
127
# ssh 登陆端口配置,请确保该端口未被占用
128
port_ssh=22222
129
130
# Hysteria 主端口配置
131
port_hysteria=8443
132
133
# Hysteria 跳跃端口配置
134
port_hysteria_jump_1=50220
135
port_hysteria_jump_1_end=50959
136
port_hysteria_jump_2=60133
137
port_hysteria_jump_2_end=60968
138
139
# ==========================================
140
# 配置信息结束
141
# ==========================================
142
143
144
# 基础环境设置
145
handle_setup() {
146
local username=""
147
local password=""
148
149
while [[ $# -gt 0 ]]; do
150
case $1 in
151
-u | --user)
152
username="$2"
153
shift 2
154
;;
155
-p | --pass)
156
password="$2"
157
shift 2
158
;;
159
-s | --ssh-port)
160
port_ssh="$2"
161
shift 2
162
;;
163
-h | --help)
164
show_command_help "setup"
165
exit 0
166
;;
167
*)
168
panic "未知选项: $1"
169
;;
170
esac
171
done
172
173
[[ -z "$username" ]] && panic "必须指定用户名"
174
[[ -z "$password" ]] && panic "必须指定密码"
175
176
log_info "开始设置基础环境..."
177
178
# 安装常用软件
179
log_info "安装常用软件..."
180
apt update && apt upgrade -y&& apt-get install -y curl vim ufw sudo
181
182
# 创建非root用户
183
log_info "创建非root用户: $username"
184
185
getent group ${groupid} || groupadd -g ${groupid} vps
186
getent passwd "$username" || useradd -ms /bin/bash -u ${userid} -g ${groupid} -G sudo "$username"
187
echo "$username:$password" | chpasswd
188
echo "$username ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
189
190
log_info "非root用户创建完成,请在新终端中使用 $username 用户登录,确认是否生效,生效请输入 y/Y,否则请重新运行脚本"
191
read -p "请输入y确认:" confirm
192
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
193
panic "非root用户创建完成未生效,请检测系统环境,重新运行脚本"
194
fi
195
196
# SSH安全加固
197
log_info "配置SSH安全设置..."
198
199
# 检查 SSH 端口是否已经修改
200
if grep -q "^Port $port_ssh" /etc/ssh/sshd_config; then
201
log_info "SSH 端口已设置为 $port_ssh,跳过修改"
202
else
203
sed -i "s/#Port 22/Port $port_ssh/" /etc/ssh/sshd_config
204
sed -i "s/^Port 22/Port $port_ssh/" /etc/ssh/sshd_config
205
log_info "SSH 端口已修改为 $port_ssh"
206
fi
207
208
# 检查 root 登录是否已经禁用
209
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
210
log_info "Root 登录已禁用,跳过修改"
211
else
212
sed -i "s/#PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config
213
sed -i "s/^PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config
214
log_info "Root 登录已禁用"
215
fi
216
217
ufw allow "$port_ssh"
218
ufw deny 22
219
220
systemctl restart ssh
221
222
log_info "SSH安全设置完成,请在新终端中使用新端口 ssh -p ${port_ssh} ${username}@ip,确认是否生效,生效请输入 y/Y,否则请重新运行脚本"
223
read -p "请输入y确认:" confirm
224
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
225
panic "SSH安全设置未生效,请检测系统环境,重新运行脚本"
226
fi
227
228
# 防火墙设置
229
log_info "配置防火墙..."
230
ufw allow 80
231
ufw allow 443
232
233
ufw --force enable
234
235
log_success "基础环境设置完成"
236
}
237
238
# 证书管理
239
# 证书管理 - 改进版本
240
handle_cert() {
241
local email=""
242
local cf_token=""
243
local cf_zone_id=""
244
local cf_account_id=""
245
local domain=""
246
local key_type="ec-256" # 新增:默认使用 EC-256
247
248
while [[ $# -gt 0 ]]; do
249
case $1 in
250
-d | --domain)
251
domain="$2"
252
shift 2
253
;;
254
-e | --email)
255
email="$2"
256
shift 2
257
;;
258
-t | --token)
259
cf_token="$2"
260
shift 2
261
;;
262
-z | --zone-id)
263
cf_zone_id="$2"
264
shift 2
265
;;
266
-a | --account-id)
267
cf_account_id="$2"
268
shift 2
269
;;
270
-k | --key-type)
271
key_type="$2"
272
shift 2
273
;;
274
-h | --help)
275
show_command_help "cert"
276
exit 0
277
;;
278
*)
279
panic "未知选项: $1"
280
;;
281
esac
282
done
283
284
[[ -z "$domain" ]] && panic "必须指定主域名"
285
[[ -z "$email" ]] && panic "必须指定邮箱"
286
[[ -z "$cf_token" ]] && panic "必须指定Cloudflare API Token"
287
[[ -z "$cf_zone_id" ]] && panic "必须指定Cloudflare Zone ID"
288
[[ -z "$cf_account_id" ]] && panic "必须指定Cloudflare Account ID"
289
290
# 验证密钥类型
291
case "$key_type" in
292
"ec-256"|"ec-384"|"2048"|"3072"|"4096")
293
;;
294
*)
295
panic "不支持的密钥类型: $key_type,支持: ec-256, ec-384, 2048, 3072, 4096"
296
;;
297
esac
298
299
log_info "开始申请TLS证书(密钥类型: $key_type)..."
300
301
# 安装acme.sh
302
log_info "安装acme.sh..."
303
curl https://get.acme.sh | sh -s email="$email"
304
apt install socat -y
305
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
306
source ~/.bashrc
307
~/.acme.sh/acme.sh --upgrade --auto-upgrade
308
309
# 设置环境变量
310
export CF_Token="$cf_token"
311
export CF_Zone_ID="$cf_zone_id"
312
export CF_Account_ID="$cf_account_id"
313
314
# 申请证书
315
local username=$(id -un 1001)
316
317
log_info "申请证书: $domain(密钥类型: $key_type)"
318
319
# 检查证书是否已经存在且有效
320
if [[ -f "/home/$username/$domain.cer" ]] && [[ -f "/home/$username/$domain.key" ]]; then
321
if openssl x509 -in "/home/$username/$domain.cer" -noout -checkend 2592000 > /dev/null 2>&1; then
322
log_info "证书已存在且有效期超过30天,跳过申请"
323
log_success "证书检查完成"
324
return 0
325
else
326
log_warning "证书已存在但即将过期或无效,重新申请"
327
fi
328
fi
329
330
# 构建 acme.sh 命令
331
local acme_cmd="~/.acme.sh/acme.sh --issue --dns dns_cf -d \"$domain\" -d \"*.$domain\""
332
333
# 添加密钥长度参数
334
acme_cmd="$acme_cmd --keylength $key_type"
335
336
# 添加输出文件参数
337
acme_cmd="$acme_cmd --key-file /home/$username/$domain.key"
338
acme_cmd="$acme_cmd --fullchain-file /home/$username/$domain.cer"
339
acme_cmd="$acme_cmd --reloadcmd 'bash -c \"nginx -s reload && x-ui restart\"'"
340
341
# 执行命令
342
eval $acme_cmd || log_warning "证书申请结果请检查,目前没有安装 nginx,会导致reload失败,但不代表证书申请失败"
343
344
# 修改权限
345
log_info "修改证书权限..."
346
chmod 644 "/home/$username/$domain.key"
347
chmod 644 "/home/$username/$domain.cer"
348
349
# 将证书重命名拷贝,并确保路径正确,主要用于xui设置路径
350
mkdir -p "/root/cert/$domain"
351
cp "/home/$username/$domain.cer" "/root/cert/$domain/fullchain.pem"
352
cp "/home/$username/$domain.key" "/root/cert/$domain/privkey.pem"
353
354
# 验证证书
355
log_info "验证证书..."
356
if openssl x509 -in "/home/$username/$domain.cer" -noout -text > /dev/null 2>&1; then
357
log_info "证书文件有效"
358
359
# 显示证书信息
360
log_info "证书有效期:"
361
openssl x509 -in "/home/$username/$domain.cer" -noout -dates
362
363
log_info "证书包含的域名:"
364
openssl x509 -in "/home/$username/$domain.cer" -noout -text | grep -A1 "Subject Alternative Name" || echo " $domain, *.$domain"
365
else
366
log_warning "证书文件可能有问题,请检查"
367
fi
368
369
log_success "证书申请完成"
370
}
371
372
# Hysteria2服务
373
# 逐步在Qos,建议搭建reality
374
handle_hysteria() {
375
local username=""
376
local password=""
377
local domain=""
378
379
while [[ $# -gt 0 ]]; do
380
case $1 in
381
-d | --domain)
382
domain="$2"
383
shift 2
384
;;
385
-p | --port)
386
port_hysteria="$2"
387
shift 2
388
;;
389
-u | --user)
390
username="$2"
391
shift 2
392
;;
393
-w | --pass)
394
password="$2"
395
shift 2
396
;;
397
-h | --help)
398
show_command_help "hysteria"
399
exit 0
400
;;
401
*)
402
panic "未知选项: $1"
403
;;
404
esac
405
done
406
407
[[ -z "$domain" ]] && panic "必须指定主域名"
408
[[ -z "$username" ]] && panic "必须指定用户名"
409
[[ -z "$password" ]] && panic "必须指定密码"
410
411
log_info "开始安装Hysteria2服务..."
412
413
# 安装Hysteria2
414
log_info "安装Hysteria2..."
415
bash <(curl -fsSL https://get.hy2.sh/)
416
417
# 配置Hysteria2
418
log_info "配置Hysteria2..."
419
420
cat > /etc/hysteria/config.yaml << EOF
421
listen: :$port_hysteria
422
423
tls:
424
cert: /home/$(id -un $userid)/$domain.cer
425
key: /home/$(id -un $userid)/$domain.key
426
427
auth:
428
type: userpass
429
userpass:
430
$username: $password
431
432
masquerade:
433
type: proxy
434
proxy:
435
url: https://bing.com
436
rewriteHost: true
437
listenHTTP: :80
438
listenHTTPS: :$port_hysteria
439
440
bandwidth:
441
up: 20 mbps
442
down: 50 mbps
443
EOF
444
445
# 配置端口跳跃
446
log_info "配置端口跳跃..."
447
ufw allow $port_hysteria_jump_1:$port_hysteria_jump_1_end/udp
448
ufw allow $port_hysteria_jump_2:$port_hysteria_jump_2_end/udp
449
iptables -t nat -A PREROUTING -i eth0 -p udp --dport $port_hysteria_jump_1:$port_hysteria_jump_1_end -j REDIRECT --to-ports "$port_hysteria"
450
iptables -t nat -A PREROUTING -i eth0 -p udp --dport $port_hysteria_jump_2:$port_hysteria_jump_2_end -j REDIRECT --to-ports "$port_hysteria"
451
ip6tables -t nat -A PREROUTING -i eth0 -p udp --dport $port_hysteria_jump_1:$port_hysteria_jump_1_end -j REDIRECT --to-ports "$port_hysteria"
452
ip6tables -t nat -A PREROUTING -i eth0 -p udp --dport $port_hysteria_jump_2:$port_hysteria_jump_2_end -j REDIRECT --to-ports "$port_hysteria"
453
454
ufw allow $port_hysteria
455
456
log_info "启动Hysteria2服务..."
457
systemctl enable hysteria-server.service --now
458
459
log_success "Hysteria2服务安装完成"
460
}
461
462
# 3X-UI面板
463
handle_xui() {
464
while [[ $# -gt 0 ]]; do
465
case $1 in
466
-h | --help)
467
show_command_help "xui"
468
exit 0
469
;;
470
*)
471
panic "未知选项: $1"
472
;;
473
esac
474
done
475
476
log_info "开始安装3X-UI面板..."
477
478
# 安装X-UI
479
log_info "安装3X-UI..."
480
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
481
482
# 配置X-UI
483
log_info "请手动配置3X-UI,或者使用3X-UI备份恢复"
484
sleep 2
485
x-ui
486
log_success "3X-UI面板安装完成,请在 ngninx 反代后,手动完成 ssl 证书路径配置"
487
}
488
489
# Sub-Store服务
490
handle_substore() {
491
local api_key=""
492
493
while [[ $# -gt 0 ]]; do
494
case $1 in
495
-a | --api-key)
496
api_key="$2"
497
shift 2
498
;;
499
-h | --help)
500
show_command_help "substore"
501
exit 0
502
;;
503
*)
504
panic "未知选项: $1"
505
;;
506
esac
507
done
508
509
[[ -z "$api_key" ]] && panic "必须指定API密钥"
510
511
log_info "开始安装Sub-Store服务..."
512
513
# 安装依赖
514
log_info "安装依赖..."
515
apt update -y && apt install unzip curl wget git -y
516
517
# 安装FNM
518
log_info "安装FNM..."
519
curl -fsSL https://fnm.vercel.app/install | bash
520
source ~/.bashrc
521
522
# 安装Node
523
log_info "安装Node..."
524
fnm install v20.18.0
525
526
# 安装PNPM
527
log_info "安装PNPM..."
528
curl -fsSL https://get.pnpm.io/install.sh | sh -
529
source ~/.bashrc
530
531
# 创建目录
532
log_info "创建目录..."
533
mkdir -p /root/sub-store
534
cd /root/sub-store
535
536
# 下载Sub-Store
537
log_info "下载Sub-Store..."
538
curl -fsSL https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store.bundle.js -o sub-store.bundle.js
539
curl -fsSL https://github.com/sub-store-org/Sub-Store-Front-End/releases/latest/download/dist.zip -o dist.zip
540
unzip -o dist.zip && mv dist frontend && rm dist.zip
541
542
# 创建服务
543
log_info "创建服务..."
544
cat > /etc/systemd/system/sub-store.service << EOF
545
[Unit]
546
Description=Sub-Store
547
After=network-online.target
548
Wants=network-online.target systemd-networkd-wait-online.service
549
550
[Service]
551
LimitNOFILE=32767
552
Type=simple
553
Environment="SUB_STORE_FRONTEND_BACKEND_PATH=/$api_key"
554
Environment="SUB_STORE_BACKEND_CRON=0 0 * * *"
555
Environment="SUB_STORE_FRONTEND_PATH=/root/sub-store/frontend"
556
Environment="SUB_STORE_FRONTEND_HOST=0.0.0.0"
557
Environment="SUB_STORE_FRONTEND_PORT=3001"
558
Environment="SUB_STORE_DATA_BASE_PATH=/root/sub-store"
559
Environment="SUB_STORE_BACKEND_API_HOST=127.0.0.1"
560
Environment="SUB_STORE_BACKEND_API_PORT=3000"
561
ExecStart=/root/.local/share/fnm/fnm exec --using v20.18.0 node /root/sub-store/sub-store.bundle.js
562
User=root
563
Group=root
564
Restart=on-failure
565
RestartSec=5s
566
ExecStartPre=/bin/sh -c ulimit -n 51200
567
StandardOutput=journal
568
StandardError=journal
569
570
[Install]
571
WantedBy=multi-user.target
572
EOF
573
574
# 启动服务
575
log_info "启动服务..."
576
systemctl enable sub-store.service --now
577
578
source /root/.bashrc
579
log_success "Sub-Store服务安装完成"
580
}
581
582
# Nginx分流配置
583
handle_nginx() {
584
local xui_domain=""
585
local substore_domain=""
586
local domain=""
587
local port_xui=""
588
589
while [[ $# -gt 0 ]]; do
590
case $1 in
591
-d | --domain)
592
domain="$2"
593
shift 2
594
;;
595
-x | --xui-domain)
596
xui_domain="$2"
597
shift 2
598
;;
599
-s | --substore-domain)
600
substore_domain="$2"
601
shift 2
602
;;
603
-p | --port-xui)
604
port_xui="$2"
605
shift 2
606
;;
607
-h | --help)
608
show_command_help "nginx"
609
exit 0
610
;;
611
*)
612
panic "未知选项: $1"
613
;;
614
esac
615
done
616
617
[[ -z "$domain" ]] && panic "必须指定主域名"
618
[[ -z "$xui_domain" ]] && panic "必须指定X-UI域名"
619
[[ -z "$substore_domain" ]] && panic "必须指定Sub-Store域名"
620
[[ -z "$port_xui" ]] && panic "必须指定X-UI访问端口"
621
622
log_info "开始配置Nginx分流..."
623
624
# 安装Nginx
625
log_info "安装Nginx..."
626
apt install libnginx-mod-stream nginx -y
627
628
# 配置Nginx
629
log_info "配置Nginx..."
630
631
# 修改主配置文件 - 检查是否已经存在 include 语句
632
if ! grep -q "include /etc/nginx/vps.conf;" /etc/nginx/nginx.conf; then
633
log_info "添加 vps.conf 包含语句到 nginx.conf"
634
sudo sed -i '$a\ include /etc/nginx/vps.conf;' /etc/nginx/nginx.conf
635
else
636
log_info "vps.conf 包含语句已存在,跳过添加"
637
fi
638
639
# 创建分流配置
640
cat > /etc/nginx/vps.conf << EOF
641
# /etc/nginx/vps.conf
642
643
stream {
644
# 定义一个映射,将 SNI 中的服务器名映射到后端标识符
645
map \$ssl_preread_server_name \$backend {
646
hostnames;
647
$substore_domain sub;
648
$xui_domain xui;
649
default hysteria; # 默认后端
650
}
651
652
# 定义各个后端的上游服务器
653
upstream sub {
654
server 127.0.0.1:8444; # $substore_domain 对应的后端,对接的是 nginx server
655
}
656
657
upstream xui {
658
server 127.0.0.1:$port_xui; # $xui_domain 对应的后端
659
}
660
661
upstream hysteria {
662
server 127.0.0.1:$port_hysteria; # 默认后端
663
}
664
665
# 定义一个服务器块,监听指定端口并根据 SNI 分发流量
666
server {
667
listen 443;
668
listen [::]:443;
669
proxy_pass \${backend};
670
ssl_preread on;
671
}
672
}
673
EOF
674
675
# 创建Sub-Store服务器配置
676
cat > /etc/nginx/sites-enabled/vps.conf << EOF
677
server {
678
listen 8444 ssl http2;
679
listen [::]:8444 ssl http2;
680
server_name $substore_domain;
681
682
ssl_certificate /home/$(id -un $userid)/$domain.cer;
683
ssl_certificate_key /home/$(id -un $userid)/$domain.key;
684
685
location / {
686
proxy_pass http://127.0.0.1:3001;
687
proxy_set_header Host \$host;
688
proxy_set_header X-Real-IP \$remote_addr;
689
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
690
}
691
}
692
EOF
693
694
# 移除默认配置
695
rm -f /etc/nginx/sites-enabled/default
696
697
# 测试配置
698
log_info "测试Nginx配置..."
699
nginx -t
700
701
# 重启Nginx
702
log_info "重启Nginx..."
703
systemctl restart nginx
704
705
log_success "Nginx分流配置完成"
706
}
707
708
##############################################
709
# 主逻辑 #
710
##############################################
711
712
main() {
713
[[ $# -eq 0 ]] || [[ "$1" == "--help" ]] && show_help && exit 0
714
715
local cmd="$1"
716
shift
717
718
[[ -n "${COMMAND_MAP[$cmd]}" ]] || panic "未知命令: $cmd"
719
720
# 同样地,这里也要避免直接 IFS="::" 分割
721
# 先用 '|' 替换 "::" ,再做一次分割即可
722
local info="${COMMAND_MAP[$cmd]}"
723
info="${info//::/|}"
724
725
local desc handler options_str
726
IFS="|" read -r desc handler options_str <<<"$info"
727
728
# 调用对应的处理函数
729
$handler "$@"
730
}
731
732
if [ "$EUID" -ne 0 ]; then
733
log_warning "请使用 root 用户运行此脚本" >&2
734
exit 1
735
fi
736
737
main "$@"
run.sh 壳脚本
1
#!/bin/bash
2
3
#==================================================================
4
# ██╗ ██╗ ██╗███╗ ██╗██████╗ ██████╗ █████╗
5
# ██║ ╚██╗ ██╔╝████╗ ██║██╔══██╗██╔══██╗██╔══██╗
6
# ██║ ╚████╔╝ ██╔██╗ ██║██║ ██║██████╔╝███████║
7
# ██║ ╚██╔╝ ██║╚██╗██║██║ ██║██╔══██╗██╔══██║
8
# ███████╗██║ ██║ ╚████║██████╔╝██║ ██║██║ ██║
9
# ╚══════╝╚═╝ ╚═╝ ╚═══╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
10
#==================================================================
11
#
12
# 文件名称: run.sh
13
# 文件描述: VPS构建脚本
14
# 运行环境:Debian 系 Linux 系统,Root 用户运行。
15
# 注意事项:
44 collapsed lines
16
# 1. 运行前,请运行 build-all.sh --help 查看脚本中的命令含义,以及每个指令的参数含义。
17
# 2. 尽可能的先修改 build-all.sh 中的配置端口,保证安全(119-141行)。
18
# 3. 通过Cloudflare申请DNS时,需要确认Cloudflare的api令牌,是否允许了新 vps 的ipv4和ipv6地址。
19
# 4. 尽可能的使用二级域名,CF的代理功能中,二级域名边缘证书是免费的,但三级域名需要开会员才能用。三级域名签发证书,同时使用代理功能,会导致SSL握手失败。
20
# 5. XUI提供备份和恢复功能,但是需要注意其SSL证书路径也会被备份,如果新旧机器的证书不一致,将导致无法网页访问,此时需要命令行修改XUI的SSL证书路径。本脚本会自动复制证书到xui的证书路径。
21
# 6. 对于 xui 上启用的各种协议所需要的端口请手动放行防火墙。
22
# 7. sub-store 建议开启github的glist备份,网上有很多教程,很简单。新机器可以直接完美同步。
23
# 作者: Lyndra <lyndra.hyst@gmail.com>
24
# 版本: 1.0.0
25
# 创建日期: 2025-05-29
26
# 最后修改: 2025-05-29
27
# 使用许可: GPLv2 or other licenses
28
# Copyright (c) 2025 Lyndra
29
#
30
#==================================================================
31
32
echo "运行前请先修改 *build-all.sh* 和 *本脚本* 中的配置信息,确保配置信息正确。"
33
34
echo "输入 y/Y 确认上述操作已完成,输入 n/N 退出"
35
read -p "请输入: " confirm
36
37
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
38
echo "退出脚本"
39
exit 0
40
fi
41
42
# 创建新用户,请根据实际情况修改用户名和密码
43
# 密码需要足够复杂,否则创建用户时会失败。
44
./build-all.sh setup -u username -p password
45
46
# 申请证书,请根据实际情况修改域名、邮箱、cloudflare的api令牌、cloudflare zone id、cloudflare account id。
47
# 请确认cloudflare的api令牌,是否允许了新 vps 的ipv4和ipv6地址。
48
./build-all.sh cert -d 二级域名 -e 邮箱 -t api_token -z zone_id -a account_id
49
50
# 安装 hysteria2,请根据实际情况修改域名、用户名、密码。
51
./build-all.sh hysteria -d 二级域名 -u 用户名 -w 密码
52
53
# 安装 xui,安装过程中请自行配置xui,并记录xui的访问端口
54
./build-all.sh xui
55
56
# 安装 sub-store,请修改token,否则可能会被盗取后端信息。
57
./build-all.sh substore -a custom_token
58
59
./build-all.sh nginx -d 二级域名 -x xui-域名 -s sub-store-域名 -p x-ui-访问端口
本文标题:VPS 搭建脚本
文章作者:Lyndra
发布时间:2025-06-03
总访问量
总访客数人次
Copyright 2025
站点地图