Shiny¶
Siehe auch
- Verwandte Artikel
- Offizielle Dokumentation
Shiny ist ein Web-Framework aus dem Hause Posit (ehemals RStudio), mit dem sich interaktive Webanwendungen bauen lassen, ohne dass man in JavaScript oder HTML schreibt. Für Eingaben (Slider, Dropdowns, Textfelder) und Ausgaben (Tabellen, Plots, berechneter Text) liefert das Framework Widgets; zwischen Eingabe und Ausgabe sitzt eine reaktive Berechnungs-Schicht, die bei Bedarf neu rendert. Ursprünglich 2012 für R vorgestellt, ist Shiny seit 2022 auch für Python verfügbar (pip install shiny, ASGI-basiert, unabhängig von der R-Implementierung gepflegt).
Eine klassische Shiny-App für R besteht aus zwei Blöcken, die entweder in einer app.R zusammen liegen oder auf ui.R und server.R aufgeteilt sind. ui.R definiert die Oberfläche, server.R die Logik und die Rendering-Funktionen. Mit Shinylive lässt sich eine Shiny-App ohne Server-Komponente direkt im Browser (WebAssembly) ausführen.
Das Shiny-Ökosystem¶
Posit vertreibt mehrere Produkte rund um Shiny. Die Abgrenzung ist wichtig, weil die Namen ähnlich klingen, die Rollen aber sehr verschieden sind:
- Shiny
Das R- bzw. Python-Framework selbst. Open Source. Auf dem Entwickler-Rechner reicht es aus, um eine App interaktiv zu testen, und auch für einen einzelnen Produktions-Dienst lässt sich eine App mit
shiny::runApp()bzw.shiny runhinter einem Reverse Proxy betreiben.- Shiny Server (Open Source)
Node.js-basierter Webserver, der mehrere R-Shiny-Apps auf einem Host hostet und pro Request einen R-Prozess startet. Konfiguration über
/etc/shiny-server/shiny-server.conf. Bindet Shiny-Apps unter URL-Paths ein, rotiert Logs pro App. Posit bietet offizielle RPM-Builds nur für RHEL 8 an (sowie Ubuntu 20+ und SLES 15); für RHEL 9 und 10 gibt es kein offizielles Paket.- Shiny Server Pro
Die kommerzielle Variante mit LDAP/Active-Directory-Authentifizierung, pro App mehrere parallele R-Prozesse, Detail-Monitoring. Sales gestoppt per 2021-01-01, End-of-Life per 2026-03-31. Für Neukunden nicht mehr verfügbar, für Bestandskunden empfiehlt Posit die Migration auf Posit Connect.
- Posit Connect
Kommerzielles Hauptprodukt von Posit und funktionaler Nachfolger von Shiny Server Pro. Hostet Shiny-Apps (R und Python), Plumber-/FastAPI-APIs, Jupyter-Notebooks, Quarto-Dokumente, R-Markdown-Reports und Streamlit-Apps auf einer Plattform, inklusive Benutzer- und Rechte-Management, Scheduling, Versionierung und Zugriffs-Audit.
Installation Shiny Server (Open Source) auf RHEL 8¶
Voraussetzungen und R installieren:
dnf --assumeyes install epel-release
dnf config-manager --set-enabled powertools
dnf --assumeyes install cmake tar wget R
R-Pakete für Shiny einrichten:
R --quiet -e "install.packages(c('shiny', 'rmarkdown', 'knitr', 'htmltools'), repos='https://cloud.r-project.org')"
Shiny Server herunterladen und installieren. Für die aktuellste Version die Download-Seite von Posit prüfen:
wget https://download3.rstudio.org/centos8/x86_64/shiny-server-1.5.23.1030-x86_64.rpm
dnf --assumeyes localinstall shiny-server-1.5.23.1030-x86_64.rpm
systemctl enable --now shiny-server
systemctl status shiny-server
Die Installation landet unter /opt/shiny-server; /srv/shiny-server ist ein Symlink darauf und soll als Site-Root dienen (Default-Config-Wert site_dir /srv/shiny-server). Beispiel-Apps liegen unter /srv/shiny-server/sample-apps/.
Erreichbar ist der Server danach auf http://<host>:3838/, die Beispiel-Apps unter http://<host>:3838/sample-apps/hello/ und http://<host>:3838/sample-apps/rmd/.
Bemerkung
Posit liefert keinen offiziellen Shiny-Server-Build für RHEL 9 oder 10. Wer auf eine neuere RHEL-Generation muss, hat drei Optionen: einen eigenen Build aus dem rstudio/shiny-server-Repo, den Betrieb im Container (z.B. über das offizielle Rocker-Image), oder die Umstellung auf Posit Connect bzw. shiny::runApp() hinter einem Reverse Proxy.
Basiskonfiguration¶
# Run applications as the user "shiny"
run_as shiny;
# Server listening on port 3838
server {
listen 3838;
location / {
site_dir /srv/shiny-server;
log_dir /var/log/shiny-server;
directory_index on;
}
}
Nach jeder Änderung an der Konfiguration:
systemctl restart shiny-server
Einfache Shiny-Anwendung¶
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')
})
})
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 über Apache Reverse Proxy¶
Shiny Server Open Source hat keine eingebaute Benutzer-Authentifizierung. Wer mehrere Apps mit unterschiedlichen Zugriffsrechten auf demselben Host betreibt, hat mehrere Optionen:
Separate Shiny-Server-Instanzen auf unterschiedlichen Ports oder IPs, je mit eigenem Reverse-Proxy-Vhost.
Je eine App pro Container.
Je eine VM pro Mandant.
Oder - die einfachste Variante - ein einzelner Shiny Server, der nur auf
127.0.0.1lauscht, und davor ein Apache, der je Mandant einen VirtualHost mit Basic Auth und Proxy auf die passende Location bereitstellt.
Die letzte Variante im Detail: zwei Apps (hello und rmd), zwei Hostnames (shiny-hello.example.com und shiny-rmd.example.com), je eine .htpasswd-Datei pro Mandant.
Shiny-Server-Konfiguration - zwei getrennte Applikationen, nur lokal lauschend:
run_as shiny;
preserve_logs true;
# listen locally only; Apache in front does the rest
server {
listen 3838 127.0.0.1;
location /hello {
app_dir /srv/shiny-server/sample-apps/hello;
log_dir /var/log/shiny-server/hello;
}
location /rmd {
app_dir /srv/shiny-server/sample-apps/rmd;
log_dir /var/log/shiny-server/rmd;
}
}
Apache-VirtualHost für die App hello - die relevanten Teile:
<VirtualHost *:80>
ServerName shiny-hello.example.com
# Longer timeout so WebSocket connections don't drop after 10s
Timeout 60
# proxy_module
ProxyPreserveHost On
# rewrite_module
RewriteEngine On
# Restrict allowed HTTP methods
RewriteCond %{REQUEST_METHOD} !^(GET|OPTIONS)
RewriteRule .* - [redirect=405,last]
<Location />
AuthType Basic
AuthName "Shiny App hello"
AuthUserFile /etc/httpd/.htpasswd-hello
Require valid-user
</Location>
# Upgrade WebSocket requests to ws://, everything else plain http://
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>
.htpasswd-Datei je Mandant anlegen:
htpasswd -c /etc/httpd/.htpasswd-hello firstname.lastname
Monitoring¶
Sinnvolle Checks für einen Shiny-Server-Host:
systemd-Unit
shiny-server.service.TCP-Port 3838 (bzw. die im Vhost konfigurierten).
HTTP-Response je Haupt-App (
200, Response-Time).
Backup und Restore¶
Sichern:
/etc/shiny-server/: Server-Konfiguration./srv/shiny-server/: App-Code (wenn die Apps nicht ohnehin in Git liegen)./var/log/shiny-server/nur, wenn die App-Logs für eine Revision oder ein Audit wichtig sind.
Zum Restore Shiny Server neu installieren, Pakete und R-Module wieder einrichten, danach die Verzeichnisse zurückspielen.
Troubleshooting¶
- App startet nicht, Fehler nur im Browser sichtbar
Default-mässig sind die Server-Logs in
/var/log/shiny-server/pro App-Session durchgeschrieben, werden aber nach erfolgreichem App-Start gelöscht. Für die Fehlersuchepreserve_logs true;inshiny-server.confsetzen und den Dienst neu laden; ab dann bleiben die Logs liegen.- App-Log zeigt
there is no package called '...' Das R-Paket ist im System-R nicht installiert oder liegt in einer Library, die der
shiny-User nicht lesen kann. Mitsudo --user=shiny R --quiet -e ".libPaths()"prüfen, welche Library-Pfade der Server-User wirklich sieht, und das fehlende Paket dort installieren.- App hängt im „greying out“-Zustand nach kurzer Zeit
WebSocket-Verbindung wurde abgeschnitten, typischerweise durch einen zu niedrigen
Timeoutim Reverse Proxy oder eine zwischengeschaltete Firewall. Apache-Vhost mitTimeout 60oder höher konfigurieren.- App lokal auf dem Server starten, um Shiny-Server aus der Gleichung zu nehmen
Reproduziert das Problem auch ohne Shiny Server, liegt es in der App selbst:
sudo --user=shiny R --quiet -e "shiny::runApp('/opt/shiny-server/samples/sample-apps/hello')"
- Logs unter
/var/log/shiny-server/aufräumen Rotation über
logrotateregeln. Die Datei/etc/logrotate.d/shiny-serverwird vom Paket mitgeliefert; einzelne Log-Dateien lassen sich mittruncate --size=0 /var/log/shiny-server/<datei>.logleeren, ohne dass der Dienst die Handles verliert. Vom pauschalenrm -rf /var/log/shiny-server/*ist abzusehen - der Dienst schreibt dann teils ins Leere, bis er neu gestartet wurde, und die Mount-Point-Permissions können verlorengehen.