Skip to content

❗ This is a read-only mirror of the CRAN R package repository. tinyshinyserver — Tiny 'shiny' Server - Lightweight Multi-App 'shiny' Proxy. Homepage: https://github.com/lab1702/tinyshinyserver Report bugs for this package: https://github.com/lab1702/tinyshinyserver/issues

License

Notifications You must be signed in to change notification settings

cran/tinyshinyserver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tinyshinyserver

R Package License: MIT Platform

A lightweight, WebSocket-enabled proxy server for hosting multiple Shiny applications with automatic health monitoring, session management, and resource cleanup.

🎯 Perfect for:

  • Hosting multiple Shiny apps behind a single server
  • Development environments with multiple projects
  • Small-scale production deployments
  • R Markdown and Quarto dashboard hosting

Installation

From GitHub

# Install from GitHub
remotes::install_github("lab1702/tinyshinyserver")

From Source

# Clone and install locally
git clone https://github.com/lab1702/tinyshinyserver.git
cd tinyshinyserver
Rscript -e "devtools::install('.')"

Prerequisites

  • R (≥ 4.0)
  • Pandoc (for R Markdown apps)
  • Quarto CLI (optional, for Quarto dashboards)

The package automatically installs required R dependencies:

Core: shiny, callr, jsonlite, later, httr, digest, httpuv, websocket, openssl Async: future Docs: rmarkdown, quarto Utils: logger

Optional (for examples): DT, plotly, dplyr, flexdashboard

🚀 Quick Start

1. Load

# Load the package
library(tinyshinyserver)

2. Get Example Apps

# Copy included example apps to your directory
examples_path <- system.file("examples", package = "tinyshinyserver")
file.copy(examples_path, ".", recursive = TRUE)

3. Start the Server

# Start with the example configuration
start_tss(config = "examples/config.json")

4. Access Your Server

🌐 Main Interface: http://localhost:3838
⚙️ Management Dashboard: http://localhost:3839
📱 Individual Apps: http://localhost:3838/proxy/{app_name}/

5. Get Help

# Package overview and getting started
?tinyshinyserver

# Main function help
?start_tss

# Configuration format reference
?config-format

Features

  • Multi-App Hosting: Host multiple Shiny applications on different ports behind a single proxy
  • Resident & On-Demand Apps: Choose between always-running apps for immediate access or on-demand apps that start when accessed and stop immediately when unused
  • WebSocket Support: Full WebSocket proxy with session affinity for real-time Shiny apps
  • Real-time Status Updates: Landing page shows live app status and connection counts with auto-refresh
  • Management Interface: Professional web-based dashboard for monitoring and controlling all applications
  • Real-time Monitoring: Live connection tracking with IP addresses and user agents
  • Individual App Control: Restart specific applications without affecting others
  • Health Monitoring: Automatic health checks with app restart on failure
  • Memory Management: Built-in connection cleanup and resource management
  • Startup Reliability: Intelligent port availability checking with retry logic for slow-starting applications
  • Graceful Shutdown: Multiple shutdown options including web-based controls
  • Dark Mode Support: Automatic theme detection for better user experience
  • R Markdown Support: Native support for interactive R Markdown documents with runtime: shiny
  • Quarto Support: Full support for interactive Quarto dashboards with server: shiny
  • Binary Asset Support: Handles images, fonts, and other binary files correctly
  • Comprehensive Logging: Structured logging with per-app log files

📋 Configuration

The server uses a JSON configuration file. Here's a minimal example:

{
  "apps": [
    {
      "name": "sales",
      "path": "./examples/sales",
      "resident": true
    }
  ],
  "starting_port": 3001,
  "proxy_port": 3838,
  "proxy_host": "127.0.0.1",
  "management_port": 3839,
  "log_dir": "./logs"
}

📖 See ?config-format for complete configuration reference

🛑 Stopping the Server

