Add Authentication to Shiny Server with Nginx

[This article was first published on R Tricks – Data Science Riot!, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Shiny Server is a great tool, but I’ve always found it odd that there was no built-in password authentication. Sure, the Shiny Pro edition has SSL auth., but even for open source projects, I’m not really crazy about just anyone hitting my server whenever they want.

To solve this little problem, I whipped up two work-arounds. One solution uses an Nginx server with basic authentication and the second uses Nginx with SSL auth. The examples below are based on a fresh install of Ubuntu 14.04. A “quick start” version of the exact environment I used can be had here.

Deploy Shiny Server with Nginx Basic Authorization

The trick is to have Shiny only serve to the localhost and have Nginx listen to localhost and only serve to users with a password. This is fairly straight forward and involves editing the Nginx default.conf as well as the Shiny Server conf.

First, make sure you’ve got Nginx installed.

sudo apt-get install nginx

Also, make sure you’ve got Apache2-utils, you’ll use this to store the usernames and passwords.

sudo apt-get install apache2-utils

Before you go on, shut down both Shiny and Nginx

sudo service nginx stop
sudo stop shiny-server

Next, you’ll need to edit the Nginx default.conf file.

sudo nano /etc/nginx/sites-available/default

Copy and paste the following into your default.conf

server {
    listen 80; 
    
    location / {
      proxy_pass http://127.0.0.1:3838/;
      proxy_redirect http://127.0.0.1:3838/ $scheme://$host/;
      auth_basic "Username and Password are required"; 
      auth_basic_user_file /etc/nginx/.htpasswd;
    }
  }

Once that’s done, you’ll need to edit Shiny Server’s conf file so it only serves to loaclhost. Otherwise users would be able to creep around your authentication by going to port 3838.

sudo nano /etc/shiny-server/shiny-server.conf

Copy and paste the below to your shiny-server.conf.

server{
    listen 3838 127.0.0.1;
    
    location / {
    site_dir /srv/shiny-server;
    log_dir /var/log/shiny-server;
    directory_index on;
    }
}

Now it’s time to create some usernames and passwords.

cd /etc/nginx
sudo htpasswd -c /etc/nginx/.htpasswd exampleuser

Restart Nginx and Shiny

sudo service nginx start
sudo start shiny-server

Ta-da, now you’ve got a password protected Shiny Server! Note, Shiny is now served by port 80 instead of port 3838!
loginnginx

Deploy Shiny Server with Nginx SSL Authorization

This is basically the same as above, but we’re going to direct the reverse-proxy to port 443 with SSL instead of port 80. The only “gotcha” is we’ll need a signed SSL certificate to view the page. There’s two ways to go about this: use a self-signed certificate with IP addresses or to use a trusted certificate with a domain name. Since this is just testing, I’ll use the self-signed method. If you need a trusted certificate, there’s a good tutorial on using letsencrypt to get a free trusted cert.

First we have to create a self-signed certificate. This is going to live in the nginx folder for ease of use.

cd /etc/nginx
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/server.key -out /etc/nginx/server.crt

Now use the same nginx default.conf method as above but add lines to read the SSL cert.

# Redirect all traffic from port 80 to SSL port
server {
    listen 80;
    return 301 https://$host$request_uri;
}
# Set reverse proxy to port 443
server {
    listen 443 ssl;
        ssl on;
        ssl_certificate /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;
    
    location / {    
        proxy_pass http://127.0.0.1:3838;
        proxy_redirect http://127.0.0.1:3838/ https://$host/;
        auth_basic "Username and Password are required"; 
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

The changes to shiny-server.conf are the same as above.

server{
    listen 3838 127.0.0.1;
    
    location / {
    site_dir /srv/shiny-server;
    log_dir /var/log/shiny-server;
    directory_index on;
    }
}

If everything is working correctly, you should be staring at an ugly error message in your browser telling you that this is an “unsafe website.” This is due to the self-signed certificate. Just ignore that, add an exception and you should be confronted with a login box.
sslauthnginx

This is purely for testing purposes. This hasn’t been fully tested so don’t go putting it into production. If you really want to take things a step further, I would look into getting a trusted cert with letsencrypt, so you won’t have to deal with the ugly error page.

One more thing, the above is a VERY basic Nginx setup, the full-monty for the Nginx conf file would probably look something like this:

# Redirect all traffic from port 80 to SSL port
server {
    listen 80;
    return 301 https://$host$request_uri;
}
# Set reverse proxy to port 443
server {
    listen 443 ssl;
        ssl on;
        ssl_certificate /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    
    location / { 
        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_pass http://127.0.0.1:3838;
        proxy_redirect http://127.0.0.1:3838/ https://$host/;
        auth_basic "Username and Password are required"; 
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

 

To leave a comment for the author, please follow the link and comment on their blog: R Tricks – Data Science Riot!.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)