19 Appendix: Programmatic Deployment with rsconnect

19.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:

  1. administrator privileges for Connect, and
  2. sudo or root privileges on the server where Connect is installed.

19.2 Use Case: A Shiny Application

Here we present a use case that explains how to configure Connect for programmatic deployment. Please see 19.4 for an example Shiny application for this use case.

19.2.1 Use Case Scenario

Bob White develops a Shiny application (see 19.4) that:

  1. Renders an R Markdown document.
  2. 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.

19.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")

19.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 10.3 for configuring the RunAs user on a per-application basis in Connect.

19.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

19.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.

19.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")

19.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.

19.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)