Recommended: Use the management interface at http://localhost:3839 and click "Shutdown Server".

Alternative methods:

  • Press Ctrl-C in the R console
  • API call: curl -X POST http://localhost:3839/api/shutdown

Graceful shutdown closes all connections and cleans up resources.

📦 Included Examples

The package includes four example applications:

App Type Description
sales Single-file Shiny Simple dashboard with sample data
inventory Multi-file Shiny Interactive tables (ui.R + server.R)
reports R Markdown Flexdashboard with runtime: shiny
dashboard Quarto Modern dashboard with server: shiny

Example configuration (from examples/config.json):

{
  "apps": [
    {
      "name": "sales",
      "path": "./examples/sales",
      "resident": true
    },
    {
      "name": "inventory", 
      "path": "./examples/inventory"
    },
    {
      "name": "reports",
      "path": "./examples/reports",
      "resident": false
    },
    {
      "name": "dashboard",
      "path": "./examples/dashboard",
      "resident": true
    }
  ],
  "starting_port": 3001,
  "proxy_port": 3838,
  "management_port": 3839,
  "log_dir": "./logs"
}

⚡ Auto Port Assignment

Apps are automatically assigned ports starting from starting_port:

  • sales → port 3001
  • inventory → port 3002
  • reports → port 3003
  • dashboard → port 3004

The system skips reserved ports (proxy_port, management_port) automatically.

🔄 Resident vs On-Demand Apps

The server supports two application life cycle modes controlled by the resident configuration option:

Resident Apps ("resident": true)

  • Always Running: Started when the server starts and keep running continuously
  • Immediate Response: No startup delay when users access the app
  • Higher Resource Usage: Consumes memory and CPU even when unused
  • Best For: Frequently accessed apps, apps with long startup times, production apps requiring immediate availability

On-Demand Apps ("resident": false, default)

  • Start on Access: Only started when a user first accesses the app (HTTP request or WebSocket connection)
  • Immediate Shutdown: Stopped immediately when the last connection closes
  • Resource Efficient: Only consumes resources when actively being used
  • Startup Delay: Users may experience a brief delay on first access while the app starts
  • Best For: Infrequently used apps, development/testing environments, resource-constrained servers

Status Indicators

  • Resident apps: Show as "running" (green) or "stopped" (red) in the management interface
  • On-demand apps: Show as "dormant" (blue) when stopped normally, "running" (green) when active

Example Configuration:

{
  "apps": [
    {
      "name": "critical-dashboard",
      "path": "./apps/dashboard",
      "resident": true  // Always running for immediate access
    },
    {
      "name": "occasional-report",
      "path": "./apps/reports",
      "resident": false  // Starts only when needed
    },
    {
      "name": "dev-prototype",
      "path": "./apps/prototype"
      // "resident" defaults to false
    }
  ]
}

Configuration Options

Option Description Default
apps Array of Shiny applications to host Required
apps[].name Application identifier for URLs Required
apps[].path Relative path to app directory Required
apps[].resident Keep app running continuously (true) or start on-demand (false) false
starting_port Starting port for auto-assignment Required
log_dir Directory for log files Required
proxy_port Port for the proxy server 3838
proxy_host Host interface for proxy server (localhost, 127.0.0.1, 0.0.0.0, ::1, ::) "127.0.0.1"
management_port Port for the management interface 3839
restart_delay Seconds to wait before restarting failed apps 5
health_check_interval Seconds between health checks 10

Network Configuration

The proxy_host option controls which network interface the proxy server binds to:

  • "localhost" or "127.0.0.1" - Binds to localhost only (default, most secure)
  • "0.0.0.0" - Binds to all network interfaces (allows external access)
  • "::1" - IPv6 localhost
  • "::" - All IPv6 interfaces

⚠️ Security Note: Using "0.0.0.0" makes the server accessible from external networks. Only use this if you understand the security implications and have proper firewall rules in place.

SSL and Authentication with Caddy

