This article belongs to the series How to deploy a Shiny app on AWS, divided into 7 parts. To access the other articles, use the following table of contents:
- Part 1: Create a Shiny app.
- Part 2: Create an AWS server.
- Part 3: Install R and R Shiny on your new server.
- Part 4: Deploy the app on the server.
- Part 5: Extra: Create a nice domain name.
- Part 6: Extra: Secure your app with HTTPS.
- Part 7: Extra: Protect your app with a password.
In the previous article, we changed the ugly IP address of our Shiny app in a good-looking domain name, so that we could reach the app by typing an URL like http://shiny.charlesbordet.com/movie-explorer.
Except there is still a problem.
Especially if you want to put your app in production for a client.
The app is not secured.
You may have noticed the subtle message from your browser:
Indeed, the app is using the HTTP protocol, which is not secure.
Nowadays, everyone uses HTTPS, the secured version of HTTP.
That’s why, in this article, we’ll talk about:
- What is HTTPS and why we need it
- How to get certificates SSL/TLS for free with Let’s Encrypt
- How to set up the certificates on your server
- How to force HTTPS over HTTP
Let’s get started!
What is HTTPS?
You certainly have heard of it, but you’re not sure how HTTPS works and why we need to use it.
Well. Imagine that each time you land on a webpage, you send a request from your home to the data center where the webpage is hosted.
Then, a request containing the webpage comes back to you so that your browser can display it.
These messages drive all over the world, from router to router, until they reach their destination.
You don’t control who own these routers, nor what they do with it.
And when you use HTTP, those messages are not encrypted.
It means that anyone can intercept the requests, open them, read them, even change them, and send them back without anyone knowing.
That’s called a Man-in-the-Middle attack.
It’s not cool when the requests contain passwords, data or your credit card numbers.
That’s why we decided to upgrade HTTP into something secure: HTTPS.
HTTPS guarantees that the messages are encrypted. If someone intercepts the request, they can’t do anything with it.
At first HTTPS was mostly used for e-commerce, where the data is confidential, but later on, it was used for the whole internet.
Because privacy is good.
That’s why your browser displays this big red warning.
In short. You want:
- that your data stays secured and encrypted
- that your client or boss doesn’t get scared seeing a warning from the browser
So we use HTTPS.
First, we need certificates (SSL/TLS) for the server. And keys.
I won’t get into too many details, but the certificate says “Yea it’s me the real server” and it contains encrypting keys (a public and a private one).
Create a Let’s Encrypt certificate
You can get certificates from trusted organizations.
Most of the time, it costs money.
But not with Let’s Encrypt. It’s free and automatic.
So.. let’s use it.
They even have some small piece of software to automatically renew the certificates. Otherwise, they expire every 3 months.
So, you do this setup once, and then you won’t have to touch it again.
To get started, visit the Cerbot website:.
- Software = Nginx
- System = Ubuntu 18.04 (change if you’re on a different system)
Scroll down and copy/paste the installation instructions in your server. If you don’t remember how to do it, you can go back on the article Install R and R Shiny.
Then, you can automatically get a certificate by typing:
Don’t forget to change the domain name for yours.
The program will speak to you then:
Renewing an existing certificate Performing the following challenges: http-01 challenge for shiny.charlesbordet.com Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/shiny.charlesbordet.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/shiny.charlesbordet.com/privkey.pem Your cert will expire on 2020-02-04. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew"
The most important part is where it says that your certificates and keys are in the
We’ll use that later.
How to set up your new SSL/TLS certificates with nginx
For this section to work, you need to have an existing
That’s the optional section I wrote in the previous article. Check it here: Set up a reverse proxy with Nginx.
If you haven’t done it yet, go there and come back once it’s set up.
We’ll wait for you.
Remember, you had installed a piece of software called
nginx is a web server. One of its features is the reverse proxy that we set up last time.
In the previous article, I explained that Nginx is like a middleman. It listens on port 80 and then redirects visitors to the correct port (3838 if they ask for shiny for example).
Port 80, that was for the HTTP protocol.
But now, we want to use HTTPS.
The port for HTTPS is 443.
How do I know this?
Each protocol has its own dedicated port. It’s not really up to us. For example, SSH is on 22, FTP on 21, etc.
It’s all listed on this Wikipedia page: List of TCP and UDP port numbers.
It goes up to 1024, and then any number after 1024 is free to use. That’s why Shiny picked 3838 by default (but we can change it).
We’ll change the Nginx configuration to use 443 instead of 80.
As a reminder, here is the path to the config file:
You should get the file we modified last time.
We’ll change a few lines.
1. Change the port
First, let’s change the port number.
Find the two lines that start with
listen and replace them with the following ones:
2. Configure SSL
Next, let’s add the SSL parameters.
SSL, that’s the encrypting protocol. Think of it like HTTP + SSL = HTTPS.
We should say TLS now, but everyone keeps talking about SSL.
I’m no expert in SSL.
So I can’t tell you every tiny detail of it.
And that’s why I use Mozilla’s recommendations. They have an SSL Configuration Generator.
Check the link and add these lines in the config file:
That’s a lot.
And there are a few things to change:
The two first rows:
ssl_certificate_key. You need to feed them with the certificates we generated earlier.
I changed them with:
(Of course, don’t forget to put your domain name)
3. Download the DH parameters
Then, the DH parameter.
The comment tells us to download them. Let’s do it:
And then change the path for
HSTS section, I recommend you deactivate it for now.
HSTS is used to tell the browser: “From now on, and for years to come, you only use HTTPS for this domain and never HTTP.”
It’s a good practice.
Except if you have issues to set up HTTPS and want to come back to HTTP, you’re screwed.
And since it’s your first time, you should expect things to go wrong.
Even if you’re following my article.
So let’s deactivate it for now, and only when we’re sure everything works we’ll activate it again. I’m adding an
4. Use the Let’s Encrypt certificate
Finally, we’re only left with the last line:
And… that’s it!
It’s test time!
Save the file, and check that there are no syntax errors:
You should get the following response:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
If not, it means you have done a syntax error. The error message should tell you what’s wrong.
Once the syntax is validated, let’s restart
Check your domain name (type https at the beginning): https://shiny.charlesbordet.com/movie-explorer.
Your browser should display a nice lock with a comforting message:
How to force HTTPS over HTTP
I told you earlier to deactivate HSTS.
Now that everything is working smoothly, let’s activate it:
And we’ll do a second change.
In the SSL configuration generator, they added another
server bloc at the top of the file.
Well, this other bloc is listening on port 80, and its only job is to automatically redirect to port 443.
That’s for the users who will visit your app with HTTP.
Instead of getting a 404 page, they’ll get redirected to the secured page.
So, let’s add these few lines at the top of your config file:
Now we’re good!
Don’t forget to restart
nginx once again:
Now, your app is secured, and the data you send with it is encrypted.
Woah, this is getting serious!
We’re a bit far away from the R language now and we can say we entered the sysadmin world.
I don’t know about you, but I love this new world.
I find it super interesting to learn about how servers work, and even the Internet.
Please share in the comments if you’ve successfully set up HTTPS (or if you’re stuck somewhere).
In the meantime, there is one last topic to tackle in this series: How to protect the app with a password.
Leave a Comment
Required fields are marked *