Shiny on AWS - Create a nice domain name

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:

In Part 4 of the series, we deployed the Shiny app on the AWS server that we had created.

At the end of the article, we could just type in the browser and our app appeared magically!

Shiny AWS Movie Explorer Final


Just as a reminder from the previous article, here is what you have on the server:

  • You deploy the app in the /srv/shiny-server directory.
  • You read the logs of Shiny in /var/log/shiny-server. This helps to understand why your app crashes.
  • You can change the configuration of Shiny in /etc/shiny-server/shiny-server.conf.

These are the three directories you need to remember.

After a while, you get used to it.

Until then, don’t hesitate to reach out to the previous articles.


I just said we can reach our Shiny app just by typing, and.. that’s kind of great!

But seriously, will you tell your friends to type and remember these numbers?

Or tell your client he has to use these numbers?

Not really..

What would be cool would be to have a really nice-looking URL.

For example, I host all my apps on

Easy to remember, and convenient for everyone.

You can find our app at this address:

How to do that?

Three steps:

  1. Get your domain name
  2. Set up the DNS
  3. Set up a reverse proxy

If you’re not familiar with servers, this might feel complicated.

But stay with us. I’ll guide you through each step with screenshots, as usual.

1. Get your domain name

The first step, if you want to use a domain name, is to get one!

This also means buying one.


It costs money.