For production deployments requiring SSL/TLS and authentication, Caddy Server provides a simple solution:

# Caddyfile
myapp.example.com {
    reverse_proxy localhost:3838
    basicauth {
        username password_hash
    }
}

manage.myapp.example.com {
    reverse_proxy localhost:3839
    basicauth {
        admin admin_password_hash
    }
}

This configuration automatically handles SSL certificates via Let's Encrypt and adds HTTP basic authentication.

Important: When using Caddy, keep proxy_host set to "localhost" or "127.0.0.1" in your config.json to ensure the server only accepts connections from Caddy, not directly from external clients.

Landing Page

The landing page at http://localhost:3838 provides an overview of all hosted applications with real-time status information.

Features

Real-time Status Display

  • Live Status Badges: Visual indicators showing if each app is running, dormant, stopped, or crashed
  • Connection Counts: Real-time display of active connections per application
  • Auto-refresh: Status updates automatically every 5 seconds
  • Color-coded Indicators: Green for running, blue for dormant, red for stopped, yellow for crashed apps
  • Connection Status: Shows server connectivity with automatic timeout detection

Application Access

  • Smart Clickable Tiles: App accessibility based on status
    • Running apps: Immediately clickable ("Click to open [app name]")
    • Dormant apps: Clickable for on-demand starting ("Click to start and open [app name]")
    • Stopped/Crashed apps: Disabled with helpful tooltips explaining next steps
    • Server down: All tiles disabled when server is unreachable
  • Visual Feedback: Disabled apps are dimmed with "not-allowed" cursor
  • Clean Interface: Modern, responsive design that works on all devices
  • Dark Mode Support: Automatically adapts to your system's theme preference

Server Information

  • System Details: Display of R version, platform, and server configuration
  • Session Info: Technical details about the running R environment

The landing page uses the same status API as the management interface, ensuring consistency between all monitoring views.

Management Interface

The management interface provides a professional web-based dashboard for monitoring and controlling your Shiny server.

Accessing the Management Interface

Visit http://localhost:3839 to access the management dashboard.

🔒 Security: The management interface is restricted to localhost only for security.

Features

System Overview

  • Total applications count
  • Running applications count
  • Active connections count
  • Real-time auto-refresh (every 5 seconds)

Application Management

  • Enhanced Status Monitoring: See if each app is running, dormant, stopped, or crashed
  • App Type Display: Shows whether apps are "Resident" (always-on) or "On-Demand"
  • Connection Counts: View active connections per application
  • Process Information: See process IDs and ports for each app
  • Smart Restart Controls:
    • Running/Stopped/Crashed apps: Show restart button
    • Dormant apps: No restart button (start automatically on access)
    • Helpful messages: "This app will start automatically when accessed"
  • Resource Details: Monitor app paths and configuration

Connection Tracking

  • Real-time Connections: See all active WebSocket connections
  • Client Information: IP addresses and user agents
  • Session Details: Connection timestamps, duration, and last activity
  • Browser Detection: Identify client browsers and operating systems

Server Controls

  • Graceful Shutdown: Shutdown the entire server with confirmation dialog
  • Safety Features: Multiple confirmation prompts prevent accidental shutdowns
  • Clean Termination: Properly closes all connections and terminates all processes

Management API

The management interface exposes a REST API for programmatic access:

Endpoint Method Description
/api/status GET System overview (apps, connections)
/api/apps GET Detailed application status
/api/connections GET Active connection details
/api/apps/{name}/restart POST Restart specific application
/api/shutdown POST Graceful server shutdown

Example usage:

# Get system status
curl http://localhost:3839/api/status

# Restart the sales app
curl -X POST http://localhost:3839/api/apps/sales/restart

# Shutdown server
curl -X POST http://localhost:3839/api/shutdown

Dark Mode Support

