Repository: AUTOMATIC1111/stable-diffusion-webui

Issue:
https (ssl) support
**Is your feature request related to a problem? Please describe.**
ability to start it in https (ssl crypted) mode, specifying the cert+key+servername on the cli.

**Describe the solution you'd like**
gradio already implemented it, just pass the ssl_keyfile and ssl_certfile parameters to launch():
https://github.com/gradio-app/gradio/issues/563

and it's recommended (required?) to use real hostname instead of 0.0.0.0, so --listen should have a parameter to specify name/ip address.

i've modified your webui.py to test and it works fine:
    demo.launch(
        share=cmd_opts.share,
        server_name="xxx.yyy.hu",
        server_port=cmd_opts.port,
        debug=cmd_opts.gradio_debug,
        auth=[tuple(cred.split(':')) for cred in cmd_opts.gradio_auth.strip('"').split(',')] if cmd_opts.gradio_auth else None,
        inbrowser=cmd_opts.autolaunch,
        ssl_keyfile="/etc/ssl/xxx.yyy.key",
        ssl_certfile="/etc/ssl/xxx.yyy.pem"
    )


**Describe alternatives you've considered**
first i've setup an apache reverse proxy (proxypass to http://127.0.0.1:7860) but it timeouts after a few minutes, so if the render took several minutes then you'll never receive it and the whole ui becames unresponsible:

[Fri Sep 23 21:03:51.138645 2022] [proxy_http:error] [pid 3946:tid 139649922103040] (70007)The timeout specified has expired: [client 37.191.45.201:57969] AH01102: error reading status line from remote server 127.0.0.1:7860
[Fri Sep 23 21:03:51.138669 2022] [proxy:error] [pid 3946:tid 139649922103040] [client 37.191.45.201:57969] AH00898: Error reading from remote server returned by /api/predict/

**Additional context**
the whole https thing is REQUIRED for browser notifications to work, because (at least in firefox) it's not allowed with http urls.



Discussion:
> first i've setup an apache reverse proxy (proxypass to http://127.0.0.1:7860/) but it timeouts after a few minutes, so if the render took several minutes then you'll never receive it and the whole ui becames unresponsible:

Increase the timeout.
I use mine exclusively through nginx with ssl and it's super snappy.  
@MrKuenning that sounds like what I want to do. Could you share any setup instructions?  
I have a dynamic DNS to my firewall.
I have nginx proxy manager running on a docker vm.
I run sd with a custom port.

Nginx manager has let's encrypt built in.
I then set a proxy of ai.domain.com to fwd to sd.
I also setup a remote script to start and stop sd.

Now I can go to ai.domain.com from my local machine or my phone from anywhere.
Very nice! Thanks!
It'll be nice if there was also an easy self-signed certificate option. Some of us just want to use notifications but that functionality is gated behind HTTPS. 

https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/1013

Resolving patch:
diff --git a/modules/shared.py b/modules/shared.py
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -86,6 +86,9 @@
 parser.add_argument("--ui-debug-mode", action='store_true', help="Don't load model to quickly launch UI")
 parser.add_argument("--device-id", type=str, help="Select the default CUDA device to use (export CUDA_VISIBLE_DEVICES=0,1,etc might be needed before)", default=None)
 parser.add_argument("--administrator", action='store_true', help="Administrator rights", default=False)
+parser.add_argument("--tls-keyfile", type=str, help="Partially enables TLS, requires --tls-certfile to fully function", default=None)
+parser.add_argument("--tls-certfile", type=str, help="Partially enables TLS, requires --tls-keyfile to fully function", default=None)
+parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None)
 
 cmd_opts = parser.parse_args()
 restricted_opts = {
diff --git a/webui.py b/webui.py
--- a/webui.py
+++ b/webui.py
@@ -34,7 +34,7 @@
 import modules.hypernetworks.hypernetwork
 
 queue_lock = threading.Lock()
-
+server_name = "0.0.0.0" if cmd_opts.listen else cmd_opts.server_name
 
 def wrap_queued_call(func):
     def f(*args, **kwargs):
@@ -85,6 +85,20 @@ def initialize():
     shared.opts.onchange("sd_hypernetwork", wrap_queued_call(lambda: modules.hypernetworks.hypernetwork.load_hypernetwork(shared.opts.sd_hypernetwork)))
     shared.opts.onchange("sd_hypernetwork_strength", modules.hypernetworks.hypernetwork.apply_strength)
 
+    if cmd_opts.tls_keyfile is not None and cmd_opts.tls_keyfile is not None:
+
+        try:
+            if not os.path.exists(cmd_opts.tls_keyfile):
+                print("Invalid path to TLS keyfile given")
+            if not os.path.exists(cmd_opts.tls_certfile):
+                print(f"Invalid path to TLS certfile: '{cmd_opts.tls_certfile}'")
+        except TypeError:
+            cmd_opts.tls_keyfile = cmd_opts.tls_certfile = None
+            print("TLS setup invalid, running webui without TLS")
+        else:
+            print("Running with TLS")
+
+
     # make the program just exit at ctrl+c without waiting for anything
     def sigint_handler(sig, frame):
         print(f'Interrupted with signal {sig} in {frame}')
@@ -131,8 +145,10 @@ def webui():
 
         app, local_url, share_url = demo.launch(
             share=cmd_opts.share,
-            server_name="0.0.0.0" if cmd_opts.listen else None,
+            server_name=server_name,
             server_port=cmd_opts.port,
+            ssl_keyfile=cmd_opts.tls_keyfile,
+            ssl_certfile=cmd_opts.tls_certfile,
             debug=cmd_opts.gradio_debug,
             auth=[tuple(cred.split(':')) for cred in cmd_opts.gradio_auth.strip('"').split(',')] if cmd_opts.gradio_auth else None,
             inbrowser=cmd_opts.autolaunch,


Test patch: