RShiny Server is Amazing

RShiny Server is Amazing

RShiny Server hosts RShiny applications: An example application (code) adapted from the superzip-example from RShiny's Demos.

Struggling to find the best way to present or share graphical representations of data? RShiny is there for you! There are tons of resources and a fantastic community of developers. If you have your own cloud service (Digital Ocean, AWS, Google Cloud, etc.), then implementation of RShiny is free and relatively straight forward. The following guide are the steps that I took to setup my own RShiny server with HTTPS setup through Nginx and Letsencrypt on a Digital Ocean Droplet.

If you're familiar with Docker, there is an excellent RShiny container available from rocker/shiny. On my home server, my connection to the internet is moderated by pfSense (router/firewall), so setting up HTTPS is a bit different than what I did in this tutorial.  This tutorial was mostly my own way of making sense of what goes on behind the scenes with Nginx and Letsencrypt - It's all still a bit murky in my brain, but becoming clearer every day.

Stuff in [brackets] are things you have to replace with your own information. For example, if I were prompted with something like [yourwebsite.com], I would replace it with spatialmsk.com.

Setup Shiny on Ubuntu 18.04

Initial Server Setup with Ubuntu 18.04

When you're creating a fresh Linux-based virtual machine, you will initially login as root. However, it's recommended practice to create a username with sudo privileges rather than working in root. For the kind of work a regular person will be doing, sudo privileges might as well just be considered root privileges. There will be no appreciable differences. Think of root privileges like administrator privileges on your home computer.

adduser [your username]
usermod -aG sudo [your username]
ufw app list
ufw allow OpenSSH
ufw enable
[y]

Log back in as [your username]

Setup Nginx on Ubuntu 18.04

How To Install Nginx on Ubuntu 18.04

Step 1 – Installing Nginx

sudo apt update
sudo apt update
sudo apt install nginx

Step 2 – Adjusting the Firewall

sudo ufw app list
sudo ufw allow 'Nginx HTTP'
sudo ufw status  

Step 3 – Checking your Web Server

systemctl status nginx

Step 4 – Managing the Nginx Process

To stop your web server:

sudo systemctl stop nginx

To start the web server when it is stopped:

sudo systemctl start nginx

To stop and then start the service again:

sudo systemctl restart nginx

If you are simply making configuration changes, Nginx can often reload without dropping connections:

sudo systemctl reload nginx

By default, Nginx is configured to start automatically when the server boots. If this is not what you want, you can disable this behavior:

sudo systemctl disable nginx

To re-enable the service to start up at boot:

sudo systemctl enable nginx

sudo mkdir -p /var/www/[yourwebsite.com]/html
sudo chown -R $USER:$USER /var/www/[yourwebsite.com]/html
sudo chmod -R 755 /var/www/[yourwebsite.com]

Add sample HTML page with nano (a text editor) to see if it works:

nano /var/www/[yourwebsite.com]/html/index.html

Fill the file with the following:

<html>
    <head>
        <title>Welcome to [yourwebsite.com]!</title>
    </head>
    <body>
        <h1>Success!  The [yourwebsite.com] server block is working!</h1>
    </body>
</html>

CTRL+O to save, and CTRL+X to exit nano.

Open and edit the sites-available file with nano:

sudo nano /etc/nginx/sites-available/[yourwebsite.com]

Fill the file with the following settings:

server {
	listen 80;
	listen [::]:80;
	root /var/www/[yourwebsite.com]/html;
	index index.html index.htm index.nginx-debian.html;
	server_name [yourwebsite.com] [www.yourwebsite.com];

	location / {
		proxy_pass http://[IP address]:3838;
		proxy_redirect / $scheme://$host/;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection $connection_upgrade;
		proxy_read_timeout 20d;				
	}
}

CTRL+O to save, and CTRL+X to exit nano.

The hard link ln command links /etc/nginx/sites-available/[yourwebsite.com] to /etc/nginx/sites-enabled/ - which is essentially creating an always-updated copy of the original file.

