甲骨文x-ui搭建过程笔记
甲骨文开台机子
此处略过,注意主机选择ubuntu2004
防火墙相关:「硬核教程」Oracle Cloud甲骨文云设定安全组仍无法访问的解决办法-Wood Chen
关闭iptables:
1 | 1.输入以下命令,来关闭实例的防火墙,开放所有端口: |
配置firewalld,注意开放22,80,443,2053,2083,8087,2096,8443
1 | sudo apt update |
上面的命令一定要一个一个执行!
- 查看防火墙状态:sudo firewall-cmd —zone=public —list-ports
- 查看防火墙当前规则:sudo firewall-cmd —list-all
- 确认特定端口是否开放:sudo firewall-cmd —zone=public —query-port=8080/tcp
然后重启服务器!!!!
x-ui配置
设置时间:
1
2sudo timedatectl set-timezone Asia/Shanghai
sudo hwclock --systohc-
1
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
- 第一个不能默认的sqlite,极其容易瓶颈然后死机,选PostgreSQL
- 第二个选项是否要自定义面板端口,选y,然后输入2053
- 第三个选项是申请ssl,选1用域名申请,然后输入面板的域名(不是根域名)
- 端口是证书申请的端口,默认80即可
配置ssl
先在cloudflare添加解析,确保能ping- 面板panel.xxx
- 订阅:ding.xxx
- reality:reality.xxx
- ws+tls:ws.xxx
1
2sudo systemd-resolve --statistics #查看当前缓存
sudo systemd-resolve --flush-caches #刷新缓存vps输入x-ui,申请域名的ssl证书
- 一定要先选择通过domain(域名)获取ssl
- 先输入域名
- 监听端口默认80即可
- 成功获取ssl(没有红色高亮)之后会先问Would you like to modify —reloadcmd for ACME? (y/n):
这里选y,然后选择1(Preset: systemctl reload nginx ; x-ui restart) - 然后会问Would you like to set this certificate for the panel? (y/n):
这里选n,不选n新域名就被配置到面板上了
请注意最后一步是否把域名配置进panel选否,否则面板地址就变了
然后在申请ip证书
申请ip证书是为了做集群的时候在主控面板里添加其他节点时使用ip的方式,因为域名会套cdn代理,造成大量ssl handshake错误导致面板崩溃!输入x-ui,选择20,然后选择6获取ip证书
然后正常申请,然后会问Would you like to set this certificate for the panel? (y/n):
这里选n,不选n新域名就被配置到面板上了
进入主控面板,配置面板ssl,配置订阅ssl
- 面板在常规里头设置,
面板监听域名填写index.xxx,顺便检查一下证书是否正确 - 订阅在订阅设置里头,
监听域名填写ding.xxx,顺便检查一下证书是否正确 - 修改订阅的
URI 路径,字母数字混合复杂一点
- 面板在常规里头设置,
(*如果有)子服务器,还需要配置节点组集群:
- 子节点的面板一定要注意,常规里头设置,
面板监听域名这什么都不要填,因为主控面板要通过ip方式直连访问子面板 - 订阅在订阅设置里头,
监听域名填写ding.xxx,顺便检查一下证书是否正确 - 修改订阅的
URI 路径,字母数字混合复杂一点
- 子节点的面板一定要注意,常规里头设置,
进cloudflare配置小黄云和ssl
dns里头注意除了reality的ssl不挂小黄云代理,其他都要代理上
ssl里头注意要开启完整或者完整(严格),不能选自动