Mine ( costs $14.99 per year.

But you can find cheaper ones, sometimes for less than 2$ per year.

I got mine at, a company specialized in domain names.

I’ve been using them for years and never had any issues.

I’m also using OVH for .fr domains since Hover doesn’t do them.

I will use Hover in the rest tutorial but don’t worry. Pretty much all domain providers have similar interfaces.


So let’s say you have bought your cool new domain name!

Now, you must make the link between:

  1. The domain name
  2. The IP address of your server

What do we use for that?

DNS of course!

2. Set up the DNS

DNS stands for Domain Name System.

It is one of the most fundamental services used all over the internet.

Even though pretty much nobody knows what it is.

It’s what allows you to type in your address bar rather than

In a few words, it makes using the internet way friendlier!

And that’s exactly what we want to do!

We want people to type rather than

Your domain name provider will have a page where you can set up the DNS.

In Hover, simply click on the DNS tab:

DNS on Hover

You can see some default entries here that might be different than my screenshot.

If you’re curious to understand what’s going on in this table, check out the blue box. Otherwise, you can jump right after to continue the tutorial.

Blue Box: A crash course in DNS entries

Each DNS entry indicates where to redirect users when they type your domain name.

Why not have only one entry?

Because you could have on one server, then on a different server, and so on. For each specific use, you must add a new row.

The TYPE column can be A to redirect the domain name towards the IP address of a server. It can be CNAME if you redirect the domain name towards another domain name. It can be MX for a mail server.

The HOST column is for the subdomain. The subdomain is everything before your domain. For example, when I type, this is a subdomain of The star * means all subdomains. The @ means the main domain ( in this case).

The VALUE column depends on the TYPE you chose. If you choose TYPE A, then you must enter an IP address.

The rest is unimportant for us today.

The default values here tell us that the main domain and all subdomains * are redirected to the IP address

That is not exactly what we want.

What I would like is to have the subdomain redirecting directly to the IP address of my AWS server.

To do so, remove both rows with TYPE A, and add this one instead:

Create DNS Record on Hover

If you don’t want to use a subdomain and you want your main domain to redirect to your AWS server, then write @ instead of shiny for the hostname.

Finally, my table looks like that:

New DNS with Hover

Now, every time someone types in his browser, he gets redirected automatically to my AWS server!

We’re not done though!

If you try by yourself, you’ll notice it doesn’t work.


We haven’t specified a port!

You still need to write to access the app.


That’s kind of annoying.

But we’re getting close!

There are two ways to solve this issue:

  1. The quick & dirty way
  2. The proper good long-term solution

The Quick & Dirty port removal solution

If you want something quick that works right now, do the following:

  1. SSH into your AWS server (check part 3 if you’ve forgotten how to do this)
  2. Open your Shiny config file: sudo nano /etc/shiny-server/shiny-server.conf.
  3. Change the row listen 3838 for listen 80.
  4. Restart shiny server by typing sudo systemctl restart shiny-server.

And that’s it!

Note: Don’t forget to open port 80 in the AWS firewall. See the article Open the port on the firewall.

Now Shiny Server listens on port 80 instead of 3838.

Why 80?

80 is the default HTTP port.

In fact, when you type in your browser, the browser uses port 80 by default.

Before, we had to specify 3838 because it’s uncommon and it can’t guess it.

So, why is it a quick & dirty solution?

Quick, ok.

Dirty, because if tomorrow you want to install another service on your server, such as an RStudio Server, or a Jupyter Notebook server, or a website, you will face the same issue.

And only one service can listen to port 80 at a time.

If you have a Shiny Server and an RStudio Server on the same machine, they must use two different ports.

They can’t both use port 80.

But you still want to have two clean URL such as and

So, what to do?

The solution is to use a Reverse Proxy Server like Nginx.

3. Set up a reverse proxy with Nginx

I could tell you exactly what to type in the terminal and be done with it.

But that’s now how I teach.

I prefer to have you understand what you’re typing.

If tomorrow you want to do something slightly different, you’ll be able to do it.

So, let’s start with..

What the hell is a reverse proxy?

Think of your server like a house that has many doors.

65,535 doors exactly.

And let’s call these doors ports, okay? porte is the French word for door.

If you want to reach out for some information in the house, you must pass one of these ports, ask the guy behind, and then get back home with the information.

Well, Shiny Server is one of these information providers.

It’s located by default at port 3838.

And let’s say you also have a service at port 8080.

That’s the default port if you install RStudio Server.

If you knock at port 3322, nobody will reply, because nobody’s there.

Without Reverse Proxy

This works.

But it’s not handy because you have to knock at the right door.

As we said before, you have to specify the port number in the URL, such as and it’s ugly.

What if, instead, there was a doorman at the main entrance that could bring you to the right person?

You ring at the main entrance and ask for Shiny Server, and you get to it right away.

And if you want RStudio Server, you ring at the main entrance and ask for RStudio Server.


Wayy easier!

No messing around trying to find the right door.

This doorman is called a reserve proxy.

Nginx is the best reverse proxy server out there.

With Reverse Proxy

Instead of typing the port number, you can only type and talk to Nginx.

Nginx understands you need to access the Shiny Server, so it fetches the right information and get it back to you directly.

To do so, we need to:

  • Install Nginx on your server.
  • Configure Nginx.

Install Nginx

This is the easiest step.

After SSH-ing to your AWS instance (check part 3 and stop forgetting how to do it), type the following:

$ sudo apt install nginx

And Nginx is installed.


Configure Nginx

Now for the tricky part.

First, change directory (cd) to where Nginx is installed:

$ cd /etc/nginx
$ ls
auth          fastcgi_params  mime.types         proxy_params     snippets
conf.d        includes        modules-available  scgi_params      uwsgi_params
dhparam.pem   koi-utf         modules-enabled    sites-available  win-utf
fastcgi.conf  koi-win         nginx.conf         sites-enabled

The ls command list all the files in this directory.

What’s of interest for us is the nginx.conf file, but we won’t touch it.

Instead, well jump to the sites-available folder and create a new file specifically for Shiny Server.

$ cd sites-available
$ sudo nano shiny.conf

And that’s where we write the config file:

server {
    # listen 80 means the Nginx server listens on the 80 port.
    listen 80;
    listen [::]:80;
    # Replace it with your (sub)domain name.
    # The reverse proxy, keep this unchanged:
    location / {
        proxy_pass http://localhost:3838;
        proxy_redirect http://localhost:3838/ $scheme://$host/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 20d;
        proxy_buffering off;

There isn’t much going on here but it can look intimidating.


The beginning states that the Nginx server now listens on port 80. Exactly what we wanted to do with our Shiny Server.

But since only ONE service can listen on port 80, we give it to Nginx.

In short, we’re telling our doorman to wait at the main entrance.


The server_name is what the user types to access the app.

In my case, I want the user to access my Shiny app on the subdomain

Replace the value with your own domain name.


Finally, everything inside location is the reverse proxy happening.

We’re giving instructions to our doorman:

If the user comes and asks for, then guide him through the house at door 3838.

And that’s it!

If you want to use this config file for RStudio Server, you can add a second file called rstudio.conf, and inside you put the same config and only replace two things:

  1. The server_name
  2. The port number

There is one thing left to do.

Save the file and go back to the terminal.

We need to create a shortcut inside the sites-enabled directory:

$ cd ../sites-enabled
$ sudo ln -s ../sites-available/shiny.conf .

Why is that necessary?

The deal is that Nginx does NOT look at the sites-available folder.

Only at the sites-enabled folder.

So we create the conf file inside sites-available and then we create a shortcut inside sites-enabled.

Why? So that if tomorrow you want to temporarily deactivate your access to Shiny, you only have to delete the shortcut.

You don’t have to delete the entire conf file and regret it later.

Now that our reverse proxy is set up, we only need to restart Nginx to take into account the changes.


$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

This ensures that the conf file is correct.

If you get the error nginx: [emerg] unknown "connection_upgrade" variable, that’s because the $http_upgrade and $connection_upgrade variables don’t exist.

In this case, open /etc/nginx/nginx.conf and add the following lines inside the http bloc:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;

Save, and try to validate the syntax again with sudo nginx -t.


$ sudo systemctl restart nginx


Your Shiny app is now accessible on a good-looking URL such as!

The last part was not easy, but that’s the best way to do it.

Plus, it comes with other benefits.

Such as..

Making your app secure with HTTPS!

That’s what you’ll learn in the next article.

Stay tuned!




This guide is excellent! What would you need to do if you wanted separate custom domains for different shiny apps hosted in my directory? Would I just use the same procedure that you describe for doing an rstudio server and shiny?


Hi Sono, I’m glad you like it :)

To create separate custom domains with the same Shiny Server:

Hm I’m not sure actually. My first approach would be to set up a redirection, for example from to I will show how to set up a redirection with Nginx in the next article (yet to be written!)

It’s different than having an RStudio Server and Shiny Server side by side, because in this case you can have different ports. Say 8080 for RStudio and 3838 for Shiny. Then you set up Nginx accordingly.

Rich Pauloo

I’ve spent this Sunday following your guide from parts 1-5, and it’s the best guide so far on the topic! Thank you for writing it. I look forward to reading your next two posts on HTTPS and authentication. Do you think you’ll use shiny-auth0?


Hey Rich! Thanks for the good words :) For the authentication part, I’ll probably use auth0 indeed because that seems to be the best solution at the moment, but I know some people are using others, so I might investigate a little bit over other existing solutions to pick the best one!


Charles I love you man hahah. Your method has worked beautifully. Big hug from Colombia my friend. Now I am stuck at this last post. After executing “sudo nginx -t” the following error comes up:

nginx: [emerg] unknown "connection_upgrade" variable
nginx: configuration file /etc/nginx/nginx.conf test failed

I usually do hours of search in stackoverflow and the internet. But this time I’ve had no luck. I can’t see the source of the error. The shiny.conf file is correct. I didn’t touch the “location / {}” section where the “connection_upgrade” is located, yet this error comes up. Help please master.


Hey Camilo! Thanks for the good words (;

You should check the file in /etc/nginx/ningx.conf file. In this file, add the following:

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;

inside the http {} brackets.

Let me know if that solves your problem!


excellent! I’m just started to learn AWS and connection with R and your articles really helped me.
I am going yo start to make my free aws and try these concepts!
can’t wait to read the new article about HTTPS.


One of the best article I ever read. Excellent!

Eagerly waiting for the next article about https. Any timeline on it and when can we expect that?


Thanks for the good words :) I’m actually currently working on the next article about https, so it’ll come soon!


man, I love you :O) This series is soooooo great! I confess that for the moment I only wandered here and there to get my server running (I am in a rush!!). But I will definitively take the time to carefully study it!

If you could also modify the main page of the tutorial to include the correction of the nginx.conf file that you suggested to Camilo, it would spare people a heart attack :O)


Hello Leonardo and thank you for the good words ;)

I have updated the article to reflect the changes to the nginx.conf file!


Just wanted to say thanks for your article. It guided me through getting my app running on a url. Thanks so much for the help, and looking forward to the next articles

Leave a Comment

Required fields are marked *


Comments are validated manually. The page will refresh after validation.