Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
shiny-server 1.5.24
--------------------------------------------------------------------------------

* Added `:PROCESS_USER:` token for the `run_as` directive, which resolves to the
user running the shiny-server process. This enables running without root.

* Added `Path` config type so that filesystem path directives (`site_dir`,
`app_dir`, `log_dir`, `bookmark_state_dir`, etc.) now resolve relative paths
to absolute at config parse time.

* Added `npm run dev` for local development. Starts the server on port 3838 with
sample R and Python apps, no root required.

shiny-server 1.5.23
--------------------------------------------------------------------------------

Expand Down
16 changes: 8 additions & 8 deletions config/shiny-server-rules.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ run_as {
desc "The user the app should be run as. This user should have the minimal amount of privileges necessary to successfully run the application (i.e. read-only access to the Shiny application directory). Note that this directive cannot be used with `user_apps`, as `user_apps` always run as the user who owns the application.";

# required parameter
param String users... "The username that should be used to run the app. If using home_dirs, this can also be the special keyword `:HOME_USER:` which will instruct `home_dirs` to run as the user in whose home directory the application exists. If using a special keyword like `:HOME_USER:`, you can specify additional usernames afterwards which will be used when this directive is applied to hosting models other than `home_dirs`.";
param String users... "The username that should be used to run the app. If using home_dirs, this can also be the special keyword `:HOME_USER:` which will instruct `home_dirs` to run as the user in whose home directory the application exists. The special keyword `:PROCESS_USER:` resolves to the user running the shiny-server process, useful for development without root privileges or for containerized environments where the server runs as a single non-root user. If using a special keyword like `:HOME_USER:`, you can specify additional usernames afterwards which will be used when this directive is applied to hosting models other than `home_dirs`.";

# List of parent node names that are valid for this directive ($ means root)
at $ server location;
Expand All @@ -15,14 +15,14 @@ run_as {

socket_dir {
desc "The path to the (empty) directory within which Shiny worker processes should create domain sockets. The directory should be owned by root with permissions set to `0333`. Defaults to `/var/shiny-server/sockets` if this directive is not present.";
param String path "The domain socket directory path (should be absolute).";
param Path path "The domain socket directory path (should be absolute).";
at $;
undocumented;
}

access_log {
desc "The file path of the HTTP access log.";
param String path "The file path where the access log should be written";
param Path path "The file path where the access log should be written";
param String [format] "The log file format; see [Connect documentation](http://www.senchalabs.org/connect/logger.html) under \"Formats\"" default;
at $;
}
Expand Down Expand Up @@ -57,7 +57,7 @@ location {

site_dir {
desc "Configures the enclosing location scope to be a website that can contain both Shiny applications and unrelated static assets in a single directory tree.";
param String rootPath "The path to the root directory of the website";
param Path rootPath "The path to the root directory of the website";
at location;
maxcount 1;
precludes user_apps app_dir redirect user_dirs;
Expand Down Expand Up @@ -88,7 +88,7 @@ user_dirs {

app_dir {
desc "Configures the enclosing location scope to serve up the specified Shiny application.";
param String path "The path to the Shiny application directory";
param Path path "The path to the Shiny application directory";
at location;
maxcount 1;
precludes redirect user_apps site_dir user_dirs;
Expand All @@ -108,7 +108,7 @@ redirect {

log_dir {
desc "Directs the application to write error logs to the specified directory. Only applies to location scopes that are configured with `app_dir` or `site_dir`, as `user_apps` (autouser) always writes error logs to `~/ShinyApps/log`. In addition, starting in v1.5.13 you can set the environment variable `SHINY_LOG_STDERR` to any non-empty value to instruct Shiny Server to emit stderr output from Shiny apps to the main process's own stderr.";
param String path "The path to which application log files should be written";
param Path path "The path to which application log files should be written";
at $ server location;
maxcount 1;
}
Expand Down Expand Up @@ -198,7 +198,7 @@ application {

template_dir {
desc "A directory containing custom templates to be used when generating pages in Shiny Server.";
param String dir "The directory containing HTML templates.";
param Path dir "The directory containing HTML templates.";
at $ server location;
maxcount 1;
}
Expand All @@ -212,7 +212,7 @@ python {

bookmark_state_dir {
desc "A directory for storing persisted application state. If Shiny Server is running without root privileges, then the `run_as` account must have read/write access to this directory. If no `bookmark_state_dir` directive is provided, `/var/lib/shiny-server/bookmarks` will be used.";
param String dir "The directory where bookmark data should be stored.";
param Path dir "The directory where bookmark data should be stored.";
at $ server location;
maxcount 1;
}
Expand Down
9 changes: 9 additions & 0 deletions dev/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Runtime artifacts -- do not commit
bookmarks/
log/
sockets/

# App runtime caches
**/app_cache/
**/__pycache__/
**/.venv/
1 change: 1 addition & 0 deletions dev/apps/py-hello/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
Empty file added dev/apps/py-hello/README.md
Empty file.
81 changes: 81 additions & 0 deletions dev/apps/py-hello/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import numpy as np
from shiny import App, reactive, render, ui

app_ui = ui.page_sidebar(
ui.sidebar(
ui.input_slider("n", "Number of points", min=10, max=500, value=100),
ui.input_select("dist", "Distribution", choices={
"norm": "Normal",
"unif": "Uniform",
"exp": "Exponential",
}),
ui.input_slider("bins", "Histogram bins", min=5, max=50, value=20),
),
ui.layout_columns(
ui.card(
ui.card_header("Histogram"),
ui.output_plot("hist"),
),
ui.card(
ui.card_header("Density Estimate"),
ui.output_plot("density"),
),
),
ui.card(
ui.card_header("Summary Statistics"),
ui.output_text_verbatim("summary"),
),
title="Shiny Server Dev Mode (Python)",
)


def server(input, output, session):
@reactive.calc
def data():
rng = np.random.default_rng()
if input.dist() == "norm":
return rng.standard_normal(input.n())
elif input.dist() == "unif":
return rng.uniform(size=input.n())
else:
return rng.exponential(size=input.n())

@render.plot
def hist():
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.hist(data(), bins=input.bins(), color="#2c7bb6", edgecolor="white")
ax.set_xlabel("Value")
return fig

@render.plot
def density():
from scipy.stats import gaussian_kde
import matplotlib.pyplot as plt

d = data()
kde = gaussian_kde(d)
x = np.linspace(d.min() - 0.5, d.max() + 0.5, 200)

fig, ax = plt.subplots()
ax.plot(x, kde(x), color="#d7191c", linewidth=2)
ax.fill_between(x, kde(x), alpha=0.2, color="#d7191c")
ax.set_xlabel("Value")
return fig

@render.text
def summary():
d = data()
return (
f"Min: {d.min():.4f}\n"
f"Q1: {np.percentile(d, 25):.4f}\n"
f"Median: {np.median(d):.4f}\n"
f"Mean: {d.mean():.4f}\n"
f"Q3: {np.percentile(d, 75):.4f}\n"
f"Max: {d.max():.4f}\n"
f"Std: {d.std():.4f}"
)


app = App(app_ui, server)
12 changes: 12 additions & 0 deletions dev/apps/py-hello/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[project]
name = "py-hello"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"matplotlib>=3.10.8",
"numpy>=2.4.4",
"scipy>=1.17.1",
"shiny>=1.6.0",
]
Loading
Loading