How to Make Shinyapp to Use Environmental Variables When Deployed on the Web

How can I make ShinyApp to use environmental variables when deployed on the web?

Finally figured out the solution!! basically I was supposed to load my workspace at the top of the UI.R file. This way:

attach("myWorkspace.RData")

Passing environmental variables to shinyapps.io

As Bill Ash suggests in the comments, using readRenviron() at the beginning of the script worked for me:

---
title: "Test"
runtime: shiny
output: html_document
---

```{r}
readRenviron(".Renviron")
print(Sys.getenv("QUANDL_API_KEY"))
```

How to pass environment variables to shinyapps

You can use Renviron.site or .Renviron to store and access private data into your shiny application. (see here for Hadley Wickham's recommendations and instructions - ref example below).


Solution:

Storing API Authentication Keys/Tokens (Attribution: Hadley Wickham)

If your package supports an authentication workflow based on an API key or token, encourage users to store it in an environment variable. We illustrate this using the github R package, which wraps the Github v3 API. Tailor this template to your API + package and include in README.md or a vignette.

  1. Create a personal access token in the Personal access tokens area of
    your GitHub personal settings. Copy token to the clipboard.
  2. Identify your home directory. Not sure? Enter normalizePath("~/") in the R
    console.
  3. Create a new text file. If in RStudio, do File > New File >
    Text file.
  4. Create a line like this:

    GITHUB_PAT=blahblahblahblahblahblah

where the name GITHUB_PAT reminds you which API this is for and blahblahblahblahblahblah is your personal access token, pasted from the clipboard.

  1. Make sure the last line in the file is empty (if it isn’t R will silently fail to load the file. If you’re using an editor that shows line numbers, there should be two lines, where the second one is empty.

  2. Save in your home directory with the filename .Renviron. If questioned,
    YES you do want to use a filename that begins with a dot ..

    • Note that by default dotfiles are usually hidden. But within RStudio, the file browser will make .Renviron visible and therefore easy to edit in the future.
  3. Restart R. .Renviron is processed only at the start of an R session.

  4. Use Sys.getenv() to access your token. For example, here’s how to use your GITHUB_PAT with the github package:

    library(github)
    ctx <- create.github.context(access_token = Sys.getenv("GITHUB_PAT"))
    # ... proceed to use other package functions to open issues, etc.

FAQ: Why define this environment variable via .Renviron instead of in .bash_profile or .bashrc?

Because there are many combinations of OS and ways of running R where the .Renviron approach “just works” and the bash stuff does not. When R is a child process of, say, Emacs or RStudio, you can’t always count on environment variables being passed to R. Put them in an R-specific start-up file and save yourself some grief.

Where to place .Renviron file when deploying shiny app with shinyproxy?

There are multiple options:

Put .Renviron file to the expected location inside the container

You can add a COPY command to the Dockefile to copy your .Renviron file to the expected location - i.e. either a home directory of the user or the WORKDIR location if defined in the Dockerfile. In case of the root user it would be:

COPY .Renviron /root/

Add environment variables from .Renviron to the Dockerfile

Add lines like:

ENV VAR1="value1"
ENV VAR2="value2"

to your Dockerfile

Add environment variables from .Renviron to the shinyproxy configuration

You can define environment variables in the application.yaml configuration file by either using

container-env:
VAR1: VALUE1
VAR2: VALUE2

or

container-env-file: /path/to/.Renviron

for your app specification. Note that the path here is on the host and not inside the container.

For docker run

When you do a docker run outside of shinyproxy you can use argument --env-file with something like:

docker run -it -p 3838:3838 shinyproxy-template --env-file /path/to/shinyproxy-template/.Renviron

Releant documentation links:

  • https://www.shinyproxy.io/documentation/configuration/#apps
  • https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file

Hide Keys in Shiny Application Deploy

I recommend the following solution and the reasons behind it:

Firstly, create a file named .Renviron (just create it with a text editor like the one on RStudio). Since that file has a dot before the name, the file will be hidden (in Mac/Linux for example). Type the following:

AWS_ACCESS_KEY_ID = "your_access_key_id"
AWS_SECRET_ACCESS_KEY = "you_secret_access_key"
AWS_DEFAULT_REGION = "us-east-2"

Secondly, if you are using .git it is advisable to add the following text in your gitignore file (so to avoid to share that file for version control):

# R Environment Variables
.Renviron

Finally you can retrieve the values stored in .Renviron to connect to your databases, S3 buckets and so on:

library(aws.s3)
bucketlist(key = Sys.getenv("AWS_ACCESS_KEY_ID"),
secret = Sys.getenv("AWS_SECRET_ACCESS_KEY"))

In that way your keys will be "obscured" and will be retrieved by the function Sys.getenv from .Renviron so you can protect your code.

Star shiny app in the background and use values of global environment

In my answer to your previous question, I gave a way to pass the working directory to the app, using options and getOption. You can apply the same technique:

launch_app <- function(fileName) {
options(filename = fileName, wd = getwd())
appDir <- system.file("myapp", package = "covid")
shiny::runApp(appDir, display.mode = "normal")
}

and in the app:

server <-  function(input, output, session){
wd <- getOption("wd")
fileName <- getOption("filename")
......

Problems with deployment of shiny app due to reticulate_python

This is actually a fairly annoying problem with running software locally and running in another environment and I'd say solutions are generally non-obvious. You probably aren't the first person to run into this.

Here are some facts that I think are relevant:

  • reticulate needs to know where your Python executable is on the computer
  • The locatl of the Python executable differs between your computer and the virtual computer shinyapps.io runs your Shiny app from
  • reticulate seems to determine where your Python executable is from the RETICULATE_PYTHON environment variable but also has some default behavior when the variable isn't set
  • The Python executable on your computer is at a different location than the executable on the virtual computer shinyapps.io runs your Shiny app from
  • When you set the value of RETICULATE_PYTHON in your .Rprofile to the value shinyapps.io needs, your setup breaks because your Python environment is different

I haven't tested this as a solution but I think the fix is actually in your link! Check out https://github.com/ranikay/shiny-reticulate-app/blob/master/.Rprofile and see how they include a bit more than just a simple assignment of a value to RETICULATE_PYTHON and actually use conditional statements to set various values depending on the result of (Sys.info()[['user']].

The value of (Sys.info()[['user']] will differ based upon whether R executes .Rprofile on your local computer versus the virtual computer shinyapps.io runs your Shiny app on and the linked .Rprofile is doing the work of setting up various values based upon whether R is running on your local computer or on another computer. This all works because shinyapps.io

From the code in the .Rprofile, I can tell that shinyapps.io runs your Shiny app under the user named "shiny",

if (Sys.info()[['user']] == 'shiny'){
Sys.setenv(RETICULATE_PYTHON = paste0('/home/shiny/.virtualenvs/', VIRTUALENV_NAME, '/bin/python'))
}

and they even add a conditional block in their to support RStudio Connect, which apparently runs your Shiny apps under the user named rstudio-connect instead of "shiny":

} else if (Sys.info()[['user']] == 'rstudio-connect'){
Sys.setenv(RETICULATE_PYTHON = paste0(VIRTUALENV_NAME, '/bin/python'))
}

Lastly, the .Rprofile uses an else statement to catch any other case and this will match the case when you're running on your own computer:

} else {
# RETICULATE_PYTHON is not required locally, RStudio infers it based on the ~/.virtualenvs path

From what you've described above and what I see at the linked tutorial, I think you could nearly copy the entire .Rprofile they have there into your project and, with maybe only a minor modification or two, you should be able to get your Shiny app running locally and on shinyapps.io with reticulate.

However, we see that not setting RETICULATE_PYTHON defers to behavior defined by running a virtualenv so I might recommend setting RETICULATE_PYTHON here to a value such as the location or your miniconda-based Python executable. I'm guessing that value might be ./Library/r-miniconda/envs/r-reticulate/bin/python3 or similar.

If you don't want to copy the linked .Rprofile and modify it as you need, you might just change yours to only contain this line:

if (Sys.info()[['user']] == 'shiny'){
Sys.setenv(RETICULATE_PYTHON = "/usr/local/bin/python3")
}

And then try running locally and deploying.

This pattern of setting environment variables differently based upon the environment a program is running under is actually a fairly widely-accepted best practice in software engineering [1] so it's a pattern that may serve you in the future as you build applications locally and deploy to other environments.

[1] https://12factor.net

How do I securely add an api key to a dockerized Shiny App?

Configure environment variable for the container:

docker run -d \
-e API_KEY=<api-key> \
...
shiny-app-image

And use it in R:

Sys.getenv("API_KEY")

So variable API_KEY will be defined on the container level, not in the Docker image.



Related Topics



Leave a reply



Submit