G Programmatic Deployment with rsconnect
G.1 Overview
It is possible to use the rsconnect
R package to programmatically deploy content to a Connect server. Furthermore, Connect-hosted content can use rsconnect
to deploy additional content to itself or to another Connect server.
Configuring Connect to deploy content with rsconnect
requires:
- administrator privileges for Connect, and
- sudo or root privileges on the server where Connect is installed.
G.2 Use Case: A Shiny Application
Here we present a use case that explains how to configure Connect for programmatic deployment. Please see G.4 for an example Shiny application for this use case.
G.2.1 Use Case Scenario
Bob White develops a Shiny application (see G.4) that:
- Renders an R Markdown document.
- Deploys the generated document using
rsconnect
Bob deploys his Shiny application to Connect. The application, as noted above, can automatically deploy documents it generates to Connect. However, the Connect server must first be configured to authorize deployment from rsconnect
.
G.2.2 Installing rsconnect
The rsconnect
package is not yet available on Bob’s Connect server, so Bob installs it by running R as root (sudo R
) and issuing the following command in the R console. In practice, rsconnect
may already be available.
install.packages("rsconnect")
G.2.3 Configuring a Custom “RunAs” User
Since Bob does not want to allow arbitrary Connect users to deploy content using rsconnect
, he configures a custom RunAs
user, robert
, for his Shiny application. See Section 12.5 for configuring the RunAs
user on a per-application basis in Connect.
G.2.4 Configuring rsconnect
Important Note: rsconnect
configuration requires a user home directory. In this use case, a valid home directory is required for the robert
user account.
Since Bob’s Shiny application will be running as the robert
user, Bob (at a server console) switches to the robert
user:
sudo su robert
Next, while running as robert
, Bob runs R
and issues the following commands in the R console:
library(rsconnect)
rsconnect::addConnectServer('http://myserveraddress:3939', 'mylocaldeployserver')
rsconnect::connectUser(server='mylocaldeployserver')
NOTE: the rsconnect server name,
mylocaldeployserver
, is an arbitrary name that is used to identify a Connect server when using rsconnect. You can choose any name you wish.
After the last command, Bob sees the following output:
A browser window should open; if it doesn’t, you may authenticate manually by visiting http://myserveraddress:3939/__login__?url=http%3A%2F%2Fmyserveraddress%3A3939%2Fconnect%2F%23%2Ftokens%2FTc8f636c59ffff521eef4888b163dcf64%2Factivate&user_id=0.
Waiting for authentication…
Bob copies the URL in the output above and pastes it into a Web browser. Then Bob authenticates with his Connect user credentials. Bob’s Connect user name (with publishing privileges) is rwhite
.
After successfully connecting his Connect account to rsconnect
, Bob sees this message at the R console:
Account registered successfully: Bob White (rwhite)
The server and account information are persisted to configuration files on the server in Bob’s home directory:
/home/robert/.config/R/connect/servers/mylocaldeployserver.dcf
/home/robert/.config/R/connect/accounts/mylocaldeployserver/connectuser.dcf
G.2.5 Deploying Content with rsconnect
Now rsconnect
is configured to use the rwhite
Connect account when running with the robert
server account. If Bob’s Shiny application uses robert
as its RunAs
user, it can deploy content using rsconnect
.
G.2.6 CRAN Note
If you don’t already have it in an RProfile
, be sure to specify a default CRAN repository in your application before issuing the rsconnect
command to deploy content. For example:
options(repos=c(CRAN="https://cran.rstudio.com"))
rsconnect::deployDoc(doc="out.Rmd", appName="ServerDeployedDoc",
account="rwhite", server="mylocaldeployserver")
G.3 Warning and Security Information
Please restrict access to any Connect content that can deploy arbitrary content via rsconnect
. The Connect Dashboard’s “Permissions” document provides details on securing content in Connect.
Do not enable deployment via rsconnect
for the default Applications.RunAs
user; if you do so, all your Connect users will be able to deploy content using your rsconnect
credentials.
Once a Connect user authorizes rsconnect
to deploy content under a particular server account, any content that runs under that server account can use rsconnect
to deploy content without further authentication.
For example, Bob logs in to a server console as Unix user robert
. Bob then configures rsconnect
to deploy content. During the authorization step, Bob signs in to Connect as a publisher with user name rwhite
. Now, any Connect application that is configured with a RunAs
user of robert
can deploy additional content using the Connect user rwhite
, regardless of who owns the application.
G.4 Example Shiny Application
Below is an example Shiny application that knits R Markdown text and deploys the resulting content using rsconnect
.
library(knitr)
library(rsconnect)
library(shiny)
library(shinyAce)
library(rmarkdown)
# Default text for editor
defaultMarkdown <- '
### Sample R Markdown
This is some markdown text. It may also have embedded R code
which will be executed.
'
# A Shiny UI for editing R Markdown
ui <- shinyUI(
bootstrapPage(
headerPanel("Embedded Deployment Example"),
div(
class="container-fluid",
div(class="row-fluid",
div(class="col-sm-6",
h2("Source R-Markdown"),
aceEditor("rmd", mode="markdown", value=defaultMarkdown),
actionButton("eval", "Update")
),
div(class="col-sm-6",
h2("Knitted Output"),
htmlOutput("knitDoc")
)
)
)
)
)
# A Shiny application that generates and deploys R Markdown content
server <- shinyServer(function(input, output, session) {
# Only update and deploy when the 'Update' button is clicked
rmd <- eventReactive(input$eval, {
input$rmd
})
output$knitDoc <- renderUI({
writeLines(rmd(), "out.Rmd")
knit2html(input="out.Rmd", fragment.only = TRUE, quiet = TRUE)
options(repos=c(CRAN="https://cran.rstudio.com"))
rsconnect::deployDoc(doc="out.Rmd", appName="GeneratedDoc",
account="rwhite", server="mylocaldeployserver")
return(isolate(HTML(
readLines("out.html")
)))
})
})
# Run the application
shinyApp(ui = ui, server = server)