The management interface automatically adapts to your system's theme preference:

  • Light Mode: Clean, professional appearance for daytime use
  • Dark Mode: Comfortable viewing for low-light environments
  • Automatic Detection: Uses CSS prefers-color-scheme media query

Application Structure

Standard Shiny App

apps/myapp/
├── app.R          # Single-file Shiny app
└── [other files]

Multi-file Shiny App

apps/myapp/
├── ui.R           # UI definition
├── server.R       # Server logic
└── [other files]

R Markdown App

apps/myapp/
├── report.Rmd     # R Markdown with runtime: shiny
└── [other files]

Quarto App

apps/myapp/
├── dashboard.qmd  # Quarto document with server: shiny
└── [other files]

Example Applications

The project includes four example applications demonstrating different application types:

1. Sales Dashboard (examples/sales/)

  • Single-file Shiny app demonstrating basic dashboard
  • Simple plot with sample sales data

2. Inventory Management (examples/inventory/)

  • Multi-file Shiny app (ui.R + server.R)
  • Interactive table with dynamic data generation

3. Business Reports (examples/reports/)

  • R Markdown flexdashboard with runtime: shiny
  • Interactive charts, KPIs, and data tables
  • Demonstrates plotly integration and responsive design

4. Interactive Dashboard (examples/dashboard/)

  • Quarto dashboard with server: shiny
  • Professional dashboard layout with sidebar controls
  • Real-time filtering, interactive plots, and data tables
  • Demonstrates modern dashboard design with format: dashboard

Memory Management

The server includes automatic memory management features:

  • Connection Cleanup: Removes stale connections after 30 minutes of inactivity
  • Queue Limits: Limits pending message queues to 100 messages per connection
  • Process Cleanup: Removes dead process objects from memory
  • File Handle Management: Ensures proper cleanup of log file handles

Cleanup runs automatically every 5 minutes and logs activity for monitoring.

Logging

Log Files

  • logs/server.log - Main server logs
  • logs/{app_name}_output.log - Per-app stdout logs
  • logs/{app_name}_error.log - Per-app stderr logs

Log Levels

  • INFO - Normal operations
  • WARN - Warning conditions (e.g., queue limits reached)
  • ERROR - Error conditions requiring attention

Development

Running Individual Apps

For development, you can run apps directly:

# Standard Shiny app
R -e "shiny::runApp('apps/sales', port = 3001)"

# R Markdown app
R -e "rmarkdown::run('apps/reports/report.Rmd', shiny_args = list(port = 3003, host = '127.0.0.1'))"

# Quarto app
R -e "quarto::quarto_serve('apps/dashboard/dashboard.qmd', port = 3004, host = '127.0.0.1')"

Adding New Applications

  1. Create your app in apps/{app_name}/
  2. Add configuration entry to config.json (only name and path required)
  3. Restart the server

The server will automatically assign the next available port to your new application.

Health Endpoints

Proxy Server:

  • Health check: GET /health - Returns {"status": "healthy"}
  • Apps status: GET /api/apps - Returns detailed application status (used by landing page)

Management Interface:

  • System status: GET /api/status - Returns overall system health
  • Apps status: GET /api/apps - Returns detailed application status
  • Connections: GET /api/connections - Returns active connection details

📁 Package Structure

tinyshinyserver/
├── R/                    # R source code
│   ├── start_tss.R       # Main exported function
│   ├── config.R          # Configuration management
│   ├── handlers.R        # HTTP request routing
│   ├── process_manager.R # Application lifecycle
│   └── ...              # Other core modules
├── inst/
│   ├── examples/         # Example apps & config
│   │   ├── sales/        # Simple Shiny app
│   │   ├── inventory/    # Multi-file Shiny app
│   │   ├── reports/      # R Markdown dashboard
│   │   ├── dashboard/    # Quarto dashboard
│   │   └── config.json   # Example configuration
│   └── templates/        # HTML templates & CSS
├── man/                  # Documentation (.Rd files)
├── DESCRIPTION           # Package metadata
└── NAMESPACE            # Exported functions

