目录如下
注意阅读本篇之前先看一下是否有需求
- 如何互联网访问,即如何安全高速的暴露在公网:主要的需求是在公网上面暴露自己的服务,比如在公司也能访问家中的服务,这块不仅仅是Stable Diffusion可以使用,其他任何服务都可以使用,如果仅仅是在本地部署局域网访问,直接在
web-user.bat
参数中加上--listen
就可以了,这样就可以监听在0.0.0.0
而不是环回接口
127.0.0.1
,局域网中的其他主机比如手机什么的都可以访问。- 模型共享:这么一个需求,在有多张显卡的时候,Stable Diffusion需要有多个实例,每个实例需要单独git clone一个项目,里面放了一堆模型(ControlNet的模型也都很大),有没有办法让这多个实例的模型共享?这样的话既能节省一倍的空间,也能同步更新多个实例的模型文件,一举两得,当然类似的需求也可以,比如一个稳定版、一个beta版本需要共享模型
如果没有上面两个需求,则下面的文章可以不用看了,如果有需求,请注意,下面的内容需要一定的网络基础!并且需要一台在公网上的VPS和一个公网域名!下面详细说下具体内容
如何安全高速的互联网访问?
其实Stable DIffusion本身是可以暴露在公网的,在web-user.bat
参数中加上--share
即可,最终会打印出一个gradio的链接,例如https://51483302-58a3-4e70.gradio.live/
,并且告诉72小时后过期,但是实际体验下来并不稳定,很慢而且过了大概10多分钟就打不开,然后出现下面这个页面:No interface is running right now
因此我们需要自己将服务暴露到公网,创建自己专属的链接。本篇会用到nginx、Wireguard和v兔瑞(后文简称v兔),如果不知道后面两个工具,可以阅读之前的文章,如果不知道nginx,下面的内容请谨慎阅读哦,对你来说可能比较复杂。
- 被Linux创始人称做艺术品的组网神器——WireGuard
- 这篇很重要,一定要先看!!不然后文无法理解:https://zhuanlan.zhihu.com/p/619234999
总体原理如下,再次注意该方案适合暴露所有服务,不仅仅是Stable Diffusion,但是本章没有图中的peer3,peer2就是公网的VPS,peer1就是运行Stable Diffusion的主机,重点来了,peer2其实能访问到peer1的服务了,再在peer2上的nginx上配置一个反向代理
直接指向peer1上的Stable Diffusion服务,这样别人其实就是使用位于公网上面的peer2访问到peer1的服务。
本章节不会详细将怎么安装什么的,直接说原理和核心配置文件,注意本文中peer2为Linux环境,peer1为Windows环境,这点上面的参考文章不同
peer2配置(内网IP:5.5.5.1)
首先配置一下nginx,这里说一下要点,假设申请的域名为baidu.com
,那么下面分别是用于伪装的域名和访问的域名
fake.baidu.com
sd.baidu.com
因此搭建一个正常的SSL网站,使用域名fake.baidu.com
,然后重点是暴露一个路径出来用于peer1的v兔连接,如someRandomPathHere
server {
...
#=====================此处为增加部分(开始)====
# 这是v1或者v3需要携带的path,越复杂越好,
location /someRandomPathHere {
proxy_redirect off;
# 注意,这是转发给v兔的
proxy_pass http://127.0.0.1:1090;
proxy_http_version 1.1;
# 升级成websocket协议
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
}
#=====================此处为增加部分(结束)====
...
}
其次是v兔的配置,其中几点需要注意
"listen": "127.0.0.1"
:监听在127.0.0.1
"port": 1090
:监听在1090端口,和nginxproxy_pass
配置一致"path": "/someRandomPathHere"
:path和nginxlocation
配置一致
{
"log": {
"loglevel": "debug"
},
"dns": {
"servers": [
"1.1.1.1",
"8.8.8.8",
"8.8.4.4"
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 1090,
"protocol": "vless",
"settings": {
"clients": [
{
// peer2的ID,peer1上的ID需要与之对应
"id": "c71c5890-56dd-4f32-bb99-3070ec2f20fa"
}
],
"decryption": "none"
},
"streamSettings": {
// 协议websocket
"network": "ws",
"wsSettings": {
// 路径和nginx的一致
"path": "/someRandomPathHere"
}
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
}
}
]
}
启动之后,访问该path,如果得到一个Bad Request说明在nginx对接v兔成功
然后配置wireguard,使用WG生成一套公私钥匙,下面命令会生成prikey
和pubkey
两个文件,然后有两个节点peer1和peer2,需要生成2对,peer2配置PrivateKey,peer1上配置peer2的PrivateKey导出来的PublicKey,peer1配置自己的PrivateKey,同时在peer2上配置peer1的PrivateKey导出来的PublicKey,注意是交叉的,看不懂先看一下上文Wireguard那篇文章。
wg genkey | tee prikey | wg pubkey > pubkey
其配置如下,有几个注意点
Address = 5.5.5.1/24
:指peer2的wireguard自用内网IPListenPort = 10000
:wireguard监听端口,很遗憾目前wireguard只能监听在0.0.0.0
即所有网络设备接口上,不能监听在127.0.0.1
上,但是默认情况下即使监听在了eth0上也需要配合iptables开放端口,所以也是安全的- iptables规则中的eth0网卡根据实际名称修改
[Interface]
Address = 5.5.5.1/24
PostUp = iptables -I FORWARD -i %i -j ACCEPT
PostUp = iptables -I FORWARD -o %i -j ACCEPT
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT
PostDown = iptables -D FORWARD -o %i -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 10000
PrivateKey = aHWomHYVWebT+lAPyZcofEfdQYXdFOXpVWRKD91OyXA=
# 配置peer1
[Peer]
PublicKey = 451o6In0DqSTyg1GE4WzrK4Z0BLuFXTrjdqjBJ/RLwc=
AllowedIPs = 5.5.5.2/32,192.168.2.0/24
peer1配置(内网IP:5.5.5.2)
peer1上的v兔配置有以下注意点
- 在入站中配置任意门协议,且远程主机(即peer2)端口为10000,和peer2中的wireguard监听端口一致,这样才会往wireguard发送数据;且协议一定要是udp,因为wireguard只支持udp协议
"address": "fakesite.com"
:指向peer2的网站,端口为443security": "tls"
:需要启用tls,因为是作为客户端去访问https站点!上面peer2中不需要启用tls是因为流量已经在nginx处解密了,到了v兔就已是明文流量。
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
//配置任意门协议
//本地监听127.0.0.1供wireguard连接
"listen": "127.0.0.1",
//本地监听端口
"port": 10000,
//任意门协议
"protocol": "dokodemo-door",
"settings": {
//发送远程主机(即peer2)的IP
//此处要特别注意,理解任意门,这里指的是往peer1上的127.0.0.1上10000端口发送的数据
//将会在peer2上的127.0.0.1的10000端口出来
//假设peer2上的wireguard使用的容器部署,假设它的IP是172.17.0.5,那么此处的IP要写172.17.0.5
//而不是127.0.0.1,这些IP都i是peer2上的,不是peer1上的,千万要注意不要混淆
//此处十分容易迷惑,一定要仔细理解上面的说明。
"address": "127.0.0.1",
//发送给远程主机(即peer2)的端口
"port": 10000,
//协议一定要是udp,因为wireguard就是udp的
"network": "udp"
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
//指向peer2的网站,端口为443
"address": "fake.baidu.com",
"port": 443,
"users": [
{
//和peer2的保持一致
"id": "c71c5890-56dd-4f32-bb99-3070ec2f20fa",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "ws",
//需要启用tls
"security": "tls",
"wsSettings": {
//和nginx的path保持一致
"path": "/someRandomPathHere"
}
}
}
]
}
此时其实已经在本地监听127.0.0.1的10000端口了,注意这是UDP端口!不是TCP端口,可以使用nc命令测试一下是否联通,在windows中使用nc命令可以先下载nc的压缩包,解压后放到设置有环境变量的路径,然后使用命令nc -vuz 127.0.0.1 10000
测试,如果输出为win11 [127.0.0.1] 10000 (?) open
并且观察v兔的日志,看到有如下类似的输出,并且同时可以观察peer2节点上面的日志是否同时有类似的输出,有说明到目前位置,连通性是没问题的。
2023/04/03 22:06:31 [Debug] [2197569131] proxy/dokodemo: processing connection from: 127.0.0.1:63696
2023/04/03 22:06:31 [Info] [2197569131] proxy/dokodemo: received request for 127.0.0.1:63696
2023/04/03 22:06:31 [Warning] [2197569131] app/dispatcher: default route for udp:172.18.0.11:10000
2023/04/03 22:06:31 127.0.0.1:63696 accepted udp:172.18.0.11:10000
2023/04/03 22:06:31 [Info] [2197569131] transport/internet/websocket: creating connection to tcp:fake.baidu.com:4432023/04/03 22:06:32 [Info] [2197569131] proxy/vless/outbound: tunneling request to udp:172.18.0.11:10000 via fake.baidu.com:443
2023/04/03 22:06:48 [Info] [2197569131] app/proxyman/inbound: connection ends > proxy/dokodemo: connection ends > context canceled
2023/04/03 22:06:48 [Info] [2197569131] app/proxyman/outbound: failed to process outbound traffic > proxy/vless/outbound: connection ends > context canceled2023/04/03 22:16:23 [Debug] [3184821071] proxy/dokodemo: processing connection from: 127.0.0.1:49206
windows的nc可以在下面的链接下载,找到nc64.exe更改名称为nc.exe放到有环境变量的路径下
最后是配置peer1上的wireguard,peer1上的wireguard配置如下,有几点需要注意
- 此时是Windows上的Wireguard配置,没有iptables等规则,这点需要注意,和Linux有些不同
Address = 5.5.5.2/24
:指peer1的wireguard自用内网IPEndpoint = 127.0.0.1:10000
:配置peer1的连接为127.0.0.1:10000
,因为此时流量已经被本地的v兔接管了,发送给peer1127.0.0.1:10000
的流量都将从v兔的任意门协议到达peer2上的127.0.0.1:10000
,peer2上已经配置了wireguard去接收该流量。AllowedIPs = 5.5.5.0/24
:整个内网流量全部转发给peer2PersistentKeepalive = 15
:每隔15s就给peer2发送心跳包
- ,保持连接(因为NAT下,peer1的公网IP和端口不定时在变化),注意不要太小,经常发探测包不是很好,也不要太大,太大容易断连,实测30比较好,60有时候会连很久
[Interface]
Address = 5.5.5.2/24
PrivateKey = oAaT5OjURGvVqs/pbMa2HAsZXpbwNQCEzW0MZBmGJ1Y=
# 配置peer2
[Peer]
PublicKey = 1yrnzlpVNhpQyyBj0oehVqCaL/06RjK/tcd3icMuZ0Q=
AllowedIPs = 5.5.5.0/24
Endpoint = 127.0.0.1:10000
PersistentKeepalive = 15
在windows中选择配置文件后启动,点击链接,如下图所示
此时开一个终端窗口,ping 5.5.5.1有返回说明隧道组网成功!5.5.5.1即为peer2的内网IP,此时已经可以在peer2上通过5.5.5.2的7860端口访问到peer1上的服务!(记得Stable Diffusion要在web-user.bat
参数中加上--listen
监听0.0.0.0
,这样就会自动监听在5.5.5.2
的7860端口上)
暴露到公网
那么怎么样暴露在公网?既然peer2本身位于公网又能直接通过内网IP 5.5.5.2访问到peer1上的服务,那么直接做一个nginx反向代理即可,前提是nginx和wireguard是共享网络的,比如在一个主机上运行这两个进程
server {
...
location / {
proxy_pass http://5.5.5.2:7860;
}
...
}
如果不共享,比如nginx是一个容器,wireguard是另外一个容器,那么只能是wireguard容器能访问到peer1的服务,可以通过ssh转发监听到wireguard容器自身的容器IP上,使用如下命令即可,前提是要先安装ssh服务
ssh -fN -L 0.0.0.0:7860:5.5.5.2:7860 root@127.0.0.1
这句话的意思是将5.5.5.2的7860端口监听在本地0.0.0.0的7860端口上,这样通过wireguard的容器IP和7860端口就能访问到,假设wireguard容器的IP为172.17.0.5
server {
...
location / {
proxy_pass http://172.17.0.5:7860;
}
...
}
最后配置我们文初的域名sd.baidu.com
即可,注意记得加上SSL,这样通过https://sd.baidu.com
即可访问到内网的Stable Diffusion服务了。
但是此时任何人都能访问,我们在给nginx加一个简单密码验证,先生成一个密码文件
yum -y install httpd-tools
htpasswd -c /etc/nginx/passwdfile username
然后在nginx配置文件中指定该密码文件
server {
...
auth_basic "Please enter username and password!";
auth_basic_user_file /etc/nginx/passwdfile username;
location / {
proxy_pass http://5.5.5.2:7860;
}
...
}
大功告成,安全是很安全的,套了一层HTTPS,在加一层Vless,高不高速就要看peer2的网络啦,测试一下,完美访问!
模型共享
前面已经讲到过模型共享的场景,此处不再赘述,主要是如何进行模型共享,其实很简单,在Windows上做一个软连接即可,比如将整个models目录(stable-diffusion-webuimodels
)挪出来放到下面目录下
D:AIlarge_modelsmodels
然后在E盘和F盘有两个stable-diffusion-webui需要引用它,那么直接在Windows上做软链接即可,使用管理员权限打开命令提示符(cmd),然后输入
mklink /D E:AIstable-diffusion-webuimodels D:AIlarge_modelsmodels
mklink /D F:AIstable-diffusion-webuimodels D:AIlarge_modelsmodels
在执行之前先删掉目录E:AIstable-diffusion-webuimodels
和目录F:AIstable-diffusion-webuimodels
,这样E盘和F盘下面的两个实例都能引用到同一个目录下的模型文件,做到模型共享
另外一个场景,假设局域网中的两台主机需要模型共享,我们都知道在局域网中Windows可以使用SMB协议共享文件,但是模型一般是很大的,不建议通过网络直接共享(如果是万兆带宽请随意),那么可以在局域网中的两个主机中分别保存一份模型文件,用于各自的本地加载,这样的需求可以通过一个文件同步工具FreeFileSync
FreeFileSync 是一个免费的、开源的文件夹比较和同步软件。 支持Windows、Linux、Mac OS X,它也适用于64位操作系统。 程序安装默认可选择一个标准的安装程序或作为一个便携式应用程序。 采用一个干净、简单、直观的界面,以同步为目标,提供了多种功能。
具体安装操作就不赘述了,如下图所示,选定好目录后点击比较和同步即可,这样只要一个目录模型发生变化,手动同步到另外一个主机,主机中的多个SD实例可以通过软连接方式进行共享,这样多个主机中的多个实例模型都是一致的
当然以上只是Windows的做法,如果是在Linux,那更好办了,同主机之间直接使用软连接共享,文件同步直接使用挂载等方式配和脚本即可做到,此处不在赘述。
赞赏 微信赞赏支付宝赞赏
暂无评论内容