Handling SSL certificates

How does one handle integrating an SSL certificate with a Reflex app hosted in a docker container? Are there Reflex config changes to be made or is it all handled by the image or Docker?

I’ve added this into my dockerfile, but it seems to be ineffective. I’m using python:3.11 as base.
‘’’
ADD /certs/generic_cert.crt /etc/ssl/certs/generic_cert.crt
RUN update-ca-certificates
‘’’

Does anyone know how to configure a Reflex app to use a SSL certificate? I’ve been struggling with this for a week now going through nginx proxy manager configs, dockerfiles, and trying to search through the Reflex github. The problem I’m running into is the web app frontend will show up when I turn SSL on in the proxy manager, but the backend/server/websocket times out or can’t be reached. I’ve used the Self-Hosting with Docker article on the Reflex blog as the reference for nginx config although I’m not using Docker Compose, it’s just Docker engine and a dockerfile to build the image.

How are you configuring your setup currently here is another example from our GitHub on someone has configured it Uploads not working when using nginx reverse proxy · Issue #973 · reflex-dev/reflex · GitHub

Hey Alek,
Thanks for the suggestion. I ended up using the single port docker example to pass everything through one place and let it all be handled internally in the container. I couldn’t get the two port without Caddy to work with nginx.

@idrix This is how I set up my nginx conf file.

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

limit_req_zone $binary_remote_addr zone=frontend_limit:10m rate=50r/s;
limit_req_zone $binary_remote_addr zone=backend_limit:10m rate=100r/s;

server {
    server_name ${DOMAIN};
    listen 80;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    server_name ${DOMAIN};
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/${CERTIFICATE_PATH};
    ssl_certificate_key /etc/letsencrypt/${CERTIFICATE_KEY_PATH};
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # reflex static frontend
    location / {
        limit_req zone=frontend_limit burst=300 nodelay;
        root /app/frontend_static;
        try_files $uri $uri/index.html /index.html;
    }

    # reflex websocket
    location ~ /_event {
        limit_req zone=backend_limit burst=300 nodelay;
        proxy_pass http://backend:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }

    # reflex backend
    location ~ ^/(admin|ping|upload) {
        limit_req zone=backend_limit burst=500 nodelay;
        proxy_pass http://backend:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }
}

This is in conjunction with a compose.yaml that runs the reflex app in the backend service. Env vars are substituted on startup of the nginx container.

The key is the location block for the /_event to enable the backend to work.

SSL certificates are mounted in the compose.yaml file, and automatically renewed by a separate certbot container with a bit of trickery in order for the nginx server to restart automatically when the certificates are renewed.

I use the production docker setup: reflex/docker-example/production-compose at main · reflex-dev/reflex · GitHub

with this setup we don’t use nginx, but the much easier to configure Caddy