使用Docker+宝塔面板部署S-UI全记录(含踩坑解决)

使用 Docker + 宝塔面板部署 S-UI 全记录(含踩坑解决)

本文记录了在已安装宝塔面板的 Debian/Ubuntu 服务器上,通过 Docker 部署 S-UI 代理面板的完整过程。整个部署过程其实并不复杂,但有一个地方卡了我很久——Cloudflare + 宝塔的 SSL 配置冲突。这个问题折腾了相当长时间,最终找到了正确的配置方式,特此记录,希望后来者少走弯路。


环境说明

  • 系统:Debian / Ubuntu
  • 面板:宝塔面板(已安装 Docker)
  • 目标:部署 S-UI,绑定域名,配置 HTTPS,封锁直接 IP 访问

图片描述

一、Docker 部署 S-UI

在宝塔终端或 SSH 中执行以下命令拉取并启动容器:

1
2
3
4
5
6
7
docker run -itd \
--name s-ui \
--restart unless-stopped \
--network=host \
-v /etc/s-ui:/etc/s-ui \
-v /usr/local/s-ui:/usr/local/s-ui \
alireza7/s-ui:latest

参数说明:

--network=host 是关键配置,让容器直接共享宿主机网络,避免额外的网络转发开销,延迟与直接安装几乎无差别。--restart unless-stopped 保证服务器重启后容器自动恢复。两个 -v 挂载目录用于持久化配置数据,容器删除重建后数据不丢失。

启动后验证运行状态:

1
2
docker ps | grep s-ui
docker logs s-ui

默认访问地址为 http://服务器IP:2095/app/,默认账号密码均为 admin首次登录后请立即修改


二、绑定域名并配置 HTTPS

直接用 IP+端口访问既不安全也容易暴露,建议通过 Nginx 反向代理绑定域名。

1. 添加站点

宝塔面板 → 网站 → 添加站点,域名填自己的域名(如 sui.example.com),不需要数据库和 PHP。

2. 配置反向代理

进入站点设置 → 反向代理 → 添加反向代理:

  • 目标 URL:http://127.0.0.1:2095
  • 发送域名:$host

保存后访问 http://sui.example.com/app/ 即可正常打开面板。

3. 申请 SSL 证书

站点设置 → SSL → Let’s Encrypt,勾选域名后申请免费证书,申请成功后开启强制 HTTPS。

前提: 域名 DNS 的 A 记录需提前解析到服务器 IP,解析生效后再申请,否则证书申请会失败。


三、封锁 IP 直接访问(隐藏 2095 端口)

直接暴露 IP:2095 很容易被爬虫扫描到,建议通过防火墙限制只允许本机访问该端口:

1
2
# 只允许本机访问 2095,拒绝外部直连
iptables -I INPUT -p tcp --dport 2095 ! -s 127.0.0.1 -j DROP

为防止规则重启后丢失,安装持久化工具保存规则:

1
2
apt install iptables-persistent -y
netfilter-persistent save

规则保存后,http://服务器IP:2095/app/ 将无法从外部访问,只能通过域名进入面板。

如果使用阿里云、腾讯云等云服务器,还需要在云控制台的安全组中删除 2095 端口的入站规则,双重保险。


四、核心踩坑:Cloudflare + 宝塔 SSL 配置冲突(最终解决方案)

这是整个部署过程中最让我头疼的问题,折腾了很长时间,现在把最终有效的方案完整写出来。

问题背景

域名套了 Cloudflare CDN,宝塔也申请了 SSL 证书,反向代理也配好了,但浏览器访问始终出现红色盾牌、不安全提示,或者连接直接报错。隐私模式有时正常、有时也不正常,排查了半天始终找不到根本原因。

根本原因

Cloudflare 和宝塔之间的 SSL 模式没有对齐。流量链路实际上是:

用户浏览器 → Cloudflare → 宝塔服务器

这中间有两段 SSL 连接,Cloudflare 的 SSL 模式决定了它与源站(宝塔)之间如何处理 HTTPS。如果模式配置不一致,就会出现证书验证失败、混合内容、连接异常等各种奇怪问题。

最终有效的配置方案

经过反复测试,以下三步组合才是真正让一切正常工作的关键:

第一步:Cloudflare SSL 模式设为”完全 (Strict)”

登录 Cloudflare 控制台 → 选择域名 → SSL/TLS → 概述,将加密模式改为完全 (Strict)