进入主控面板,添加节点:
协议选https
地址填子服务器的ip,端口就是面板端口,基础路径就是面板路径
TLS校验选择
固定证书,然后获取固定证书的sha-256这里一定要确认子服务器上有ip的ssl证书
api令牌就天子服务器上的api令牌即可
测试链接,确保正常
进入面板建两个协议
vless+vision+reality:正常配置- 分享地址策略选自定义,地址填reality.xxx,端口443
- 传输选tcp(raw)
- 安全选reality
- 开启嗅探
vless+ws+tls:
- 地址写面板地址,分享地址策略选自定义,地址填
*.cloudflare.19931110.xyz,这个是cdn优选域名 - 传输选websocket,然后得添加主机ws.xxx,路径随便填,
- 安全选tls。
- min/ max version改为1.1-1.3,删除所有alpn(或者只保留http/1.1),证书选择面板证书,然后把中间的域名替换成ws.xxx(一般获取到的是index.xxx就是之前设置的面板域名)
安装warp:fscarmen / warp · GitLab,选择12安装 WireProxy
1
wget -N https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh && bash menu.sh [option] [lisence/url/token]
配置面板出入站:xray设置-高级设置
- 直接把全部替换成下面这些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146{
"inbounds": [
{
"listen": "127.0.0.1",
"port": 62789,
"protocol": "tunnel",
"settings": {
"rewriteAddress": "127.0.0.1"
},
"tag": "api"
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "AsIs",
"finalRules": [
{
"action": "allow"
}
]
}
},
{
"tag": "warp",
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 40000
}
]
}
},
{
"tag": "WARP-socks5-v4",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv4"
},
"proxySettings": {
"tag": "warp"
}
},
{
"tag": "WARP-socks5-v6",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv6"
},
"proxySettings": {
"tag": "warp"
}
},
{
"tag": "blocked",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": [
"api"
],
"outboundTag": "api"
},
{
"type": "field",
"domain": [
"ip.sb",
"geosite:google",
"scholar.google.com",
"scholar.google.com.hk"
],
"outboundTag": "WARP-socks5-v4"
},
{
"type": "field",
"domain": [
"geosite:netflix",
"p3terx.com",
"ip111.cn",
"byr.pt",
"ip.gs"
],
"outboundTag": "WARP-socks5-v6"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "blocked"
},
{
"type": "field",
"protocol": [
"bittorrent"
],
"outboundTag": "blocked"
}
],
"domainStrategy": "AsIs"
},
"log": {
"access": "none",
"dnsLog": false,
"error": "",
"loglevel": "warning",
"maskAddress": ""
},
"policy": {
"system": {
"statsInboundDownlink": true,
"statsInboundUplink": true,
"statsOutboundDownlink": false,
"statsOutboundUplink": false
},
"levels": {
"0": {
"statsUserDownlink": true,
"statsUserUplink": true
}
}
},
"api": {
"services": [
"HandlerService",
"LoggerService",
"StatsService",
"RoutingService"
],
"tag": "api"
},
"metrics": {
"listen": "127.0.0.1:11111",
"tag": "metrics_out"
},
"stats": {}
}
- 直接把全部替换成下面这些:
时间设置
- 首先输入
1 | date -R |
查看当下系统时间是否一致。
- 设置时区,亚洲/上海:
1 | sudo timedatectl set-timezone Asia/Shanghai |
- 将当前时间写入BIOS避免重启之后失效:
1 | apt install util-linux-extra |
- 再次查看日期是否更改成功
1 | date -R |
cloudflare设置
由于订阅的地址无法修改,都是xxx.xxx.com,但是两个协议只想让reality访问直连域名(443端口),ws+tls(8443端口,自己改优选ip才能使用)需要阻断以保证vps安全性,故还需配置cloudflare
待定,目前关闭reality,只是用ws+tls
防火墙设置
1 | #开放端口 |
bbr+cake加速
安装锐速 BBR+cake
支持系统:Centos 6+/Debian 7+/Ubuntu 14+,BBR 魔改版不支持 Debian 8。
注意:该脚本在 Vultr 各个系统均测试通过,如果期间有出现任何问题,可向原作者反映帮助改善。
运行以下命令:
1 | wget -N --no-check-certificate "https://github.com/ylx2016/Linux-NetSpeed/raw/master/tcp.sh" && chmod +x tcp.sh && ./tcp.sh |
3x-ui脚本死循环导致宕机问题
7.4.2版本的x-ui脚本有一个严重bug,执行完20里头的ssl证书申请后可能会引发死循环:
/usr/bin/x-ui 里的 ssl_cert_issue_main() 在 /usr/bin/x-ui:1291 开始,read -rp “Choose an option: “ choice 没有做 EOF/读失败判断。
一旦进入这个 SSL 菜单后标准输入断掉,默认分支会在 /usr/bin/x-ui:1467 递归再次调用 ssl_cert_issue_main(),形成死循环。
- restart() 在 /usr/bin/x-ui:529 会执行 systemctl restart x-ui,然后 sleep 2。这和你机器上上一轮启动里 2026-07-03 16:11:30 到 2026-07- 03 16:27:05 每约 2 秒一次的重启节奏完全吻合。
复现
printf ‘20\n’ | x-ui 会无限刷 Invalid option,证明当前安装的脚本确实带着这个 EOF 死循环问题。这个现象和上游已 知问题一致: https://github.com/MHSanaei/3x-ui/issues/4390
总结
不是内存爆、不是 OOM、不是 x-ui 二进制崩溃。是这个菜单/脚本在后台持续跑,疯狂 systemctl restart x-ui,把面板和 xray 一起不断重启,最后 把机器拖到 SSH 都连不上。
处理建议
先不要再用 x-ui 的 SSL 证书菜单,尤其是 20 这个“SSL Certificate Management”入口,直到脚本补上 EOF 保护。 如果下次又出现同样现象,应该先杀掉那个脚本进程,而不是只盯着服务本身:
1 | pkill -f '/usr/bin/x-ui|/usr/local/x-ui/x-ui.sh |
然后再看 x-ui 服务状态。
3x-ui长时间运行导致爆内存的问题
因为服务器是1c1g小水管,如果长时间运行(尤其是开了日志)100%会导致内存泄漏然后死机,解决方案就是限制内存
安装swap
- 先检查有没有 swap
1 | free -h |
如果 Swap: 0B 或 swapon --show 没输出,就说明还没配置。
- 创建 2G swap 文件
1 | sudo fallocate -l 2G /swapfile || sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress |
检查是否生效:
1 | free -h |
应该能看到:
1 | /swapfile file 2G ... |
- 设置开机自动启用 swap
1 | grep -q '^/swapfile ' /etc/fstab || echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab |
确认:
1 | grep '^/swapfile ' /etc/fstab |
应该输出:
1 | /swapfile none swap sw 0 0 |
- 优化 swap 使用策略
1 | printf 'vm.swappiness=10\nvm.vfs_cache_pressure=50\n' | sudo tee /etc/sysctl.d/99-vps-memory.conf |
检查:
1 | sysctl vm.swappiness vm.vfs_cache_pressure |
正常应看到:
1 | vm.swappiness = 10 |
- 重启后检查
重启:
1 | sudo reboot |
重新登录后检查:
1 | free -h |
如果还能看到 /swapfile,说明配置成功且重启后自动生效
限制cpu,内存检查cgroup v2还是cgroup v1
跑一下:
1 | stat -fc %T /sys/fs/cgroup |
如果第一行输出是:
1 | cgroup2fs |
就很好。MemoryHigh、MemoryMin/Low、MemorySwapMax 都依赖 cgroup v2 / unified hierarchy;Ubuntu 的 systemd 文档也说明 MemoryLow、MemoryHigh、MemorySwapMax 这类设置只在 unified hierarchy 下支持。(Ubuntu Manpages)
如果
/sys/fs/cgroup显示tmpfs。所以我前面那组里MemoryHigh、MemoryMin、MemorySwapMax不能按预期使用,应该改用 cgroup v1 兼容方案。
1
2
3 stat -fc %T /sys/fs/cgroup
tmpfs
systemd 245
cgroup v2处理办法
执行:
1 | sudo systemctl edit x-ui |
填入:
1 | [Service] |
然后:
1 | sudo systemctl daemon-reload |
检查是否生效:
1 | systemctl show x-ui \ |
再确认 xray 是否被一起限制:
1 | systemd-cgls /system.slice/x-ui.service |
如果看到类似:
1 | x-ui.service |
说明 CPUQuota 和内存限制会同时管住 x-ui + xray。
- CPUQuota 怎么选
先用:
1 CPUQuota=80%意思是最多吃掉 0.8 个 CPU 核。这样能给 SSH、systemd、网络服务留余量。
如果代理速度明显下降,可以改成:
1 CPUQuota=100%如果还是卡,就降到:
1 CPUQuota=60%
- 查看 CPU 核心数
1 nproc
- 查看当前实时占用
1
2
3
4 systemctl status x-ui --no-pager
ps -eo pid,user,%cpu,%mem,rss,comm,args --sort=-%cpu | head -20
free -h
uptime如果限制后还是偶尔 CPU 打满,再加一个 CPU 长时间高占用自动重启 x-ui 的 timer;但第一步先把
CPUQuota=80%配上,通常就能明显避免整机卡死。
保护 SSH,避免爆内存时登不上
再给 SSH 提高存活优先级:
1 | sudo systemctl edit ssh |
填入:
1 | [Service] |
应用:
1 | sudo systemctl daemon-reload |
如果你的 SSH 服务名是 sshd,则用:
1 | sudo systemctl edit sshd |
给面板套一个cloudflare Access认证防止被扫
前提:面板地址和xray地址不是一个
- 打开zero trust-访问控制-应用程序
- 新建应用程序,然后配置公共主机名(填写你面板的地址,路径可以不加),然后在下面的策略里头添加新策略,然后策略规则选择电子邮件,下面添加好邮箱,右侧策略会话持续时间建议改为
与应用程序会话持续时间相同
- (可选)因为他这里没法绑定端口,所以access通过认证之后没法跳转到面板,可以强制重定向端口解决这个问题。
去域名管理界面(请注意,是域名管理界面,不是zero trust)规则-概述,创建Origin Rules(源服务器规则),选择自定义帅选表达式,然后选择主机名等于<面板地址>,最下面的目标端口重写到你的面板端口即可。这样就可以解决认证后不跳转面板登录页的问题了








