nginx as reverse proxy for shiny server

Hello- I am trying to configure an nginx sever as a reverse proxy sitting in front of a (working, running, previously installed) Shiny server.

This post from Joe Cheng last year discusses some breaking changes in the development of shiny and specifically the need for correct passing of the websocket/ http upgrade process in the nginx config, and this very recent post from @ian gives specific adivce on configuring the nginx.conf file to do so.

However, I’m having trouble getting the proxy set up on port 80; ie, if I use the following configuration as recommended in the post:

http {

  map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }

  server {
    listen 80;
    
    
    location / {
      proxy_pass http://localhost:3838;
      proxy_redirect / $scheme://$http_host/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;
      proxy_buffering off;
    }
  }
}

and then navigate to the root url, I get the boilerplate default html found in /var/www/html/index.nginx-debian.html ("Welcome to nginx!”)

If however, I change the listen port above to, say, listen 65535;, and then navigate to my_url:65535, I see that nginx is successfully passing through the Shiny server app.

Finally, the nginx reverse proxy examples seem to suggest that this config (specfically proxy_pass) should work.

What is superceding the port 80 proxy pass? I obviously know little about nginx...
Any advice would be greatly appreciated.

For completeness, below is my complete config file; apologies for the verbosity.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {
    #### start orig http config ###
	##
	# Basic Settings
	##

	#sendfile on;
	#tcp_nopush on;
	#tcp_nodelay on;
	#keepalive_timeout 65;
	#types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	#include /etc/nginx/mime.types;
	#default_type application/octet-stream;

	##
	# SSL Settings
	##

	#ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	#ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

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

	##
	# Gzip Settings
	##

	#gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	#include /etc/nginx/conf.d/*.conf;
	#include /etc/nginx/sites-enabled/*;
     #### end orig http config ###
     ### BELOW BLOCK added per https://support.rstudio.com/hc/en-us/articles/213733868-Running-Shiny-Server-with-a-Proxy

  map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
      }  

    server {
      listen 80;
    
    
      location / {
        proxy_pass http://localhost:3838;
        proxy_redirect / $scheme://$http_host/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 20d;
        proxy_buffering off;
      }
    }
   ### END BLOCK
}
1 Like

Alright- an update. I'm a novice with nginx (and Shiny Server for that matter), but here's what I did, which seems to be working:

  1. instead of adding the following code block to nginx.conf (again; as recommended in this recent rstudio support post),
http {
  map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }
  server {
    listen 80;
    
    
    location / {
      proxy_pass http://localhost:3838;
      proxy_redirect / $scheme://$http_host/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;      proxy_buffering off;
    }
  }
}

it was instead necessary to add just the mapping block (ie "map $http_...") to nginx.conf, separating the location/ {...} logic to a new site configuration file, or more precisely:

nginx.conf:

.
.
.
http {
map $http_upgrade $connection_upgrade {
            default upgrade;
            ''      close;
         }
.
.

And then for the site configuration, to unlink the default site configuration file which ships with nginx:

sudo unlink /etc/nginx/sites-enabled/default

create a new configuration file, eg:

sudo vim please_proxy_my_shiny_server.conf

with this new file containing the following:

please_proxy_my_shiny_server.conf:

       server_name my_domain.com www.my_domain.com;

	location / {
                # block added from rstudio support doc
                proxy_pass http://localhost:3838;
                proxy_redirect / $scheme://$http_host/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                proxy_read_timeout 20d;
                proxy_buffering off;
	}

and then finally update the symlink:

sudo ln -s /etc/nginx/sites-available/please_proxy_my_shiny_server.conf /etc/nginx/sites-enabled/please_proxy_my_shiny_server.conf

then restart everything. On ubuntu:

sudo systemctl reload nginx

And btw, certbot seemed to be able to handle the upgrade to SSL just fine, autoediting my site config file to handle https without issue, which happened via a command sequence like this:

sudo apt-get update

sudo apt-get install python-certbot-nginx

sudo certbot --nginx -d my_domain.com -d www.my_domain.com

I'll leave this post open for a day or three until I'm sure this is indeed a solution and/or if anyone knowledgeable cares to weigh in.

3 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.