Shiny

Shiny wurde 2012 von Posit (ehemals RStudio) angekündigt, und ist ein Web-Framework für die Entwicklung von Webanwendungen (Apps). Es ist ursprünglich in R und seit 2022 auch in Python verfügbar. Eine der Anwendungen von Shiny ist das schnelle Prototyping.

Im Jahr 2022 wurde eine parallele Implementierung von Shiny für Python angekündigt, die beide unabhängig voneinander entwickelt werden. Shiny for Python nutzt Starlette und asyncio und lässt sich per pip install shiny einrichten. Eine App startet man typischerweise mit dem CLI-Befehl shiny run, der intern einen ASGI-Server hochfährt - ganz anders als beim Node.js-basierten Shiny-Server für R Shiny.

Mit Shiny kann der Benutzer auf Basis seiner Eingaben Berechnungen erneut ausführen oder Grafiken nahezu in Echtzeit neu rendern. Für die Eingabevariablen stehen Widgets wie Textfelder, Optionsfelder und Dropdown-Listen zur Verfügung.

Eine Shiny-Datei besteht aus zwei Blöcken, die alternativ auch in zwei separaten Dateien gespeichert werden können. Der eine Teil ist für die Benutzeroberfläche (meist ui.R) und der andere Teil für die Serverberechnungen und den Code zur Diagrammerstellung (meist server.R) vorgesehen.

Mit Shinylive wird Shiny auf dem Client ausgeführt.

Links

Installation

Siehe auch https://posit.co/download/shiny-server/:

sudo dnf -y install epel-release wget

# RHEL 8
sudo dnf config-manager --set-enabled powertools

# RHEL 9
sudo dnf config-manager --set-enabled crb

Bevor der Shiny-Server installiert werden kann, muss R und das Shiny R Paket installiert werden:

sudo dnf -y install R
sudo R -e "install.packages('shiny', repos='https://cloud.r-project.org')"
sudo R -e "install.packages('rmarkdown', repos='https://cloud.r-project.org')"

Shiny-Server installieren. Für die aktuellste Versionsnummer siehe https://posit.co/download/shiny-server/:

wget https://download3.rstudio.org/centos8/x86_64/shiny-server-1.5.23.1030-x86_64.rpm
sudo dnf -y localinstall shiny-server-1.5.23.1030-x86_64.rpm

Shiny-Server starten:

sudo systemctl enable --now shiny-server
sudo systemctl status shiny-server

Die Installation landet in /opt/shiny-server (/srv/shiny-server symlinkt auf /opt/shiny-server).

Der Shiny-Server ist anschliessend per http://shiny:3838/ erreichbar. Beispiel-Apps finden sich auf http://shiny:3838/sample-apps/hello/ und http://shiny:3838/sample-apps/rmd/ und können per sudo rm -rf /srv/shiny-server/sample-apps gelöscht werden.

Die Shiny-Server Konfigurationsdatei:

/etc/shiny-server/shiny-server.conf
# Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;

# Define a server that listens on port 3838
server {
  listen 3838;

  # Define a location at the base URL
  location / {

    # Host the directory of Shiny Apps stored in this directory
    site_dir /srv/shiny-server;

    # Log all Shiny output to files in this directory
    log_dir /var/log/shiny-server;

    # When a user visits the base URL rather than a particular application,
    # an index of the applications available in this directory will be shown.
    directory_index on;
  }
}

Einfache Shiny-Anwendung

/srv/shiny-server/samples/sample-apps/hello/server.R
library(shiny)

# Define server logic required to draw a histogram
shinyServer(function(input, output) {

  # Expression that generates a histogram. The expression is
  # wrapped in a call to renderPlot to indicate that:
  #
  #  1) It is "reactive" and therefore should be automatically
  #     re-executed when inputs change
  #  2) Its output type is a plot

  output$distPlot <- renderPlot({
    x    <- faithful[, 2]  # Old Faithful Geyser data
    bins <- seq(min(x), max(x), length.out = input$bins + 1)

    # draw the histogram with the specified number of bins
    hist(x, breaks = bins, col = 'darkgray', border = 'white')
  })

})
/srv/shiny-server/samples/sample-apps/hello/ui.R
library(shiny)

# Define UI for application that plots random distributions
shinyUI(pageWithSidebar(

  # Application title
  headerPanel("It's Alive!"),

  # Sidebar with a slider input for number of observations
  sidebarPanel(
    sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
  ),

  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot", height=250)
  )
))

Mandantentrennung in Shiny

Dafür gibt es mehrere Möglichkeiten:

  • Es lassen sich beispielsweise separate Shiny-Server-Instanzen auf jeweils unterschiedlichen Ports oder IPs betreiben, die von einem Apache Reverse-Proxy individuell angesprochen werden.

  • Man verwendet einzelne Docker-Container.

  • Oder man setzt gleich auf eine VM pro Mandant für volle Netz- und Nutzerisolation.

  • Hier wird eine möglichst einfache Mandantentrennung auf Ebene des Apache Reverse-Proxies beschrieben, bei der jeder Mandant eine eigene VirtualHost-Konfiguration erhält, die nur die jeweilige Shiny-Location proxyt.

Beispiel:

  • shiny-hello.example.com > App „hello“

  • shiny-rmd.example.com > App „rmd“

Shiny-Server-Konfiguration - zwei getrennte Applikationen:

/etc/shiny-server/shiny-server.conf
run_as shiny;
preserve_logs true;

# just listen locally, if Apache Reverse Proxy is running here on localhost
server {
  listen 3838 127.0.0.1;

  # App "hello"
  location /hello {
    app_dir /srv/shiny-server/sample-apps/hello;
    log_dir /var/log/shiny-server/hello;
  }

  # App "rmd"
  location /rmd {
    app_dir /srv/shiny-server/sample-apps/rmd;
    log_dir /var/log/shiny-server/rmd;
  }
}

Apache vHost für App „hello“ - die relevanten Teile:

<VirtualHost *:80>
    ServerName shiny-hello.example.com

    # increase websocket disconnects (default: 10s)
    Timeout 60

    # proxy_module
    ProxyPreserveHost On

    # rewrite_module
    RewriteEngine On

    # limit allowed http request methods
    RewriteCond %{REQUEST_METHOD} !^(GET|OPTIONS)
    RewriteRule .* - [redirect=405,last]

    <Location />
        AuthType Basic
        AuthName "Shiny Apps hello"
        AuthUserFile /etc/httpd/.htpasswd-hello
        Require valid-user
    </Location>

    RewriteCond %{HTTP:Upgrade} =websocket [nocase]
    RewriteRule /(.*) ws://127.0.0.1:3838/hello/$1 [proxy,last]
    RewriteCond %{HTTP:Upgrade} !=websocket [nocase]
    RewriteRule /(.*) http://127.0.0.1:3838/hello/$1 [proxy,last]
</VirtualHost>

Benutzer und Passwörter für die simple HTTP Basic-Auth anlegen:

sudo htpasswd -c /etc/httpd/.htpasswd-hello firstname.lastname

Fertig.

Monitoring

  • SystemD-Service(s) wie shiny-server.service

  • Shiny-Server Listen-Port wie 3838

  • von Shiny-Server angebotene URLs

Backup und Restore

Folgende Verzeichnisse sichern:

  • /etc/shiny-server

  • /srv/shiny-server

  • /var/log/shiny-server (optional)

Troubleshooting

tail -f /var/log/shiny-server.log /var/log/shiny-server/*.log

Built on 2025-10-27