Architecture

The server uses a multi-process architecture:

                    ┌─────────────────────┐
                    │  Management Server  │
                    │    (Port 3839)      │
                    │                     │
                    │  • System Status    │
                    │  • App Control      │
                    │  • Connection Info  │
                    │  • Graceful Shutdown│
                    └─────────────────────┘
                    
┌─────────────────────┐
│   Proxy Server      │
│   (Port 3838)       │
│                     │
│  ┌─WebSocket────────┤
│  │  Handler         │
│  │                  │
│  │  ┌─HTTP──────────┤
│  │  │  Handler      │
└──┼──┼───────────────┘
   │  │
   │  └── HTTP Requests ──┐
   │                      │
   └── WebSocket ─────────┼───┐
       Messages           │   │
                          ▼   ▼
              ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
              │ Sales    │ │Inventory │ │ Reports  │ │Dashboard │
              │(Port     │ │(Port     │ │(Port     │ │(Port     │
              │ 3001)    │ │ 3002)    │ │ 3003)    │ │ 3004)    │
              └──────────┘ └──────────┘ └──────────┘ └──────────┘

Key Components

  • Management Server: Web-based monitoring and control interface
  • HTTP Handler: Routes requests to appropriate backend apps
  • WebSocket Handler: Manages real-time connections with session affinity
  • Process Manager: Monitors and restarts failed applications
  • Memory Manager: Cleans up stale connections and resources
  • Connection Tracker: Records client information and session details

🔧 Troubleshooting

Common Issues

Apps won't start
  • Check that the app directory exists and contains valid Shiny code
  • Verify ports aren't already in use: netstat -an | findstr :3838
  • Check app-specific error logs in logs/{app_name}_error.log
  • Use ?start_tss for configuration help
WebSocket connection failures
  • Ensure backend app is running and healthy
  • Check for firewall issues blocking WebSocket connections
  • Verify session affinity is working correctly
  • Monitor logs for WebSocket connection messages
Management interface not accessible
  • Verify server is running: check R console output
  • Access via http://localhost:3839 (not external IP)
  • Ensure no firewall is blocking localhost connections
  • Check logs for management server startup messages

🔍 Debug Mode

# Check server logs (created after starting)
list.files("logs", pattern = "\\.(log|txt)$")

# Monitor main server log
tail -f logs/server.log  # Linux/macOS
Get-Content logs/server.log -Wait  # PowerShell

🔒 Security Considerations

⚠️ Important: This server is designed for development and internal use.

For production deployment, consider:

  • Adding authentication (see Caddy reverse proxy example)
  • SSL/TLS encryption for external access
  • Firewall rules and network segmentation
  • Regular security updates
  • Rate limiting on management endpoints

Built-in security features:

  • Management interface restricted to localhost only
  • Input validation for configuration files
  • Process isolation between applications

🤝 Contributing

Contributions are welcome! Please see our contribution guidelines:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes and add tests
  4. Test thoroughly: devtools::check()
  5. Submit a pull request

Development Setup

# Clone and setup for development
git clone https://github.com/lab1702/tinyshinyserver.git
cd tinyshinyserver

# Install with dependencies
devtools::install_deps()
devtools::load_all()

# Run checks
devtools::check()

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

  • 📖 Documentation: Use ?tinyshinyserver, ?start_tss, ?config-format
  • 🐛 Bug Reports: GitHub Issues

Built with ❤️ for the R and Shiny community

About

❗ This is a read-only mirror of the CRAN R package repository. tinyshinyserver — Tiny 'shiny' Server - Lightweight Multi-App 'shiny' Proxy. Homepage: https://github.com/lab1702/tinyshinyserver Report bugs for this package: https://github.com/lab1702/tinyshinyserver/issues

Resources

License

Stars

Watchers

Forks

Packages

No packages published