I am working on a project where I need to upload PDFs generated from Rmarkdown to a SFTP server. The sftp
R package is a nice wrapper to the RCurl
package for handling SFTP access. But to my surprise, SFTP support is not included on Macs by default through the curl
command. After some research I found the curl-openssl
formula that includes SFTP support. However, since curl
is a build-in program for Mac OS brew install
will not install it into the PATH
environment, therefore not being directly available. This function will help configure RCurl
on a Mac to use the curl-openssl version so we can have SFTP access.
# First, need to install a version of CURL that supports SFTP
# brew install curl-openssl
# Verify that SFTP is a supported protocol
# /opt/homebrew/Cellar/curl/7.82.0/bin/curl -V
#' Configures CURL with openSSL support for Macs.
#'
#' This function will try the following:
#' 1. Verify that this is being called on a Mac.
#' 2. Check to see if sftp is already available (returns gracefully so to be
#' integrated in setup scripts).
#' 3. Checks to see if Homebrew is installed even if not currently on the PATH.
#' 4. Install curl-openssl if not already installed.
#' 5. Modify the PATH to include the openssl version of curl.
#' 6. Install RCurl from source.
#' 7. Verify sftp is available.
#'
#' @param path the path where Homebrew packages are installed.
#' @return TRUE if sftp is available.
configure_curl_openssl <- function(
path = '/opt/homebrew/Cellar'
) {
if(Sys.info()['sysname'] != 'Darwin') {
warning('This funtion only works on Mac OS.')
return(FALSE)
}
if(system('which brew') == 1) {
if(file.exists('/opt/homebrew/bin/brew')) {
# Homebrew is installed but not on the PATH
PATH <- Sys.getenv("PATH")
Sys.setenv(PATH = paste("/opt/homebrew/bin", PATH, sep = ":"))
} else {
stop('Could not find brew. Try installing from https://brew.sh')
}
}
if('sftp' %in% RCurl::curlVersion()$protocols) {
return(TRUE)
}
curl.versions <- list.dirs(path = paste0(path, '/curl/'),
recursive = FALSE,
full.names = FALSE)
if(length(curl.versions) == 0) { # Try install curl
message('curl-openssl not found, trying to install using Homebrew...')
system('brew install curl-openssl')
curl.versions <- list.dirs(path = paste0(path, '/curl/'),
recursive = FALSE,
full.names = FALSE)
}
if(length(curl.versions) == 0) {
stop('Could not find or install curl-openssl.')
}
version <- curl.versions[length(curl.versions)] # Use the latest version
if('package:RCurl' %in% search()) { # Detach the RCurl package first
detach('package:RCurl', character.only = TRUE)
}
PATH <- Sys.getenv("PATH")
Sys.setenv(PATH = paste0("/opt/homebrew/Cellar/curl/", version, "/bin:", PATH))
message('Resinstalling RCurl from source...')
install.packages('RCurl', type = 'source')
if(!'sftp' %in% RCurl::curlVersion()$protocols) {
stop('Could not configure RCurl with openssl, sorry.')
}
return(TRUE)
}
Simply running the command should do the setup. However, if things go wrong I tried to indicate where in the process something went wrong. You should only need to run this once per R installation since once RCurl
has been installed from source built against the curl-openssl
version of CURL, it should remember to use that version.
configure_curl_openssl()
Once done, we can verify that SFTP access is available.
'sftp' %in% RCurl::curlVersion()$protocols # Verify sftp is available