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.
- Create a personal access token in the Personal access tokens area of
your GitHub personal settings. Copy token to the clipboard. - Identify your home directory. Not sure? Enter normalizePath("~/") in the R
console. - Create a new text file. If in RStudio, do File > New File >
Text file. 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.
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.
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.
Restart R. .Renviron is processed only at the start of an R session.
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 theRETICULATE_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
Programming with Ggplot2 and Dplyr
Usemethod("Predict"):No Applicable Method for 'Predict' Applied to an Object of Class "Train"
Fastest Way to Filter a Data.Frame List Column Contents in R/Rcpp
Pivot_Longer into Multiple Columns
Control Number Formatting in Shiny's Implementation of Datatable
Assign Column Names to List of Dataframes
Object Not Found Error with Ggplot2
Converting Date Column in Data Frame
Concatenate Values Across Columns in Data.Table, Row by Row
How to Insert Appendix After References in Rmd Using Rstudio
How to Get the First 10 Words in a String in R
Simple Comparing of Two Texts in R
How to Show a Loading Screen When the Output Is Being Calculated in a Background Process
Combine Rows and Sum Their Values
R Find the Distance Between Two Us Zipcode Columns
How to Scale the Size of Line and Point Separately in Ggplot2