ShinyProxy is a free and open-source platform to deploy containerized web applications and is packed with enterprise features.
ShinyProxy requires a Java runtime, and Docker to run containers. Dockerized Shiny applications have been the primary target as the name indicates. But don't let this fool you, ShinyProxy can host any web app, including RStudio IDE, Python Dash, and more.
ShinyProxy comes with lots of free enterprise features, e.g. various ways of authentication and authorization. It has no limits on concurrent usage of the deployed applications. When a user runs an application, ShinyProxy spins up a new container and serves the application to the user. This is all made possible by the dedicated developer team at Open Analytics.
The Docker-based workflow comes with some advantages:
- user sessions are fully isolated
- apps can have different R versions, package versions, and dependencies
- updates to one app won't interfere with other apps
- monitoring and resource management (RAM and CPU usage) can be done with Docker tooling
This post shows you how you can set up this versatile, robust, and tested piece of technology to host your Shiny apps!
System Requirements
Provision a virtual machine with your favourite cloud provider. I use Ubuntu Linux 20.04 in this tutorial. You will need root user access, root user is usually root
(e.g. on DigitalOcean) or ubuntu
(e.g. on AWS). I will assume you have your ssh
keypair configured for passwordless login. Include the internet protocol (IPv4) address of your server as the $HOST
environment variable:
export HOST="159.203.63.9"
ssh root@$HOST
Update the system, install the Java runtime, the Docker Engine CE (community edition) and Docker Compose:
apt-get -y update
apt-get -y upgrade
apt-get -yq install \
default-jre \
default-jdk \
docker \
docker-compose
Check that all went according to plan, java -version
should return something like this:
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)
ShinyProxy needs to be able to connect to the Docker daemon to spin up the containers for the apps. By default, ShinyProxy will do so on port 2375 of the Docker host. To allow for connections on port 2375, the startup options need to be edited following the ShinyProxy guide.
Create a file /etc/systemd/system/docker.service.d/override.conf
:
mkdir /etc/systemd/system/docker.service.d
touch /etc/systemd/system/docker.service.d/override.conf
Add the following content (use nano
or vim
):
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H unix:// -D -H tcp://127.0.0.1:2375
Reload the system daemon, then restart and enable Docker:
systemctl daemon-reload
systemctl restart docker
systemctl enable docker
All this is to make sure that the Docker service starts when the system boots and the system configurations stay the same so that ShinyProxy can function properly.
To see if Docker is running properly, type service docker status
:
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/docker.service.d
└─override.conf
Active: active (running) since Wed 2021-07-21 03:55:26 UTC; 36s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 18881 (dockerd)
Tasks: 9
Memory: 39.6M
CGroup: /system.slice/docker.service
└─18881 /usr/bin/dockerd -H unix:// -D -H tcp://127.0.0.1:2375
Install ShinyProxy
We download and install version 2.5.0 of ShinyProxy. In case of a newer version, just change the version variable accordingly, check for updates on the downloads page:
export VERSION="2.5.0"
wget https://www.shinyproxy.io/downloads/shinyproxy_${VERSION}_amd64.deb
apt install ./shinyproxy_${VERSION}_amd64.deb
rm shinyproxy_${VERSION}_amd64.deb
Configure ShinyProxy
ShinyProxy looks for a configuration file called application.yml
in the /etc/shinyproxy
directory. Let's create this file:
touch /etc/shinyproxy/application.yml
Copy these configs using a command-line text editor:
proxy:
title: ShinyProxy
# logo-url: https://link/to/your/logo.png
landing-page: /
favicon-path: favicon.ico
heartbeat-rate: 10000
heartbeat-timeout: 60000
port: 8080
authentication: simple
admin-groups: admins
# Example: 'simple' authentication configuration
users:
- name: admin
password: password
groups: admins
- name: user
password: password
groups: users
# Docker configuration
docker:
cert-path: /home/none
url: http://localhost:2375
port-range-start: 20000
specs:
- id: 01_hello
display-name: Hello Shiny App
description: A simple reactive histogram
container-cmd: ["R", "-e", "shiny::runApp('/home/app')"]
container-image: registry.gitlab.com/analythium/shinyproxy-hello/hello:latest
logo-url: https://github.com/analythium/shinyproxy-1-click/raw/master/digitalocean/images/app-hist.png
access-groups: [admins, users]
- id: 02_hello
display-name: Demo Shiny App
description: App with sliders and file upload
container-cmd: ["R", "-e", "shiny::runApp('/home/app')"]
container-image: analythium/shinyproxy-demo:latest
logo-url: https://github.com/analythium/shinyproxy-1-click/raw/master/digitalocean/images/app-dots.png
access-groups: [admins]
logging:
file:
name: shinyproxy.log
Pull the two Docker images referenced in the configuration file:
docker pull registry.gitlab.com/analythium/shinyproxy-hello/hello:latest
docker pull analythium/shinyproxy-demo:latest
The first one is the familiar Hello image. The second one is another simple Shiny app (that you can find in this GitHub repository) with coloured random points and a file uploader that prints the size of the uploaded file.
The last step is to restart the ShinyProxy service so that the new configuration takes effect:
service shinyproxy restart
Check the status with service shinyproxy status
:
● shinyproxy.service - ShinyProxy
Loaded: loaded (/etc/systemd/system/shinyproxy.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-07-21 04:22:46 UTC; 10s ago
Main PID: 19552 (java)
Tasks: 12 (limit: 2344)
Memory: 118.9M
CGroup: /system.slice/shinyproxy.service
└─19552 /usr/bin/java -jar /opt/shinyproxy/shinyproxy.jar
Admin and user views
You can access your ShinyProxy server at http://$HOST:8080
. Visit this address and log in using the username 'admin' and password 'password' as defined in the configuration:
Note that the connection is not secure, this is something that can be addressed later. Once inside, the admin view lists both apps with their thumbnail images. Click on the links to spin up the apps. Clicking the 'Admin' button to see the active proxies listing the users, app names, uptime, etc.
Now log out and try logging in with the 'user' / 'password' combination. You can only find one of the apps listed. This is how we set up access based on the user groups. This gives great flexibility for managing the users' access at the application level.
Conclusions
This is the basic setup of ShinyProxy with basic authentication/authorization. Edit the configuration file, pull new Docker images with your Shiny apps and enjoy. There is a lot more you can do to secure the server and set up a custom domain. I will cover these topics next.