User Interface

This page describes the features of the ShinyProxy interface and the corresponding documentation.

Main page

After logging in, the user is redirected to the main page. This page contains a list of apps.

App page

As the name suggests the app page is used to display a (running) app. With all features enabled this page can look like:

app-page

The only part of this page controlled by ShinyProxy is the navigation bar. The other part of the page displays the app in an iframe. The navigation bar contains (from left to right):

  • the logo and title (see configuration)
  • the username of the current logged-in user
  • the Switch instance button
  • the Report issue button, clicking on this button opens a popup where a user can report an issue to the administrator of the ShinyProxy server (see configuration).
  • the Admin button which is only showed for admin users, clicking on this buttons opens the admin page.
  • the Sign Out button

Using multiple instances of an app

By default, ShinyProxy allows a user to only run one instance of an app at a given time. This means that a user cannot open a second instance of an app. Starting with ShinyProxy 2.6.0, it is possible to run multiple instances of an app.

There are two ways to control this behavior:

  • by specifying the global proxy.default-max-instances option. By default, this option is set to one. Specifying a larger value allows the user to run the given amount of instances of any apps. This option allows you to specify the value -1 which allows a user to run unlimited instances of any app.
  • by specifying the max-instances option on a specification of an app. This overrides the global value provided in proxy.default-max-instances, but only for this specific app. Again specifying the value -1 allows a user to run unlimited instances of any app.
proxy:
    default-max-instances: 5
    specs:
    - id: 01_hello
      display-name: Hello Application
      container-cmd: [ "R", "-e", "shinyproxy::run_01_hello()" ]
      container-image: openanalytics/shinyproxy-demo
      max-instances: 1
  - id: rstudio
    display-name: RStudio
    container-image: openanalytics/shinyproxy-rstudio-ide-demo:1.4.1106__4.0.4
    container-env:
      DISABLE_AUTH: true
      WWW_ROOT_PATH: "#{proxy.getRuntimeValue('SHINYPROXY_PUBLIC_PATH')}"
    port: 8787

The above example allows a user to run up to 5 instances of RStudio and one instance of the hello application. When the user can run only one app, the Switch instance button is replaced by a Restart instance and Stop instance button.

After clicking on the Switch instance button, a popup is shown where the user can manage the instances of the app:

shinyproxy-instance

The popup lists the current active instances of the app. When clicking on the link on the main page, the “Default” instance is opened. Every instance can be stopped, but only the current open instance can be restarted. A new instance can be opened by providing a name in the input field and clicking the Start button, after which a new tab is opened with the new instance. This new instance will be listed in the popup:

shinyproxy-instance

Note: the different instances of each app are fully isolated and are running in a separate container. This also means that any inactive instances will be cleaned up, independently of any other instance of the same app. A user can stop apps themselves using the Switch instance button, even for apps running in a different tab of their browser.

Automatically reconnecting websockets

Many apps used in ShinyProxy use websockets for communicating with the backend server. Due to the nature of websockets, this connection can be disturbed by suboptimal WiFi connections, server restart etc. Therefore, ShinyProxy contains a mechanism for restoring this connection. However, since ShinyProxy does not know how an app internally works, this is a best-effort approach. Therefore, it is always better to use any reconnecting mechanism which is natively supported by the app. You can configure this option by specifying:

  • the proxy.default-webSocket-reconnection-mode option: specifies the global reconnection mode. By default, this is None.
  • the websocket-reconnection-mode on a specification of an app. This overrides the global value provided in proxy.default-webSocket-reconnection-mode, but only for this specific app.
  • the shiny-force-full-reload on a specification of an app. This controls whether ShinyProxy performs a full reload of the iframe or only tries to restore the websocket connection in case of a Shiny app.

The mode can be set to one of None, Confirm or Auto. In the first case, the mechanism is disabled and ShinyProxy will not try to restore the connection with the app. Using Confirm, ShinyProxy will first ask the user for confirmation before trying to restore the connection. Using Auto, ShinyProxy will automatically try to reconnect to the app without asking the user for confirmation.

When the mechanism is enabled and a websocket connection of the apps get interrupted, ShinyProxy notices this and starts the restore procedure. First of all, a message is shown to the user:

reconnecting

In the background ShinyProxy tries to restore the connection. When ShinyProxy detects that the running application is a Shiny app, it uses the $socket.reconnect() function of the Shiny JavaScript API to restore the connection. For all other apps, ShinyProxy reloads the iframe displaying the app. The mechanism tries to restore the connection up to ten times. However, between every attempt, ShinyProxy waits for an increasing amount of time. That is, after the first attempt, it waits for two seconds, after the third for three second and so on. If the app cannot be restored after 10 seconds, ShinyProxy asks the user whether it should reload the complete page.

Note: you can tell ShinyProxy to reload the iframe instead of using the special Shiny function ($socket.reconnect()) by setting the shiny-force-full-reload option in the app specification to true (see above).

As discussed earlier, the reconnecting mechanism is a best-effort approach. In an ideal case the app should be responsible for restoring the connection. The reason is that the developers of an app know better how to restore the websocket connection. It is not uncommon that extra actions must be taken care of when reconnecting. Such situations cannot be handled by ShinyProxy. Note that as a developer of a Shiny app, you can add native support for reconnecting.

The following table shows how the mechanism works in different situations. This should help an administrator on deciding whether to activate the mechanism.

Configuration App characteristics Result
Enabled? Force reload?¹ Shiny app? App supports reconnecting?² Reconnect mechanism App working after reload? Data loss?
Yes No Yes No $socket.reconnect() It It depends Yes
Yes No Yes Yes $socket.reconnect() Yes No
Yes Yes Yes Yes or No Reload iframe Yes Yes
No N/A Yes Yes or No Do nothing No Yes
Yes N/A No No Reload iframe Yes It Depends, but likely
Yes N/A No Yes Reload iframe Yes It Depends, but likely
No N/A No Yes Do nothing Yes (after native reload) No
  • ¹ shiny-force-full-reload is enabled
  • ² in case of Shiny app, the code is written such that reload works properly. In case of another app, it has a native reconnect mechanism.

The short advice for an administrator is:

  • when an app contains a native reconnecting mechanism -> do not enable the mechanism in ShinyProxy
  • when an app does not contain a native reconnecting mechanism -> try enabling the ShinyProxy mechanism and decide whether this works for your app. In case of a Shiny app, you can also test whether enabling the shiny-force-full-reload option improves things.

Admin page

The admin page is only visible to users which are part of the groups configured in the proxy.admin-groups property. The page displays an overview of the current running apps.

admin page