这个模式要求 Cloudflare 在访问源站时,必须验证源站证书的有效性。很多教程会建议用”灵活”模式图省事,但灵活模式下 Cloudflare 到源站这段是 HTTP 明文传输,安全性差,而且与宝塔强制 HTTPS 同时开启时会造成重定向循环。”完全”模式不验证证书有效性,也存在中间人风险。只有 Strict 才是最规范、最稳定的选择。

第二步:宝塔部署有效的 SSL 证书

Cloudflare Strict 模式要求源站证书必须是被信任的有效证书,有两种方式二选一:

方式一:使用宝塔自带 Let’s Encrypt 申请免费证书(推荐,自动续期)。

方式二:在 Cloudflare 控制台 → SSL/TLS → 源服务器 → 创建证书,生成源站证书(Origin Certificate),然后手动粘贴到宝塔该域名的 SSL 配置中。源站证书有效期可选 15 年,不需要频繁续期。

第三步:关闭宝塔的强制 HTTPS

这一步是最容易被忽略、也最关键的一步。

在宝塔 → 网站 → 该域名的 SSL 设置里,关闭”强制 HTTPS”开关

原因:Cloudflare 到源站的请求本身已经是 HTTPS,宝塔再强制跳转 HTTPS 会造成重复重定向,部分情况下直接导致连接失败或循环跳转。HTTPS 的强制跳转应该交给 Cloudflare 来做(在 Cloudflare 的”边缘证书”里开启”始终使用 HTTPS”),而不是在宝塔这一侧设置。

配置完成后的访问链路

1
用户 ---(HTTPS)---> Cloudflare ---(HTTPS, 验证证书)---> 宝塔 Nginx ---> S-UI 2095

整条链路全程加密,证书验证严格,不会出现任何安全警告。


其他小问题

浏览器显示不安全但隐私模式正常

这是浏览器缓存问题,SSL 本身配置没问题。按 F12 打开开发者工具,右键地址栏刷新按钮,选择”清空缓存并硬性重新加载”,只清除当前页面缓存,不影响其他网站。

控制台黄色警告

部署完成后控制台可能出现两条黄色提示,均不影响使用:[Intervention] Slow network is detected 是网络较慢时浏览器自动使用备用字体的提示;Input elements should have autocomplete attributes 是 S-UI 前端代码本身的小问题,忽略即可。


五、节点配置(套域名 + TLS)

S-UI 面板搭建完成后,在”入站”中添加节点。以下是三种常用协议的配置要点:

VLESS + TLS

协议选 vless,传输方式选 tcp,开启 TLS 后填写域名和证书路径。证书路径通常为宝塔申请后的:

  • 证书:/www/server/panel/vhost/cert/你的域名/fullchain.pem
  • 密钥:/www/server/panel/vhost/cert/你的域名/privkey.pem

VMess + WebSocket + TLS

协议选 vmess,传输方式选 ws,填写自定义路径(如 /vmess),开启 TLS 并填写证书路径。WebSocket 传输更适合后续套 CDN 使用。

Hysteria2(HY2)

协议选 hysteria2,端口避开 443(如使用 18443),根据服务器实际带宽填写上传/下载速率。

注意: HY2 基于 UDP 协议,需要在宝塔防火墙和云服务商安全组中放行对应端口的 UDP 流量,而不是 TCP。


六、关于 Docker 部署的延迟问题

使用 Docker 部署时,如果担心延迟比直接安装高,实际上使用 --network=host 网络模式后容器直接共享宿主机网络栈,与直接安装在系统上几乎没有差别,延迟差距通常在 1ms 以内,可以忽略不计。只有使用默认的 bridge 网络模式才会有明显的额外转发开销。


总结

步骤 关键点
Docker 启动 必须使用 --network=host
反向代理 目标填 127.0.0.1:2095
SSL 先解析 DNS,再申请证书
Cloudflare SSL 模式 必须设为”完全 (Strict)”,不能用”灵活”
宝塔强制 HTTPS 必须关闭,由 Cloudflare 侧控制跳转
源站证书 Let’s Encrypt 或 CF 源站证书二选一
封锁 IP 访问 iptables 限制 + 云安全组双重保障
HY2 协议 防火墙需放行 UDP 端口
证书路径 宝塔证书在 /www/server/panel/vhost/cert/