RStudio & Shiny Servers with NGINX & SSL

I fairly often set up servers to host both Shiny and RStudio servers. This is my recipe.

Once you’ve installed RStudio Server, your next concern should be about accessing it securely. To do this you’ll need to setup SSL.

Setup

Install NGINX.

sudo apt install nginx-full

You’ll also need to install Shiny and RStudio servers, possibly following these instructions.

Basic NGINX Configuration

Edit the contents of /etc/nginx/sites-available/default as follows:

server {
    listen 80;
    server_name _;

    location / {
        proxy_pass          http://127.0.0.1:8787;
        proxy_read_timeout  900;
    }
}

The above configuration works for RStudio Server (port 8787). For Shiny server, simply replace 8787 with 3838.

The proxy_read_timeout setting is optional, but it will stop you from getting 504 errors on long running R statements.

A slightly more sophisticated configuration might look like this:

server {
    listen 80;

    server_name www.example.com;

    location / {
        proxy_pass          http://127.0.0.1:8787;
        proxy_read_timeout  900;
        proxy_set_header    Host $host;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Use the actual DNS name of the server rather than www.example.com. If the server doesn’t have an allocated DNS name then you can simply use _ instead.

Now restart NGINX.

# Two ways to restart the NGINX service.
sudo service nginx restart
sudo systemctl restart nginx

You should be able to access the server via port 80. If you’re running this on localhost, then head to http://127.0.0.1/. 📢 If you’re running the service on AWS then you’ll need to apply a security group which allows inbound connections on port 80 (HTTP).

The final hurdle is to enable HTTPS by installing an SSL certificate.

Services on Sub-Directories

What about serving Shiny and RStudio on separate sub-directories? This requires a little more configuration.

server {
    listen 80;
    server_name www.example.com;

    location /shiny {
        rewrite         /shiny/(.*) /$1 break;
        rewrite         ^/shiny$ /shiny/ permanent;
        proxy_redirect  / /shiny/;
        proxy_pass         http://127.0.0.1:3838;
        proxy_buffering    off;
        proxy_set_header   Host $host;
        proxy_pass_header  Server;
    }

    rewrite ^/rstudio$ $scheme://$http_host/rstudio/ permanent;

    location /rstudio/ {
        rewrite ^/rstudio/(.*)$ /$1 break;
        proxy_pass http://localhost:8787;
        proxy_redirect http://localhost:8787/ $scheme://$http_host/rstudio/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_read_timeout 20d;
    }
}

Add an SSL Certificate

Install Certbot.

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx

Replace the _ in the NGINX configuration file with the DNS name you want to assign to the machine. This is mandatory: if there’s no DNS name then you can’t get a certificate.

Run Certbot.

sudo certbot --nginx

After install the default configuration should look something like this:

server {
    server_name www.example.com;

    location / {
        proxy_pass http://127.0.0.1:8787;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

}
server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    }

    listen 80;

    server_name www.example.com;
    return 404;
}

Restart NGINX and you should be 🚀.

📢 If you’re running the service on AWS then you’ll need to apply a security group which allows inbound connections on port 443 (HTTPS).