Shiny App in Docker with HTTP Authentication

[This article was first published on R | datawookie, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Suppose you have an applocation running on a Shiny server and you want to add HTTP authentication so that it’s only accessible via a username and password. This can be done using NGINX.

Test Shiny Server

The Shiny server should be accessible at http://localhost:3838/ (assuming you’re running Shiny server on localhost). ? Substitute another IP address or DNS entry if you’re running on another machine.

Install Packages

Install a couple of packages.

sudo apt install -y nginx-light apache2-utils

Default Configuration

Make a backup copy of /etc/nginx/nginx.conf then replace the original content with the following.

events {}

http {
  server {
    listen 80;
    
    location / {
      proxy_pass http://127.0.0.1:3838;
    }
  }
}

This is a minimal NGINX configuration. You could (and perhaps should!) provide a more extensive configuration.

Restart NGINX.

sudo service nginx restart

Once you’ve restarted NGINX the Shiny server will be accessible on port 80 at http://localhost/. ? Replace localhost if necessary.

Password File

Now we need to set up some credentials. We’ll use the htpasswd tool to create and populate a password file, /etc/nginx/.htpasswd.

# Create a "wookie" user.
sudo htpasswd -c /etc/nginx/.htpasswd wookie

Type and retype a password.

Check for user and hashed password.

cat /etc/nginx/.htpasswd
wookie:$apr1$6dONo8NN$169ClUPwSYtxhZ05fTE4l1

? You can add more usernames and passwords by running the htpasswd again. However, omit the -c flag so that the password file is not truncated each time.

Adding Authentication to NGINX Configuration

Now we need to tell NGINX to use the password file.

Authentication at the Location Level

Update /etc/nginx/nginx.conf.

events {}

http {
  server {
    listen 80;
    
    location / {
      auth_basic "Shiny Server";
      auth_basic_user_file /etc/nginx/.htpasswd;

      proxy_pass http://127.0.0.1:3838;
    }
  }
}

We’ve inserted auth_basic and auth_basic_user_file records for a specific location entry.

The location block passes all requests for the root URL to the Shiny server listening on port 3838.

Restart NGINX. When you try to connect to the Shiny server you should get an authentication popup.

Authentication at the Server Level

You can also add authentication at the server level, which means that it will apply to all locations. This is moot for our configuration, which has only a single location specified.

user www-data;
worker_processes auto;
daemon on;                  # Run as daemon process

events {
  worker_connections 512;
}

http {
  gzip on;

  server {
    listen 80;
    
    auth_basic "Shiny Server";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    location / {
      proxy_pass http://127.0.0.1:3838;
    }
  }
}

Although there’s now a password challenge, the actual credentials are still being transmitted over HTTP. This means that, although access to the resource is secured, it’s possible for an adversary to intercept your credentials en route to the server.

To lock this down properly you’d need to also add SSL.

Try It Yourself

If you’d like to experiment with this, here are some resources:

To build and run the Docker image:

docker build -t shiny-nginx .
docker run --rm --name shiny-nginx -p 80:80 shiny-nginx

To leave a comment for the author, please follow the link and comment on their blog: R | datawookie.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)