sudo ln -s /etc/nginx/sites-available/[yourwebsite.com] /etc/nginx/sites-enabled/

The ufw allow command allows port 3838 - Rshiny's default port.

sudo ufw allow 3838
sudo ufw allow 3838/tcp

Open and edit the nginx.conf file

sudo nano /etc/nginx/nginx.conf

Uncomment (remove the #) server_names_hash_bucket_size 64;

http {
    ...
    # Map proxy settings for RStudio
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
		
    server_names_hash_bucket_size 64;        # UNCOMMENT     		
    }
}

CTRL+O to save, and CTRL+X to exit nano.

Restart nginx to apply the new settings:

sudo nginx -t
sudo systemctl restart nginx

How To Install R on Ubuntu 18.04

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
sudo add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran35/'
sudo apt update
sudo apt install r-base
[y]

sudo -i R
q()	

How to Set Up Shiny Server on Ubuntu 16.04

Install Shiny Server on RStudio

Need shiny server to run mapping applications!

Step 1 — Installing Shiny

sudo su - -c "R -e "install.packages('shiny', repos='https://cran.rstudio.com/')""

Step 2 — Installing Shiny Server

sudo apt-get update
sudo apt-get install gdebi-core
wget https://download3.rstudio.org/ubuntu-14.04/x86_64/shiny-server-1.5.9.923-amd64.deb

Use check sum to make sure it's all there!

md5sum shiny-server-1.5.9.923-amd64.deb
sudo gdebi shiny-server-1.5.9.923-amd64.deb
[y]

Check to see if shiny server is running

sudo netstat -plunt | grep -i shiny
sudo systemctl status shiny-server

How To Secure Nginx with Let's Encrypt on Ubuntu 18.04

Step 1 — Installing Certbot

sudo add-apt-repository ppa:certbot/certbot
[enter]

sudo apt install python-certbot-nginx
[y]

Step 2 — Confirming Nginx's Configuration

sudo nano /etc/nginx/sites-available/[yourwebsite.com]

double check server_name

sudo nginx -t
sudo systemctl reload nginx

Step 3 — Allowing HTTPS Through the Firewall

sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
sudo ufw status

Step 4 — Obtaining an SSL Certificate

sudo certbot --nginx -d [yourwebsite.com] -d [www.yourwebsite.com]

If done properly, then there should be a print out that contains the following:

Congratulations! You have successfully enabled https://yourwebsite.com and https://www.yourwebsite.com
You should test your configuration at: https://www.ssllabs.com/ssltest/analyze.html?d=yourwebsite.com https://www.ssllabs.com/ssltest/analyze.html?d=www.yourwebsite.com
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/yourwebsite.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/yourwebsite.com/privkey.pem

Step 5 — Verifying Certbot Auto-Renewal

sudo certbot renew --dry-run

GitHub and RShiny

I use RStudio to make changes to my RShiny application locally, then I use git to commit and push working copies to GitHub, which I then pull into my virtual machine. That way I'm never making changes to a live application and only applying them when there are working versions with no errors. I also keep backups (just in case something goes wrong) and have 'working' and 'in-progress' versions.

End of Nginx, LetsEncrypt, and Shiny Setup.


Step 4 — Hosting Interactive R Documents

(This next part is slow!)

Some of your RShiny applications will probably use an R Library or two. In order for them to function on shiny server, the libraries need to be installed. The following commands install some popular R Libraries that I use for my applications. I left this part for last because it took the longest to run, and did Step 5 first. If your application is missing an R Library, you may find yourself bouncing between Step 5 and Step 4. Their order does not matter.

# RMarkdown 
sudo su - -c "R -e "install.packages('rmarkdown', repos='http://cran.rstudio.com/')"" 

Leaflet installs the library Raster, which uses up a good amount of memory. The smallest Digital Ocean Droplet (1CPU and 1GB Ram) will fail because there is not enough available memory for the installation.

# Leaflet 
sudo su - -c "R -e "install.packages('leaflet', repos='http://cran.rstudio.com/')"" 

