Robert's Data Science Blog

Access CRAN on JFrog

JFrog offers a CRAN for R packages. The R capabilities are not particularly fancy, but the main benefit for me is that this is a platform used elsewhere at work and hence someone else is taking care of maintenance.

A CRAN is part of JFrog’s Artifactory and R packages are accessed through Artifactory’s REST API. In this post I show how to install packages from a JFROG CRAN.

The first thing is to generate an API key instead of using your password. It is also possible to use access tokens, which I think is a good idea for e.g. CI jobs instead of making a user just to have an extra API key.

When creating a CRAN in JFrog you have to choose a name, which I refer to as <CRAN name> in the following.

Basic authentication

JFrog’s own documentation suggests using basic HTTP access authentication by including username and API key in the CRAN URL:

install.packages("<package>", repos = "https://<user>:<API key>@<domain><CRAN name>"})

Typing the repos argument every time gets tedious so instead I update my system wide Rprofile to include this repository:

    repos = c(
        "JFROG" = "https://<user>:<API key>@<domain><CRAN name>",
        "MRAN" = ""

As explained in the post I linked to above I use MRAN instead of the bleeding edge CRAN and this particular date is for R version 4.0.2.

Actually, I don’t recommend hardcoding the <user> and <API key> in the system wide Rprofile. Instead I rely on environment variables:

    repos = c(
        "JFROG" = paste0("https://", Sys.getenv('JFROG_USER'), ":", Sys.getenv('JFROG_API'), "@<domain><CRAN name>",
        "MRAN" = ""

Then each user fill their personal .Renviron with the variables JFROG_USER and JFROG_API:


Remember that the usethis package can help find this file with usethis::edit_r_environ().

Header authentication

While the above method works there is a downside: When installing a package (from any CRAN) R writes the full URL in the console – which now includes personal credentials. This may be okay on a personal computer, but I don’t like it in automatic jobs with logs like a CI pipeline

This is where authentication with a dedicated header is useful:

install.packages("<package>", headers = c("X-JFrog-Art-Api" = Sys.getenv('JFROG_API')))

Alternatively, an access token (saved in the environment variable JFROG_PAT) can be used for bearer authentication:

install.packages("<package>", headers = c("Authorization" = paste("Bearer", Sys.getenv('JFROG_PAT'))))

The headers arguments is passed on to download.file.