Running with a Proxy

Overview

RStudio Workbench runs a fully managed Nginx HTTP server that can be customized for SSL, security and more. It is configured from settings in rserver.conf (e.g. ssl-enabled, www-address) and can be customized with additional Nginx directives. See Customizing Default Proxy for more info on customizing the built-in proxy server.

Even with a built-in Nginx server, it’s common for customers to also use an external proxy server that runs in front of RStudio Workbench for security, to bridge firewalls, or to leverage an existing IT proxy server. This section describes how to configure an external proxy server to proxy traffic to and from RStudio Workbench.

If you are installing a new Apache or Nginx proxy server, see the complete examples for Nginx Configuration and Apache Configuration for a quicker start. These step-by-step instructions allow you to customize those examples or update an existing proxy server’s configuration.

  1. Add a Proxy Pass Directive
  2. Set HTTP Headers
  3. Forwarding Websockets
  4. Check the Connection Timeout

Add a Proxy Pass Directive

The proxy pass directive controls which URLs are forwarded to RStudio Workbench. If the proxy server is shared with other applications, choose a path prefix that identifies RStudio requests, e.g. /rstudio. Otherwise, for a dedicated proxy server, send all requests to RStudio by specifying a location of /. The proxy pass directive requires the host name or ip address of RStudio Workbench. In the examples below, replace localhost with RStudio’s host name or ip address when the proxy server is not local. The proxy pass directive also requires a protocol in the target URL. Use https when RStudio itself has SSL enabled (with the setting ssl-enabled=1 in rserver.conf), otherwise use http.

Here’s the proxy_pass directive for Nginx with the /rstudio prefix and ssl-enabled=0:

location /rstudio {
    # Removes /rstudio from the URL
    rewrite ^/rstudio(.*)$ /$1 break;
    proxy_pass http://localhost:8787;
    # other directives go here
}

or for Nginx with no prefix:

location / {
    proxy_pass http://localhost:8787;
    # other directives go here
}

For Apache with the /rstudio prefix:

RewriteRule /rstudio/(.*)     http://localhost:8787/$1 [P,L]
ProxyPass /rstudio/ http://localhost:8787/

or for Apache with no prefix:

ProxyPass / http://localhost:8787/

Set HTTP Headers

To properly generate externally resolvable redirect URLs and cookie domain paths, RStudio needs the external proxy server’s host name, port, protocol and optional path prefix. These should be similar to those used in a location redirect for HTTP.

Hostname and Port

By default, RStudio obtains the hostname and port from the standard HTTP Host header. This value is set by the browser and forwarded to RStudio but it’s important to set it in the proxy configuration as well. Those headers are optional in HTTP and resetting them prevents tampering from the browser, and prevents the proxy server from rewriting the Host header to the internal hostname. It’s usually possible to add a Set-Header directive to the proxy server configuration that sets Host to the correct external hostname. Add the :serverport suffix if you are not using default ports for http/https.

Server Protocol

If the proxy server is configured for SSL and RStudio is not the X-Forwarded-Proto header should be set to https.

This will prevent RStudio from changing the protocol of generated URLs from https to http when it performs a redirect. For example, if the header is not set the login page will redirect back to http://servername instead of https://servername.

Path Prefix

If you configured the ProxyPass directive with a path prefix, configure the www-root-path attribute in /etc/rstudio/rserver.conf so that RStudio knows to add this path prefix to any external URLs it generates.

# /etc/rstudio/rserver.conf
www-root-path=/rstudio

Alternatively, to configure the path-prefix entirely in the proxy server’s configuration, add a proxy set header directive to set the HTTP header X-RStudio-Root-Path with the value of your path prefix - e.g. /rstudio.

Note

The header X-RStudio-Root-Path and the configuration option www-root-path serve the same purpose. If either is set RStudio will always return cookies and redirects for the correct path, without requiring rewrite assistance from the proxy. The header value has precedence over the configuration value.

Alternate Headers

RStudio supports other HTTP headers as alternative ways to inform it of the hostname, server port, protocol, and path prefix:

To set all of the values with one header, use:

X-RStudio-Request  protocol://server-name:server-port/path-prefix

For example:

X-RStudio-Request  https://www.example.com:8787/rstudio

Just as with X-Forwarded-Proto, if your proxy server already sets the headers X-Forwarded-Host and X-Forwarded-Port they can be used to ensure RStudio redirects to the correct hostname and port, respectively.

Similarly RStudio supports the standard Forwarded header for retrieving the host= and proto= fields.

Note

When not using a custom path prefix, the hostname used by RStudio will always come from the Host header, not from X-Forwarded-Host, X-RStudio-Request, or Forwarded.

