Managing secrets and configuration can be a challenge in applications which need to work in different development and deployment environments. Typically, secrets are credentials for an external service such as a database. Environments, on the other hand, are used to manage multiple configurations that we can be easily switched between. Rhino recommends a way for working with either one.
Secrets are a confidential information and should not be tracked in your version control system.
Therefore, a natural place for them are system environment variables.
Variables set in system environment can be retrieved within your code with Sys.getenv()
.
R provides a way to easily set environment variables.
Upon a session start (or restart) R reads .Renviron
file contents and sets environment variables.
.Renviron
# A comment in .Renviron file DATABASE_PASSWORD="foobar123!" API_KEY="75170fc230cd88f32e475ff4087f81d9"
Secrets defined via environment variables can be read and used the following way:
db_password <- Sys.getenv("DATABASE_PASSWORD") if (db_password == "") { # Handle unset or empty DATABASE_PASSWORD variable } pool <- pool::dbPool( drv = RMySQL::MySQL(), dbname = "...", host = "...", username = "admin", password = db_password )
.Renviron
..Renviron
file for every environment. Swap the whole file when changing environments.CONSTANT_CASE
for variable names..Renviron
file in a version control system. Store it in a secure location, e.g. a password manager..Renviron
to RStudio Connect nor shinyapps.io. Both, RStudio Connect and Shiny Apps, provide means to manage environment variables.Having every configurable setting stored as an environment variable would result in overgrown .Renviron
files.
That's where configurable environments come in.
Everything that is not confidential can be tracked by a version control system.
Rhino endorses use of {config}
package for managing environments.
config.yml
default: rhino_log_level: !expr Sys.getenv("RHINO_LOG_LEVEL", "INFO") rhino_log_file: !expr Sys.getenv("RHINO_LOG_FILE", NA) database_user: "service_account" database_schema: "dev" dev: rhino_log_level: !expr Sys.getenv("RHINO_LOG_LEVEL", "DEBUG") staging: database_schema: "stg" production: database_user: "service_account_prod" database_schema: "prod"
.Renviron
R_CONFIG_ACTIVE="dev"
You can access the configuration variables in the following way:
box::use(config) config$get("rhino_log_level") # == "DEBUG" config$get("database_user") # == "service_account" config$get("rhino_log_level", config = "production") # == "INFO" config$get("database_user", config = "production") # == "service_account_prod" withr::with_envvar(list(RHINO_LOG_LEVEL = "ERROR"), { config$get("rhino_log_level") # == "ERROR" config$get("rhino_log_level", config = "production") # == "ERROR" })
config.yml
.R_CONFIG_ACTIVE
variable in .Renviron
.!expr Sys.getenv()
to make settings overridable with environment variables.box::use(config)
and config$get()
.snake_case
for field names.Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.