说在前面的话......

我希望能在公网直接访问我的Stable Diffusion WebUI,虽然说可以直接通过端口隐射或者内网穿透的方式引出来,但是由于WebUI本身是不带身份验证的,万一被某些无聊的人乱搞就不好了。
于是,我就想到用Nginx做反向代理,并且加入基本身份验证。也就是你打开网站的时候浏览器会弹出一个窗口要你填写身份信息进行认证。这样做的话,相对而言比较省事,不需要去增加功能和代码。

所需软件/工具

  • Stable Diffusion WebUI
  • FRP内网穿透工具
  • Nginx
  • HAproxy(如果有多个服务需要同时访问的话)

Stable Diffusion配置允许外部访问

在Stable Diffusion的目录找到webui-user.sh文件,取消注释export COMMANDLINE_ARGS="",加上--listen
例如:

export COMMANDLINE_ARGS="--xformers --enable-insecure-extension-access --listen"

然后按照常规方式启动Stable Diffusion:

./webui.sh

配置FRP内网穿透

下载FRP后,解压,frps是服务端,配置文件为frps.tomlfrpc是客户端,配置文件为frpc.toml
服务端配置文件如下:

bindPort = 7000
auth.token = "your_passwd"

bindPort是服务器监听端口。
auth.token是设置的连接密码。

客户端配置文件如下:

serverAddr = "172.16.0.1"
serverPort = 7000
auth.token = "your_passwd"

[[proxies]]
name = "Stable_Diffusion"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7860
remotePort = 7860

serverAddr是服务器的IP地址。
serverPort是服务器设置的端口,需要和服务器保持一致。
auth.token是自定义的密码,需要和服务器保持一致。
localIP是要访问服务的本地IP。
localPort是本地服务的端口。
remotePort是把本地服务暴露出去在外面访问的端口。

所有相关文件位于同一目录,设置好后,服务端运行frps:

./frps -c ./frps.toml

客户端运行frpc:

./frpc -c ./frpc.toml

注意,这一步可以防火墙放行相关端口看看是否成功,但是弄完之后一定要关掉这个端口!

配置Nginx反向代理

配置基础身份验证

为了添加基础身份验证,需要生成一个密码文件。使用htpasswd工具来创建这个文件。如果没有安装htpasswd,可以通过安装 apache2-utils包来获得:

apt install apache2-utils

然后,创建一个密码文件,并添加一个用户:

sudo htpasswd -c /etc/nginx/.htpasswd user

配置Web服务器配置文件

Web服务器配置文件内容如下:

server {
    server_name yourdomain.example.com;
    listen 10086 ssl;
    listen [::]:10086 ssl;
    ssl_certificate     /path/to/your/cert.pem;
    ssl_certificate_key /path/to/your/certkey.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    gzip            on;
    gzip_vary       on;
    gzip_proxied    any;
    gzip_comp_level 6;
    gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

    auth_basic "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;


    proxy_http_version                 1.1;
    proxy_cache_bypass                 $http_upgrade;
    proxy_set_header Upgrade           $http_upgrade;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header Connection           "upgrade";
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Port  $server_port;
    proxy_set_header Host $host;

    client_max_body_size 20m;

    proxy_connect_timeout              60s;
    proxy_send_timeout                 60s;
    proxy_read_timeout                 60s;
    location / {
        proxy_pass http://127.0.0.1:7860/;
    }

    location ~ /\.(?!well-known) {
        deny all;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log    off;
    }

    location = /robots.txt {
        log_not_found off;
        access_log    off;
    }

}

以上是模板,要做以下修改:
yourdomain.example.com填你自己的域名。
/path/to/your/cert.pem填你服务器证书的位置。
/path/to/your/certkey.key填你服务器证书私钥路径。
保存为你自己想要的名称.conf并且放到/etc/nginx/http.d/,例如/etc/nginx/http.d/neko.conf

重启Nginx

systemctl restart nginx

如果你按照我这样配置完成后,理论上访问https://yourdomain.example.com:10086并且输入用户和密码验证身份后,即可看到你的Stable Diffusion WebUI了。
哦对了,别忘了添加域名的DNS解析记录。

配置HAproxy实现端口复用(可选)

如果你的服务器像我一样运行了多个不同的服务,并且你有域名的话,就可以用这个方法实现端口复用。也就是都走443端口进行访问。
这里我贴出来我的HAproxy配置文件:

#---------------------------------------------------------------------
# 全局设定部分
#---------------------------------------------------------------------
global
 
defaults
    log                     global
    option                  dontlognull
    option http-server-close
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

#---------------------------------------------------------------------
# 定义DNS解析器
#---------------------------------------------------------------------
resolvers dns1
    nameserver internal-dns 1.1.1.1:53
    resolve_retries 3
    timeout resolve 10s
    timeout retry 10s
    hold other 30s
    hold refused 30s
    hold nx 30s
    hold timeout 30s
    hold valid 10s
    hold obsolete 30s

#---------------------------------------------------------------------
# 接管HTTP流量实现302跳转HTTPS
#---------------------------------------------------------------------
frontend http
    bind :80 
#accept-proxy
    mode http

    redirect scheme https code 302 if { hdr(Host) -i www.nekopara.uk } !{ ssl_fc }
    redirect scheme https code 302 if { hdr(Host) -i sd.nekopara.uk } !{ ssl_fc }
 
#---------------------------------------------------------------------
# 通过SNI Proxy对HTTPS流量实现四层转发
#---------------------------------------------------------------------
frontend https_proxy
    mode tcp
    bind :443
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }

    acl is_www.nekopara.uk req_ssl_sni -i www.nekopara.uk
    use_backend www.nekopara.uk if is_www.nekopara.uk

    acl is_sd.nekopara.uk req_ssl_sni -i sd.nekopara.uk
    use_backend sd.nekopara.uk if is_sd.nekopara.uk


backend www.nekopara.uk
    mode tcp
    balance roundrobin
    option tcp-check
    server  ddns-1 org.nekopara.uk:3939 resolvers dns1 resolve-prefer ipv4 check send-proxy
    server backup-server 127.0.0.1:8443 backup



backend sd.nekopara.uk
    mode tcp
    balance roundrobin
    option tcp-check  
    server backup-server 127.0.0.1:10086

其中,www.nekopara.uk是我博客的主域名,而sd.nekopara.uk则是我自己要运行的Stable Diffusion WebUI服务。
这样一设置,我就可以让我的好几个不同的Web服务一起在443端口访问了,也就是不需要加端口了。
要注意一点,这里的端口号是要填写Nginx反代出来的端口号,也就是10086,如果填FRP穿透出来的端口号,两个结果,要么无法访问,要么所有人都可以访问。一定要注意!

最终效果

访问时会弹出身份认证:
20241107_150311.png
不认证不给访问:
20241107_150332.png
认证成功后进入界面:
20241107_150552.png
Nice!