Guide: Securing URSYS - dsriseah/ursys GitHub Wiki

The URSYS Build Framework utilizes both Express webservers and WebSocket servers running on localhost, and do not support https. This is sufficient for developing on your own machine, but if you want to deploy to a remote server you want at least secure http (https). This guide provides details on how to achieve that.

Configuring NGINX as WebSocket and WebServer Proxy

While our Node Express code uses plain http, Nginx can both handle https and redirect websocket connections.

  1. Follow Guide: Ubuntu Server Administration to set up nginx with let's encrypt
  2. Add the following location to the nginx https server block, which in this example will redirect https://ursys.dsri.xyz/app/ to the express app
server_name ursys.dsri.xyz ;

location /app/ {
  proxy_pass http://127.0.0.1:8080/;
  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;
  proxy_set_header X-Forwarded-Host $server_name;
  proxy_read_timeout 7200;  # 2 hours
}
  1. Restart nginx by first testing the config with nginx -t then systemctl nginx restart

Modifying the Express App for the Proxy

Make sure your Express app's listen() is using the address http://127.0.0.1:8080 to force IPV4, then browser to the route (here it's set to app) on the Nginx server.

This proxy is forwarding the url to 127.0.0.1:8080 without additional route information. To support that, you will need to rewrite your nginx location block and express server accordingly to handle routes and route parameters.

Appendix: Complete Config

This particular location block redirects a single path like http://ursys.dsri.xyz/app/ to the Express app running on 127.0.0.1:8080, handling websocket traffic as well. The http connection is changed to https behind the scenes through the nginx configuration.

Here's my complete nginx config for ursys.dsri.xyz as of the time of this writing. The top block is for https, and the second for handling http redirects to https. Note that Let's Encrypt manages the security certificates through its certbot.

server {

    root /var/www/ursys_dsri_xyz/html;
    index index.html index.htm index.nginx-debian.html;

    server_name ursys.dsri.xyz ;

    location /app/ {
      proxy_pass http://127.0.0.1:8080/;
      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;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_read_timeout 7200;  # 2 hours
    }

    location / {
      try_files $uri $uri/ =404;
    }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dsri.xyz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dsri.xyz/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {

    if ($host ~ ^[^.]+\.dsri\.xyz$) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = ursys.dsri.xyz) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    listen [::]:80;

    server_name ursys.dsri.xyz ;
    return 404; # managed by Certbot

}

Note

The proxy settings specific for websockets are proxy_http_version, "Upgrade", and "Connection". WebSocket requires HTTP/1.1. The Upgrade and Connection headers are passed-through to the WebSocket Server library in the Express application so it can configure itself appropriately.

⚠️ **GitHub.com Fallback** ⚠️