目录
可以。同一台 Windows 11 可以同时运行两个 S-UI 实例,但必须把两个实例的以下资源完全隔离:
- 安装目录
- Windows 服务名称
- 数据库目录
- 面板端口
- 订阅端口
- 所有 Sing-box 入站端口
- 日志和证书目录
S-UI 官方 Windows 安装脚本默认固定使用:
- 安装目录:
C:\Program Files\s-ui - 服务名称:
s-ui - 面板端口:
2095 - 订阅端口:
2096
因此,不能直接把官方安装程序连续执行两次,否则第二次会覆盖或复用第一个实例。 (GitHub)
一、推荐规划
| 项目 | S-UI 实例1 | S-UI 实例2 |
|---|---|---|
| 安装目录 | C:\Program Files\s-ui |
C:\Program Files\s-ui2 |
| Windows 服务名 | s-ui |
s-ui2 |
| 面板端口 | 2095 |
2195 |
| 订阅端口 | 2096 |
2196 |
| 面板路径 | /app/ |
/app2/ |
| 订阅路径 | /sub/ |
/sub2/ |
30001~30999 |
31001~31999 |
|
| 入站端口 | 2080 | 2180 |
访问地址分别是:
实例1: http://10.10.28.10:2095/app/ 实例2: http://10.10.28.10:2195/app2/
订阅地址分别是:
实例1: http://10.10.28.10:2096/sub/用户订阅标识 实例2: http://10.10.28.10:2196/sub2/用户订阅标识
二、在现有 S-UI 基础上创建第二个实例
假设你现在的第一个实例已经安装在:
C:\Program Files\s-ui
以下操作使用管理员身份运行 CMD。
1. 暂时停止第一个实例
net stop s-ui
2. 复制程序文件,但不要复制数据库
创建目录:
mkdir "C:\Program Files\s-ui2
执行:
robocopy "C:\Program Files\s-ui" "C:\Program Files\s-ui2" /E /XD db logs cert /XF s-ui-service.exe s-ui-service.xml
然后重新启动第一个实例:
net start s-ui
这样会复制:
sui.exewinsw.exebin目录- Sing-box 核心程序
- 其他运行文件
但不会复制第一个实例的:
- 数据库
- 日志
- 证书
创建第二个实例所需目录:
mkdir "C:\Program Files\s-ui2\db" mkdir "C:\Program Files\s-ui2\logs" mkdir "C:\Program Files\s-ui2\cert"
不建议直接复制第一个实例的
db目录,否则两个实例会拥有完全相同的入站端口配置,启动 Sing-box 时容易发生端口冲突。
3. 初始化第二个实例数据库
进入第二个实例目录:
cd /d "C:\Program Files\s-ui2"
执行数据库迁移:
sui.exe migrate
4. 设置第二个实例的面板和订阅端口
执行:
sui.exe setting -port 2195 -path "/app2/" -subPort 2196 -subPath "/sub2/"
参数说明:
-port 后台管理面板端口 -path 后台管理面板路径 -subPort 订阅服务端口 -subPath 订阅服务路径
设置后,第二个实例后台地址为:
http://10.10.28.10:2195/app2/
第二个实例订阅基础地址为:
http://10.10.28.10:2196/sub2/
5. 设置第二个实例管理员账号
例如:
sui.exe admin -username "admin2" -password "请替换成复杂密码"
不要让两个实例使用相同的弱密码。
三、创建第二个 Windows 服务
官方 Windows 服务配置使用 WinSW,默认服务ID是 s-ui,工作目录使用程序所在目录,数据库使用相对目录 db。第二个实例必须修改服务ID。 (GitHub)
1. 创建第二个服务配置文件
创建文件:
C:\Program Files\s-ui2\s-ui2-service.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?> <service> <id>s-ui2</id> <name>S-UI Proxy Panel 2</name> <description>S-UI second proxy panel instance</description> <executable>%BASE%\sui.exe</executable> <arguments></arguments> <workingdirectory>%BASE%</workingdirectory> <env name="SUI_BIN_FOLDER" value="bin" /> <env name="SUI_DB_FOLDER" value="db" /> <env name="SUI_DEBUG" value="false" /> <logmode>rotate</logmode> <logpath>%BASE%\logs</logpath> <log size="10 m" /> <log keep="10" /> <onfailure action="restart" delay="10 sec" /> <onfailure action="restart" delay="20 sec" /> <onfailure action="none" /> <resetfailure>1 hour</resetfailure> <startmode>Automatic</startmode> <depend>tcpip</depend> <depend>netman</depend> </service>
这里最关键的是:
<id>s-ui2</id>
它不能还是:
<id>s-ui</id>
否则会和第一个服务冲突。
2. 创建第二个 WinSW 服务程序
进入目录:
cd /d "C:\Program Files\s-ui2"
复制 WinSW:
copy winsw.exe s-ui2-service.exe
最终必须存在两个同名文件:
s-ui2-service.exe s-ui2-service.xml
WinSW 会根据 EXE 文件名寻找对应的 XML 配置。
3. 安装第二个服务
s-ui2-service.exe install
启动第二个服务:
net start s-ui2
查询状态:
sc query s-ui2
同时检查两个服务:
sc query s-ui sc query s-ui2
正常情况下,两个服务都应显示:
STATE : 4 RUNNING
四、开放 Windows 防火墙端口
允许内网访问第二个后台:
New-NetFirewallRule ` -DisplayName "S-UI2 Panel 2195" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 2195 ` -RemoteAddress Any ` -Action Allow
允许访问第二个订阅端口:
New-NetFirewallRule ` -DisplayName "S-UI2 Subscription 2196" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 2196 ` -RemoteAddress Any ` -Action Allow
后续在第二个 S-UI 中创建 VLESS、Mixed、SOCKS 或 HTTP 入站后,还需要单独放行相应入站端口。
例如第二个实例创建了 2180 入站:
New-NetFirewallRule ` -DisplayName "S-UI2 Inbound 2180" ` -Direction Inbound ` -Protocol TCP ` -LocalPort 2180 ` -RemoteAddress Any ` -Action Allow
五、检查端口是否正常监听
执行:
netstat -ano | findstr ":2095" netstat -ano | findstr ":2096" netstat -ano | findstr ":2195" netstat -ano | findstr ":2196"
或者在 PowerShell 中执行:
Get-NetTCPConnection -State Listen |
Where-Object {
$_.LocalPort -in 2095,2096,2195,2196
} |
Format-Table LocalAddress,LocalPort,OwningProcess
测试第二个后台:
Test-NetConnection 127.0.0.1 -Port 2195
正常应该显示:
TcpTestSucceeded : True
六、两个实例最容易发生的冲突
1. 面板端口冲突
不能两个实例都使用:
2095
第二个可以改成:
2195
2. 订阅端口冲突
不能两个实例都使用:
2096
第二个可以改成:
2196
3. Sing-box 入站端口冲突
假设实例1已经使用:
0.0.0.0:2080
实例2就不能继续使用:
0.0.0.0:2080
实例2应改为:
0.0.0.0:2180
同一台电脑、同一个IP、同一个协议的监听端口不能重复。
4. 80和443端口冲突
如果两个实例都创建了监听:
0.0.0.0:80 0.0.0.0:443
一定会冲突。
解决办法是:
- 使用不同端口,例如
443和8443 - 或给电脑配置不同IP,并让两个实例分别绑定不同IP
- 或只让 Nginx/Caddy 监听
80/443,再反向代理到两个 S-UI 实例
5. Clash API或V2Ray API端口冲突
假如你手工启用了:
{
"external_controller": "127.0.0.1:9090"
}
第二个 Sing-box 实例不能也使用 9090,应改成例如:
{
"external_controller": "127.0.0.1:9190"
}
Sing-box 的 API 本身也是一个监听服务,因此不同实例需要不同监听端口。 (Sing Box)
七、是否真的需要两个 S-UI 实例
结合你前面的场景:
- S-UI 运行在服务器A
- 服务器B、服务器C提供不同的 HTTP 代理
- 希望不同用户从不同代理出口访问海外网站
这种情况通常不需要运行两个 S-UI 实例。
一个 S-UI 实例中就可以配置:
Outbound-B 类型:HTTP 服务器:服务器B的IP 端口:服务器B的3proxy端口
以及:
Outbound-C 类型:HTTP 服务器:服务器C的IP 端口:服务器C的3proxy端口
然后分别创建:
Inbound-User-B → 路由到 Outbound-B Inbound-User-C → 路由到 Outbound-C
只有以下情况才建议运行两个实例:
- 不同管理员分别管理
- 两套用户和数据库必须完全隔离
- 一套生产环境,一套测试环境
- 两套订阅、日志、流量统计必须独立
- 防止修改一个实例时影响另一套业务
对于你目前的“多台代理服务器作为不同出口”场景,优先建议使用一个 S-UI 配置多个 Outbound;两个实例虽然可行,但维护和端口管理会更复杂。