I recently began receiving warnings on the Milestone Mobile app stating that support for self-signed SSL certificates would soon be ending. I decided that the easiest solution would be to reverse proxy Milestone using my existing NGINX server and a free Let's Encrypt SSL certificate.

I am not going to cover the process of obtaining a Let's Encrypt certificate – there are several tutorials out there that explain it.

Initially, I was able to proxy Milestone quite easily. However, I noticed that the camera feeds were not being streamed to the clients. After some research, I learned that this was due to the WebSockets connections not being proxied. I needed to add some extra parameters to the configuration to get WebSockets connections proxied. In the end, I came up with the following server block which worked great.

EDIT 8/11/19: Since upgrading my Milestone servers to 2019 R2, I am unable to figure out a working configuration for NGINX to correctly proxy WebSockets. Discussion in comments.

server {
        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/live/<FQDN>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/<FQDN>/privkey.pem;

        server_name <FQDN>;

        gzip off;

        location / {
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_pass https://<MILESTONE IP>:8082;
        }
}