Forwarding Websockets

Beyond the normal reverse proxy configuration you’d apply for any HTTP server application, you also need to ensure that websockets are forwarded correctly between the proxy server and RStudio to ensure that all RStudio functions work correctly. In particular, they’re needed for Shiny applications and VS Code sessions.

The configuration to forward websockets varies for each proxy server. There are examples for enabling websockets in Nginx Configuration and Apache Configuration.

Check the Connection Timeout

It’s also important to ensure that your reverse proxy allows long-standing connections or uses a relatively lenient connection timeout; we recommend at least 60 seconds. Several components of RStudio use HTTP Long Polling to push information to the browser; a connection timeout of under 50 seconds will result in HTTP 504 (gateway timeout) errors from the reverse proxy.

Shiny applications will close abruptly if the websocket is timed out by a proxy server.

Starting a VS Code session will show a blank page if the websocket connection is not fowarded.

Nginx Configuration

On Debian or Ubuntu a version of Nginx that supports reverse-proxying can be installed using the following command:

sudo apt-get install nginx

On CentOS or Red Hat you can install Nginx using the following command:

sudo yum install nginx

To enable an instance of Nginx running on the same server to act as a front-end proxy to RStudio you would add commands like the following to your nginx.conf file. These examples represent the customizable chunks but you should insert each chunk under http, server, and location to modify your nginx.conf file as necessary. Note that you must add the configuration below to proxy websockets in order to correctly display Shiny apps and R Markdown Shiny documents in RStudio. Also note that if you are proxying to a server on a different machine you need to replace references to localhost with the correct address of the server where you are hosting RStudio.

http {

  # Support proxying of web-socket connections
  map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
  }
  
  server {
    listen 80;
    
    location / {
      proxy_pass http://localhost:8787;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;

      proxy_set_header Host $host:$server_port;

      proxy_read_timeout 20d;
    }
  }
}

If you want to serve RStudio from a custom path (e.g. /rstudio) update your nginx.conf file with the directives shown below. Replace all occurrences of /rstudio with your chosen custom path prefix.

http {

  # Support proxying of web-socket connections
  map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
  }
  
  server {
    listen 80;
    
    location /rstudio/ {
      # Needed only for a custom path prefix of /rstudio
      rewrite ^/rstudio(.*)$ /$1 break;

      # Use http here when ssl-enabled=0 is set in rserver.conf
      proxy_pass http://localhost:8787;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;

      # Not needed if www-root-path is set in rserver.conf
      proxy_set_header X-RStudio-Root-Path /rstudio;

      # Optionally, use an explicit hostname and omit the port if using 80/443
      proxy_set_header Host $host:$server_port;
    }
  }
}

If the Nginx proxy is using SSL and RStudio has ssl-enabled=0, use the directives from this example:


http {
    # Support proxying of web-socket connections
    map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name localhost;

        # Change to point to your certs
        ssl_certificate /etc/ssl/certs/localhost.crt;
        ssl_certificate_key /etc/ssl/private/localhost.key;

        ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

        location /rstudio {
           # Needed only for prefix of /rstudio
           rewrite ^/rstudio(.*)$ /$1 break;

           # Use http here when ssl-enabled=0 is set in rserver.conf
           proxy_pass http://localhost:8787;
           proxy_http_version 1.1;

           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection $connection_upgrade;

           # Optionally, use an explicit hostname and omit the port if using 80/443
           proxy_set_header Host $host:$server_port;

           # Not needed if there's no prefix or www-root-path is set in rserver.conf
           proxy_set_header X-RStudio-Root-Path /rstudio;

           # Tells RStudio to send redirect URLs back to https
           proxy_set_header X-Forwarded-Proto https;

           proxy_read_timeout 20d;
        }
    }
}

After adding these entries you’ll then need to restart Nginx so that the proxy settings take effect:

sudo /etc/init.d/nginx restart

or

sudo systemctl restart nginx

In some cases, such as when streaming job statuses from the launcher, the default response buffering in nginx can be too slow for delivering real-time updates, especially when configured to use SSL. If job output streams are not working properly from the home page, we recommend disabling response buffering by adding the following line under the server directive:

server {
  # ... follows previous configuration
  proxy_buffering off;
}

Apache Configuration

To enable an instance of Apache running on the same server to act as a front-end proxy to RStudio you need to use the mod_proxy and mod_proxy_wstunnel modules. The steps for enabling this module vary across operating systems so you should consult your distribution’s Apache documentation for details. Apache as reverse proxy already includes X-Forwarded-Host (with port) and X-Forwarded-Proto by default.

