Streamlit, docker, Nginx, ssl/https

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:

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.

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. 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;

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

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 …

I forgot to say I am getting lots of these:

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

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;
  }
}

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. In particular it allows to 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

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

There were some specifics that had to do with the

# 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