# RColorBrewer 
sudo su - -c "R -e "install.packages('RColorBrewer', repos='http://cran.rstudio.com/')"" 

# Scales 
sudo su - -c "R -e "install.packages('scales', repos='http://cran.rstudio.com/')""  

# Lattice 
sudo su - -c "R -e "install.packages('lattice', repos='http://cran.rstudio.com/')""

# Dplyr - This one is also slow 
sudo su - -c "R -e "install.packages('dplyr', repos='http://cran.rstudio.com/')"" 

# DT - DataTable 
sudo su - -c "R -e "install.packages('DT', repos='http://cran.rstudio.com/')"" 

# ggplot2 
sudo su - -c "R -e "install.packages('ggplot2', repos='http://cran.rstudio.com/')"" 

# htmlTable 
sudo su - -c "R -e "install.packages('htmlTable', repos='http://cran.rstudio.com/')"" 

# spdplyr
sudo su - -c "R -e "install.packages('spdplyr', repos='http://cran.rstudio.com/')"" 

GDAL is a pain to setup if you're running CentOS 7. It's only slightly better with Ubuntu 18.04. Before proceeding, I would make sure you need this library, then check and see if there are better options available. The reason why it gave me a headache, was because it required the PROJ.4 library. Installing the required dependencies are relatively straight forward on Ubuntu 18.04.

# GDAL - This one was a PAIN!

sudo apt-get update
sudo apt install gdal-bin proj-bin libgdal-dev libproj-dev
sudo su - -c "R -e \"install.packages('rgdal',type='source')\""

Step 5 — Troubleshooting

Does it work?

Go to your web browser and navigate to [yourwebsite.com]

If you are unable to load applications, the issue could be related to folder permissions or the absence of necessary R libraries. The first thing you should check are the shiny server error logs.

Shiny Server Error Logs

Open and read [yourwebsite.com].log

# For server error logs
sudo nano /var/log/shiny-server.log

# For your website application error logs
sudo nano /var/log/shiny-server/[yourwebsite.com].log

CTRL+X to exit nano.

If there is a missing R library, refer to Step 4 to find and install it. If all libraries are installed and the applications are still not loading, then move on to Folder Permissions.

Folder Permissions

If permissions are not setup correctly, they application may just refuse to load shiny applications, resulting in generic error webpages. I had some issues with the permissions set on my sub-directory for my shiny-apps folder, which made it so that my embedded figures were just error messages. The following links provided me with information to fix it:

To start, try granting permissions:

Add a new group called shiny-apps and grant permissions to the shinyapps folder within the shiny-server folder. The shinyapps folder will contain your repository for working RShiny applications.

sudo groupadd shiny-apps
sudo usermod -aG shiny-apps [yourusername]
sudo usermod -aG shiny-apps shiny
cd /srv/shiny-server

sudo chown -R [yourusername]:shiny-apps .
sudo chmod g+w .
sudo chmod g+s .
sudo chmod -R 555 /srv/shiny-server/shinyapps
sudo systemctl restart shiny-server

Check permissions of the shiny-apps folder

ls -ld /srv/shiny-server/sample-apps

Refresh the webpage - Do the applications work? If so, you're good to go!

If not, then proceed to the following:

Open and edit shiny-server.conf

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

Change run_as shiny to run_as [yourusername]


# Instruct Shiny Server to run applications as the user "shiny"
run_as shiny; # change run_as shiny to run_as [yourusername]

# Define a server that listens on port 3838
server {
  listen 3838;

  # Define a location at the base URL
  location / {

    # Host the directory of Shiny Apps stored in this directory
    site_dir /srv/shiny-server;

    # Log all Shiny output to files in this directory
    log_dir /var/log/shiny-server;

    # When a user visits the base URL rather than a particular application,
    # an index of the applications available in this directory will be shown.
    directory_index on;
  }
}

CTRL+O to save, and CTRL+X to exit nano.

Now you're all setup to make mapping applications!

Here is an example application (code) adapted from the superzip-example from RShiny's Demos.