On Debian and Ubuntu systems Apache can be installed with mod_proxy using the following commands:

sudo apt-get install apache2
sudo apt-get install libapache2-mod-proxy-html
sudo apt-get install libxml2-dev

Then, to update the Apache configuration files to activate mod_proxy you execute the following commands:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel

On CentOS and RedHat systems Apache can be installed with mod_proxy and mod_proxy_wstunnel by following the instructions here:

http://httpd.apache.org/docs/2.4/platform/rpm.html

By default with Apache 2.4, mod_proxy and mod_proxy_wstunnel should be enabled. You can check this by opening the file /etc/httpd/conf.modules.d/00-proxy.conf and making sure the following lines are included and not commented out:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

Once you have enabled mod_proxy and mod_proxy_wstunnel in your Apache installation you need to add the required proxy commands to your VirtualHost definition. Note that you will also need to include code to correctly proxy websockets in order to correctly proxy Shiny apps and R Markdown documents within RStudio. Also note that if you are proxying to a server on a different machine you need to replace references to localhost with the correct address of the server where you are hosting RStudio.

For Apache, if you are setting the Host header, you must enable the option:

ProxyPreserveHost On

RStudio relies on the Host header matching what the browser sees. If ProxyPreserveHost is Off, the server and port are changed in the Host header and URLs will point to the wrong server and port.

In the examples below, change example.com:80 to the hostname:port users will use to access your site and change localhost:8787 to the hostname:port of your RSW server.

Here’s an example where the proxy server is not configured with SSL or a path prefix, and where SSL is also not enabled (i.e. ssl-enabled=0 in rserver.conf) for RSW.

ProxyPreserveHost On

<VirtualHost *:80>

  <Proxy *>
    Allow from localhost
  </Proxy>

  ProxyPass / http://localhost:8787/
  ProxyPassReverse / http://localhost:8787/
  RequestHeader set Host example.com:80
  ProxyRequests Off

</VirtualHost>

If you want to serve RStudio from a custom path (e.g. /rstudio) use this example. Replace all occurrences of /rstudio with your chosen custom path prefix.

ProxyPreserveHost On

<VirtualHost *:80>
   <Proxy *>
     Allow from localhost
   </Proxy>
   ProxyPass /rstudio/ http://localhost:8787/
   RequestHeader set Host "example.com:80"
   RequestHeader set X-RStudio-Root-Path "/rstudio"
   ProxyRequests Off
</VirtualHost>

Use this example for a proxy server that supports SSL, also using a custom path prefix. For this example, you need to install the mod_ssl module for Apache.

  ProxyPreserveHost On

   <Proxy *>
     Allow from localhost
   </Proxy>
   
   ProxyPass /rstudio/ http://localhost:8787/
   RequestHeader set Host "example.com:443"
   RequestHeader set X-RStudio-Root-Path "/rstudio"
   RequestHeader set X-Forwarded-Proto https
   ProxyRequests Off
# /etc/rstudio/rserver.conf
www-root-path=/rstudio

Finally, after you’ve completed all of the above steps you’ll then need to restart Apache so that the proxy settings take effect:

sudo /etc/init.d/apache2 restart

or

sudo systemctl restart httpd

RStudio Configuration

If your RStudio Workbench and proxy server are running on the same machine you can also change the port RStudio Workbench listens on from 0.0.0.0 (all remote clients) to 127.0.0.1 (only the localhost). This ensures that the only way to connect to RStudio is through the proxy server. You can do this by adding the www-address entry to the /etc/rstudio/rserver.conf file as follows:

www-address=127.0.0.1

Note that you may need to create this config file if it doesn’t already exist.

Customizing Default Proxy

RStudio Workbench exposes itself over TCP by means of an nginx proxy instance that runs as the rserver-http process on the local machine. In some cases, this proxy instance may need to be customized.

In order to customize it, you can create any of the following three files. Each file modifies the nginx configuration at /var/lib/rstudio-server/conf/rserver-http.conf in the following way:

  • /etc/rstudio/nginx.http.conf - allows you to add additional nginx directives under the root http node, and should be used for altering basic HTTP settings
  • /etc/rstudio/nginx.server.conf - allows you to add additional nginx directives under the server node, and should be used for altering basic server settings
  • /etc/rstudio/nginx.site.conf - allows you to add additional nginx directives under the location / node, and should be used for altering responses sent from RStudio

Simply add the desired nginx configuration in the files above to modify the desired section - the contents of each file is copied into the rserver-http.conf template verbatim. Then, restart rstudio-server for the changes to take effect.

In most cases, you should not need to create these files and modify the nginx template that is provided.