As described in my Shiny overview post, there are different versions of Shiny server. Among other limitations, the open source flavor does not come with built-in support for https and user access control. In this post, we explain how you can nevertheless turn your Shiny Open Source server into a Shiny https server.
This tutorial builds on previous tutorials, namely:
In a future post, we will explain how you can secure Shiny Server Open Source with user/password access.
This tutorial builds on Amazon AWS. But it is easy to adopt it to other cloud services or a local machine.
Https, what’s that?
Https is a protocol that encrypts your communication with a web server. For a one-minute definition, see here. Https can be useful for two things:
- So nobody can read the communication between you and the web server
- So you can be sure that you are really really talking to the desired web server, and not to a fake (a so-called man-in-the-middle)
What is an SSL certificate?
An SSL certificate binds together a domain name, a publisher of data or services, and a cryptographic key. In simple terms, it makes sure that when you connect to www.gmail.com your are really connected with google, and not with somebody who pretends to be google.
An SSL certificate is required for any https communication. Typically, you would buy an SSL certificate from a certification authority like VeriSign, Comodo, digicert, or many others. They come in various flavors and prices, and your browser typically reacts differently based on the strength of the certificate (e.g. by displaying an orange lock, a green lock, or a warning page).
For the sake of this tutorial, we will create our own SSL certificate. It will make sure that the communication to our Shiny server is encrypted. However, most browsers will display a warning when you access your Shiny app. The reason for this is that no certification authority has checked your identity. Feel free, however, to replace the the SSL certificate with a commercially obtained one.
Why would I want to have a Shiny https server?
Without a password-protected Shiny server, there are no secrets, really. So, encrypting the communication does not seem to be overly important, right?
However, making sure that your users are indeed talking to you might be important. For example, consider the case of a finance researcher that publishes on a regular basis a widely used index on company data. If people are using this data e.g. for trading, they want to be sure that the source of the data is indeed the researcher, and not an ill-natured man in the middle that wants to influence the markets to his benefit.
Shiny https (based on Shiny Server Open Source) vs. Shiny Pro?
If you are working for a company and manage to convince your boss to buy a license of Shiny Pro, by all means do that. It is a fine product and gives you advantages that go beyond securing the communication with https. The same is true for a subscription to shinyapps.io
However, if you do not have access to these financial resources, e.g. because you’re in academics or open-source development, and if you are only interested to secure your connection, then this step-by-step guide is for you.
This guide uses Apache Tomcat and Amazon AWS. There are other options to achieve the same thing, but to keep the guide short we do not list them. With a bit of googling, you should be able to adapt this to other scenarios.
Our set-up will look like this:
The numbers correspond to the configuration steps we’ll follow in this guide. Specifically:
- Set up an AWS EC2 Ubuntu instance. If you haven’t done so, this tutorial tells you how.
- Set up Shiny Server Open Source: After this step, you should be able to check your setup with a regular http configuration. How to get there is explained in this tutorial.
- Set up AWS Firewall to only allow connections to our https port. This will block direct http access to the Shiny Server
- Install an SSL Certificate: Here, we’ll install a free, self-generated certificate. But if you want, you can install a bought SSL certificate that makes sure the user will not get any warnings
- Install Apache Tomcat, who will manage the incoming https connections,
- Configure Apache Tomcat to proxy, i.e. to translate/forward incoming https connections to http Shiny Server
If you know your way around AWS and Linux, you’ll be able to finish the entire set-up in about 15 minutes. If this is all news to you, count on spending one or two hours until everything is working properly.
1. Create AWS EC2 Ubuntu instance
Again, see here.
2. Install Shiny Server
If you haven’t done so, check out this post.
3. Block http by configuring firewall
Log into the AWS management console and go to EC2. If you don’t know what the security group of your instance is, go to Instances and select your instance. In the bottom part, you’ll find the Security Group. Click on it. This will get you to the Security Groups. Now, do two things:
- in Inbound Rules, remove the 3838 custom rule we had open to access Shiny server over http
- add an HTTPS rule
Your security group should look similar to this:
Now, try to access your Shiny Server by typing either
Replace the Public IP of your instance, of course. You should get an error page for both cases.
4. Install an SSL certificate
Here, we will create our own SSL certificate. However, for real-world cases, you should instead install a commercially bought SSL certificate. Most commercial CAs provide extensive help on how to install their certificates.
A second point of importance: In a real world scenario, you would secure a domain name that you own. Note, however, that AWS will assign a new IP address when you stop and re-start your instance. So, if you intend to go beyond just trying it out once, then make sure you at least reserve an elastic IP, so you can keep using your certificate even if you need to restart your instance. An elastic IP is an IP address reserved for you, for use on AWS. As IP addresses are scarce, AWS charges you for not using them.
SSH into your instance and perform the following steps.
First, make sure your commands are from su, which avoids typing sudo all the time:
Next, we generate a key:
openssl genrsa -out /etc/ssl/private/apache.key 2048
Finally, we create our SSL certificate, using the key we have just created. Type:
openssl req -new -x509 -key /etc/ssl/private/apache.key -days 365 -sha256 -out /etc/ssl/certs/apache.crt
This will ask you a few questions. The only crucial part is the Common Name. Here you need to enter the public DNS name or the public IP of your AWS instance. Again, note, that normally you would enter a domain name that you own, e.g. ‘shiny.ipub.com’ in my case. If you are just goofing around, enter the public DNS of your instance:
5. Install Apache
apt-get install apache2
aptitude install -y build-essential aptitude install -y libapache2-mod-proxy-html libxml2-dev
You should now have apache installed. To install the ssl and proxy modules in apache, run the following command:
This will open a dialog that asks you which modules you would like to install. Type the following:
ssl proxy proxy_ajp proxy_http rewrite deflate headers proxy_balancer proxy_connect proxy_html
6. Configure the Reverse Proxy
Last thing to do is to configure apache to forward https calls to http port 3838. Here, we do this globally, but if you want to use your apache for something else, too, you will want to do some reading up on apache configuration.
This will open a simple text editor.
Your config file should look like this:
<VirtualHost *:*> SSLEngine on SSLCertificateFile /etc/ssl/certs/apache.crt SSLCertificateKeyFile /etc/ssl/private/apache.key ProxyPreserveHost On ProxyPass / http://0.0.0.0:3838/ ProxyPassReverse / http://0.0.0.0:3838/ ServerName localhost </VirtualHost>
This does two things:
- it turns on SSL for our apache server, pointing to the certificate previously created.
- It forwards all incoming https calls to http port 3838, the default Shiny server port
Save by hitting Ctrl+O and Enter.
Finally, you need to restart apache:
service apache2 restart
Test your Shiny https server
Try connecting to your Shiny server by typing:
Of course, you need to replace the public dns name with the one of your instance.
Remember that, with a self-generated SSL certificate, most browsers display a warning. If you dare insisting to proceed, however, you will see something like this:
And, if you click on the little lock on the left of the address bar, then you’ll see that your communication is encrypted, though the identity is not entrusted:
And here we go, you have your Shiny https server! That’s all you need to add encryption to your Shiny server.
In a future post, we’ll add users and passwords to our Shiny https server.