# Streamlit, docker, Nginx, ssl/https

**URL:** <https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195>\
**Category:** Deployment\
**Tags:** nginx, configuration, docker, https\
**Created:** [March 16, 2020, 4:28pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195 "2020-03-16T16:28:18Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![H\_Felix\_Wittmann](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/h_felix_wittmann/32/1331_2.png) [@H\_Felix\_Wittmann](https://discuss.streamlit.io/u/H_Felix_Wittmann)\
**Post date:** [March 16, 2020, 4:28pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/1 "2020-03-16T16:28:18Z")

</div>

Thanks for the amazing streamlit!

I am wondering if anyone has tried run streamlit in docker with https.

What I am thinking of is a combination of these:

- streamlit
- docker
- nginx
- letsencrypt via something like [GitHub - SteveLTN/https-portal: A fully automated HTTPS server powered by Nginx, Let's Encrypt and Docker.](https://github.com/SteveLTN/https-portal)

Details:  
I am using the

streamlit 0.56.0

In config config.toml I have set

enableCORS = false

It works fine with http but in every scenario that I tried with https I always had the notice

> Please wait … connecting

displayed in my browser.

And in the console

> Uncaught Error: Unsupported state transition.  
> State: PINGING\_SERVER  
> Event: CONNECTION\_TIMED\_OUT

I have tried all the combinations I can think of, I have read all the posts in the forum having to do with nginx. I cant think of any solution.

---

<div class="post-metadata">

**Author:** ![agray](https://avatars.discourse-cdn.com/v4/letter/a/bc79bd/32.png) [@agray](https://discuss.streamlit.io/u/agray)\
**Post date:** [March 17, 2020, 3:45pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/2 "2020-03-17T15:45:25Z")

</div>

I think you need some additional nginx config with proxy\_… parameters.

I haven’t used with docker but I have gotten streamlit/nginx/https working in a Windows VM using tips from [this post](https://discuss.streamlit.io/t/how-to-use-streamlit-with-nginx/378). I believe the following nginx config was what fixed the … connecting … timeout issue for me.

```
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
```

---

<div class="post-metadata">

**Author:** ![H\_Felix\_Wittmann](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/h_felix_wittmann/32/1331_2.png) [@H\_Felix\_Wittmann](https://discuss.streamlit.io/u/H_Felix_Wittmann)\
**Post date:** [March 17, 2020, 9:04pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/3 "2020-03-17T21:04:26Z")

</div>

Thank you for your reply, and for giving me some encouragement, agray!  
Despite trying it’s not working, however. I have something like you suggest in my nginx config, which I’ll post here:  
` # This file overrides default nginx HTTP settings for [my.example.com](http://my.example.com)

# Mount this file as “/var/lib/nginx-conf/my.example.com.conf.erb”

map $http\_upgrade $connection\_upgrade {  
default upgrade;  
‘’ close;  
}

```
server {
    listen 443 ssl http2;
    server_name subdomain.example.local;
    keepalive_timeout 5;

    location / {
        proxy_pass http://127.0.0.1:8501/;
    }
    location ^~ /static {
        proxy_pass http://127.0.0.1:8501/static/;
    }
    location ^~ /healthz {
        proxy_pass http://127.0.0.1:8501/healthz;
    }

    location ^~ /vendor {
        proxy_pass http://127.0.0.1:8501/vendor;
    }
    location /stream { # most important config

        proxy_pass http://127.0.0.1:8501/stream;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 86400;
    }
 }`

```

Also I have that on starting up streamlit emits:  
`subdomain_1 | You can now view your Streamlit app in your browser. subdomain_1 | subdomain_1 | Network URL: http://172.21.0.2:8501 subdomain_1 | External URL: http://79.247.21.93:8501 `  
So I switched all the 172.0.0.1 to 172.21.0.2 , but unfortunately it did not work either …

---

<div class="post-metadata">

**Author:** ![H\_Felix\_Wittmann](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/h_felix_wittmann/32/1331_2.png) [@H\_Felix\_Wittmann](https://discuss.streamlit.io/u/H_Felix_Wittmann)\
**Post date:** [March 17, 2020, 9:06pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/4 "2020-03-17T21:06:46Z")

</div>

I forgot to say I am getting lots of these:

WebSocket connection to ‘’ failed: WebSocket is closed before the connection is established.

---

<div class="post-metadata">

**Author:** ![agray](https://avatars.discourse-cdn.com/v4/letter/a/bc79bd/32.png) [@agray](https://discuss.streamlit.io/u/agray)\
**Post date:** [March 19, 2020, 5:57am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/5 "2020-03-19T05:57:15Z")

</div>

> [@H\_Felix\_Wittmann](#):
>
> # most important config

My nginx server stanza looks like this. Maybe try putting the proxy\_set… params outside of your location {…} stanzas.

```
server {
  listen 443 ssl;
  server_name localhost;
  
  ssl_certificate C:/.../nginx/conf/certificate.pem;
  ssl_certificate_key C:/.../nginx/conf/key.pem;
  
  proxy_http_version 1.1; 
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $host;

  # streamlit specific: 
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_read_timeout 86400;
  
  location / {
    auth_basic "Access Restricted";
    auth_basic_user_file C:/.../nginx/conf/.htpasswd;
    proxy_pass http://127.0.0.1:8501;
  }
}

```

---

<div class="post-metadata">

**Author:** ![H\_Felix\_Wittmann](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/h_felix_wittmann/32/1331_2.png) [@H\_Felix\_Wittmann](https://discuss.streamlit.io/u/H_Felix_Wittmann)\
**Post date:** [March 19, 2020, 8:23am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/6 "2020-03-19T08:23:40Z")

</div>

I have now been able to solve it. I could do it using a specific option of the docker based solution [https://github.com/SteveLTN/https-portal](https://github.com/SteveLTN/https-portal). In particular it allows to [override nginx configuration files](https://github.com/SteveLTN/https-portal#override-nginx-configuration-files)

The main point is it uses erb files, which allow variables, such as \<%= domain.name %\> which I had to use instead of [http://127.0.0.1](http://127.0.0.1)

I had to modify the one for ssl.  
Here it is:

There were some specifics that had to do with the

```auto
# based on https://github.com/SteveLTN/https-portal/blob/master/examples/custom_config/nginx-conf/example.com.ssl.conf.erb
# This file overrides default nginx HTTPS settings for my.example.com
# Mount this file as "/var/lib/nginx-conf/my.example.com.ssl.conf.erb"

server {
    listen 443 ssl http2;

    # domain.name will be "my.example.com", you can also hard-code it.
    server_name <%= domain.name %>;

    ssl on;
    ssl_certificate <%= domain.chained_cert_path %>;
    ssl_certificate_key <%= domain.key_path %>;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:50m;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_prefer_server_ciphers on;

    ssl_dhparam <%= dhparam_path %>;

    location / {
        set $backend <%= domain.upstream %>;
        proxy_pass $backend;
    }
    location /stream {
        proxy_pass <%= domain.upstream %>/stream;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 2h;
    }
}

```

Unfortunately I have now hit the letsencrypt limits, but this should resolve itself in a couple of days.

@agray Thank you for your help and encouragement

---

<div class="post-metadata">

**Author:** ![deweil](https://avatars.discourse-cdn.com/v4/letter/d/ee59a6/32.png) [@deweil](https://discuss.streamlit.io/u/deweil)\
**Post date:** [October 21, 2020, 9:37am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/7 "2020-10-21T09:37:14Z")

</div>

@H_Felix_Wittmann Thanks for sharing the config!  
I updated the config since `ssl on;` isn’t allowed anymore (removed it)  
There is also the config included to enable basic auth:

```
server {
    listen 443 ssl http2;
    # domain.name will be "my.example.com", you can also hard-code it.
    server_name <%= domain.name %>;
    ssl_certificate <%= domain.chained_cert_path %>;
    ssl_certificate_key <%= domain.key_path %>;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:50m;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_prefer_server_ciphers on;
    ssl_dhparam <%= dhparam_path %>;

    <% if domain.basic_auth_enabled? %>
    auth_basic "Password";
    auth_basic_user_file <%= domain.htaccess_path %>;
    <% end %>

    location / {
        set $backend <%= domain.upstream %>;
        proxy_pass $backend;
    }

    location /stream {
        proxy_pass <%= domain.upstream %>/stream;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 2h;
    }
}
```

---

<div class="post-metadata">

**Author:** ![Khd\_Jbn](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/khd_jbn/32/5298_2.png) [@Khd\_Jbn](https://discuss.streamlit.io/u/Khd_Jbn)\
**Post date:** [March 30, 2021, 4:58pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/8 "2021-03-30T16:58:23Z")

</div>

I ran successfully streamlit in docker but even though runOnsave is activated in streamlit conf, my app does not update.

Here is my nginx config :

server {

```
listen 80 default_server;

location /test/ {
    auth_request /auth;
    proxy_pass http://localhost:8501/;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;
}

location ^~ /test/static {
    proxy_pass http://localhost:{{metadata['port']}}/static/;
}

location ^~ /test/healthz/ {
    proxy_pass http://localhost:{{metadata['port']}}/healthz/;
}

location ^~ /test/vendor/ {
    proxy_pass http://localhost:{{metadata['port']}}/vendor/;
}

location = /auth {
    proxy_pass http://localhost:8000/;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Real-Ip $remote_addr;
    proxy_set_header X-Authorization $http_authorization;
}

```

}

---

<div class="post-metadata">

**Author:** ![DPunited](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/dpunited/32/11705_2.png) [@DPunited](https://discuss.streamlit.io/u/DPunited)\
**Post date:** [November 14, 2021, 3:40pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/9 "2021-11-14T15:40:39Z")

</div>

Hello everyone…  
Can any one please provide a step-by-step methodology for https:// custom-domain. com to access x.x.x.x:8501 ?  
It seems most of us are struggling to get things going.

Thank You…

---

<div class="post-metadata">

**Author:** ![fccoelho](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/fccoelho/32/12571_2.png) [@fccoelho](https://discuss.streamlit.io/u/fccoelho)\
**Post date:** [December 29, 2021, 5:04pm UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/10 "2021-12-29T17:04:17Z")

</div>

This solution does not work for me. Keep being redirected to 404.

I have a main site running on the `/` configured by certbot.

My streamlit sits on another location:

```auto
server {

    location /covidch/ {
        auth_basic "Restricted Area";
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_pass http://127.0.0.1:8502/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
# proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-Proto $scheme;
    }
# error_page 404 /404.html;
# error_page 500 502 503 504 /50x.html;

# location = /50x.html {
# root /usr/share/nginx/html;
# }
}

```

---

<div class="post-metadata">

**Author:** ![dbkt](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/dbkt/32/23996_2.png) [@dbkt](https://discuss.streamlit.io/u/dbkt)\
**Post date:** [March 12, 2023, 12:04am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/11 "2023-03-12T00:04:05Z")

</div>

I was facing the same issue while deploying my streamlitapp via my AWS EC2 instance:  
[http://MyIpAdress:8501](http://MyIpAdress:8501) was working without any errors. However, once I tried to bring my ssl certificates within my nginx.conf file in order to be able to run https instead of http, [https://MyDomainName](https://MyDomainName) didn’t work. Instead, it showed me “Please Wait…” and somehow I could see that there was an issue with the WebSocket. ([http://MyIpAdress:8501](http://MyIpAdress:8501) still worked tho)

Changing  
_proxy\_set\_header Connection “upgrade”;_  
to  
_proxy\_set\_header Connection $connection\_upgrade;_

fixed it for me somehow!

If this doesn’t fix it on your end, just let me know and I can share the entire nginx.conf file.

Hope this helps!

---

<div class="post-metadata">

**Author:** ![Elshan\_Gadimov](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/elshan_gadimov/32/28957_2.png) [@Elshan\_Gadimov](https://discuss.streamlit.io/u/Elshan_Gadimov)\
**Post date:** [July 13, 2023, 8:22am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/12 "2023-07-13T08:22:37Z")

</div>

Could you please share the entire nginx.conf file, Thanks

---

<div class="post-metadata">

**Author:** ![brablc](https://sea2.discourse-cdn.com/streamlit/user_avatar/discuss.streamlit.io/brablc/32/31999_2.png) [@brablc](https://discuss.streamlit.io/u/brablc)\
**Post date:** [September 12, 2023, 11:58am UTC](https://discuss.streamlit.io/t/streamlit-docker-nginx-ssl-https/2195/13 "2023-09-12T11:58:39Z")

</div>

Solution for running in docker on Plesk control panel.

1. In docker container configuration set manual port mapping 8501-\>8501.
2. For your domain do not use Docker Proxy Rules and use Additional nginx directives:

```auto
location ~ ^/.* {
	proxy_pass http://0.0.0.0:8501;
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	# streamlit specific BEGIN
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "upgrade";
	# streamlit specific END
	# streamlit optional END
	proxy_buffering off;
	proxy_read_timeout 86400;
	# streamlit optional END
}

```

Only marked parts have been modified the rest is the standard code, that would Plesk generate with Docker Proxy Rules.

No need to disable CORS.
