Opening RStudio using AWS' SSL certificate v2

Hey guys,

About the topic I've created in January: Opening RStudio using AWS' SSL certificate

After spending some days (:joy:) trying to find a solution, I finally found the correct configuration for the virtual host (using apache httpd):

<VirtualHost *:80>

  <Proxy *>
    Allow from localhost
  </Proxy>


#Proxy to RStudio:
RedirectMatch permanent ^/rstudio$ /rstudio/
  
RewriteEngine on

  RewriteCond ${HTTP:Upgrade} websocket [NC]
  RewriteCond ${HTTP:Connection} upgrade [NC]
  RewriteRule /rstudio/(.*) "wss:/localhost:8787/$1" [P,L]
  ProxyPass /rstudio/ http://localhost:8787/
  ProxyPass /rstudio/ https://localhost:8787/
  ProxyPassReverse /rstudio/ https://localhost:8787/
  ProxyRequests off


RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

</VirtualHost>

And now if I type mydomain.com/rstudio I'm automatically redirected to https :v:

Now I only found one issue:
After logging in, I can see my code, so no problem here. But when I try to run my app using RStudio, the Chrome page goes gray and in the console I can find the following error:
WebSocket connection to 'wss://mydomain.com/rstudio/p/b25d206d/websocket/' failed: Error during WebSocket handshake: Unexpected response code: 404

I tried to apply some solutions I found online but they didn't work. When I ran my shiny app directly in the browser by typing mydomain.com/shiny the app works fine, but it was also giving me the warning in the console about the websocket, so I changed my shiny-server config file, adding this new line:
disable_protocols websocket;

So now I don't have any error message in the console and mydomain.com/shiny continues to work fine.

But I wasn't able to fix this same websocket error message after trying to run the app in RStudio server.

Thanks in Advance for the help!

2 Likes

I suspect a port issue.

In your proxy settings you have opened the port 8787 (which is the port that RStudio server uses) and not 3838 (that Shiny server uses, unless overriden).

I am more of a Nginx than Apache person, so I can not help you with the actual settings, but if I were you I would check the ports.

So Shiny Server (and RStudio Connect) can run protocols other than websockets for hosting Shiny applications. However, RStudio Server's implementation requires websockets in order to function.

Basically, the behavior you are seeing tells us: "websockets are not being propagated properly through the proxy."

The way that we do this in our guide is to ensure the appropriate modules are being loaded:

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

And then do the appropriate upgrade for websocket connections (this is when RStudio Server is listening HTTP - i.e. RStudio Server Open source) :

  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /(.*)     ws://localhost:8787/$1  [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket
  RewriteRule /(.*)     http://localhost:8787/$1 [P,L]
  ProxyPass / http://localhost:8787/
  ProxyPassReverse / http://localhost:8787/

Are you running RStudio Server Pro and have RStudio listening in HTTPS? If so, it would look like:

  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /(.*)     wss://localhost:8787/$1  [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket
  RewriteRule /(.*)     https://localhost:8787/$1 [P,L]
  ProxyPass / https://localhost:8787/
  ProxyPassReverse / https://localhost:8787/

In any case, I think the two ProxyPass lines are a bit redundant, and one of them should be removed, depending on how you have things set up (i.e. is RStudio Server listening on HTTP or HTTPS):

  ProxyPass /rstudio/ http://localhost:8787/
  ProxyPass /rstudio/ https://localhost:8787/

Hey jlacko!

Thanks for the answer.

This part is also replicated for shiny in my virtual host (I didn't paste it in my question because shiny is already working well.

#Proxy to RStudio:
RedirectMatch permanent ^/rstudio$ /rstudio/
  
RewriteEngine on

  RewriteCond ${HTTP:Upgrade} websocket [NC]
  RewriteCond ${HTTP:Connection} upgrade [NC]
  RewriteRule /rstudio/(.*) "wss:/localhost:8787/$1" [P,L]
  ProxyPass /rstudio/ http://localhost:8787/
  ProxyPass /rstudio/ https://localhost:8787/
  ProxyPassReverse /rstudio/ https://localhost:8787/
  ProxyRequests off

(the code above is the same for shiny, I only changed /rstudio to /shiny and the port to 3838).

I checked the ports in the security group and both port 3838 and 8787 are open to everyone.

Maybe it's really an apache configuration part I'm missing.

Thanks again! :grin:

Hey Cole!

I already have this code inside the 00-proxy.conf file:

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

And if I use your suggestion for the virtual host configuration, when I type mydomain.com/rstudio I'm redirected to the http version (and then if I click on the url and press enter again it redirects me to the https version).
So I logged in using the https version and after the login the url goes again automatically to the http version and I can see my code (this doesn't happen with the config I inserted in my first post. Using the other config the page is always using https), but when I click on "Run app" the websocket error remains the same.

Can you clarify if you are using HTTPS for RStudio? I.e. You have SSL from the browser to apache. Is RStudio listening SSL for traffic from apache to RStudio? It sounds like the current problem w/ HTTP vs. HTTPS is your ProxyRedirect is not being caught appropriately. Understanding the target architecture will definitely help make recommendations accordingly :slight_smile:

I don't know if I understood your question, Cole.. :thinking:

How can I check if RStudio is listening?

What I tried to do (and it's finally working) is to use the SSL certificate I selected on AWS to always see the https version of mydomain.com/rstudio

Does that mean that RStudio is listening SSL? (based on the virtual host code I inserted in my first post, every time I type on chrome mydomain.com/rstudio it redirects automatically to https://www.mydomain.com/rstudio and I can safely log in).

Sorry, I didn't phrase my question super well. Is it possible that you can share your /etc/rstudio/rserver.conf file? That should tell me what I'm looking for.

No problem (English isn't my native language, so it might be that :joy: ).

Yeah, sure. Basically I just added the address 127.0.0.1 for security reasons like a RStudio post suggested:

# Server Configuration File

www-address=127.0.0.1

Thanks for your help, Cole!

Thanks for sharing! Yes, so RStudio server is listening in HTTP. So I suspect your proxy needs to look more like:

<VirtualHost *:80>

  <Proxy *>
    Allow from localhost
  </Proxy>


#Proxy to RStudio:
RedirectMatch permanent ^/rstudio$ /rstudio/
  
RewriteEngine on

  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /rstudio/(.*)     ws://localhost:8787/$1  [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket
  RewriteRule /rstudio/(.*)     http://localhost:8787/$1 [P,L]

  ProxyPass /rstudio/ http://localhost:8787/
  ProxyPassReverse /rstudio/ http://localhost:8787/

  ProxyRequests off

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

</VirtualHost>

HTTPS is enforced on reaching Apache, but then traffic behind / upstream from Apache is HTTP

Hey Cole!

If I use your suggestion, I'm redirected to the http version of the page when I type mydomain.com/rstudio and only if I click on the url and click enter again, then I'm redirected to the https page. And when I log in, my url changes to localhost:8787 and this is the page after logging in:

(and we know this problem, because you helped me fix it by adding more code in the vhost when I created the topic Opening RStudio using AWS' SSL certificate )

I know this is the configuration RStudio suggests, but unfortunately it didn't work for me. What worked was the configuration I pasted here in my first post. The only thing I'm not able to do is to run the app inside RStudio using https because of the websocket error.

Woops. Sorry about that :man_facepalming: I forgot the other ProxyPassReverse. I think this should work. Maybe :see_no_evil:

<VirtualHost *:80>

  <Proxy *>
    Allow from localhost
  </Proxy>


#Proxy to RStudio:
  RedirectMatch permanent ^/rstudio$ /rstudio/

  RewriteEngine On

  # force HTTPS
  RewriteCond %{HTTP:X-Forwarded-Proto} !=https
  RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

  # proxy websockets
  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /rstudio/(.*)     ws://localhost:8787/$1  [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket
  RewriteRule /rstudio/(.*)     http://localhost:8787/$1 [P,L]

  #proxy traffic to RStudio
  ProxyPass /rstudio/ http://localhost:8787/
  ProxyPassReverse /rstudio/ http://localhost:8787/
  ProxyPassReverse /rstudio/ https://localhost:8787/

  ProxyRequests off
</VirtualHost>

Basically, you need (1) the redirect to HTTPS to work (it's not currently) and (2) the ProxyPassReverse to work (the problem with localhost:8787).

(1) is discussed in more detail here. I made some changes that I hope will fix it...

(2) is hopefully handled by:

  ProxyPassReverse /rstudio/ https://localhost:8787/

It's worth noting that another possibility is that your AWS load balancer is never sending the X-Forwarded-Proto header, in which case you may have the wrong protocol specified in your TargetGroup or ELB setup. The protocol should be HTTP (not TCP):

Note that TCP load balancers do not support the X-Forwarded-* headers

1 Like

Hey Cole!

The protocol is HTTP, yes.

That virtual host solution worked!! :raised_hands:

Thanks a lot, man! :grin:

I have only one more doubt. It's also about websockets but on shiny server: as you said, shiny works if we disable websockets (like I did to avoid the 400 error in Chrome console). But is this best way to fix the problem? Just add the disable_protocols websocket; line in my shiny server config and that's it?

Thanks again, Cole!

My pleasure!! Glad to hear it is working!!

If websockets are working for RSP now, you can implement the same type of setup for Shiny Server and websockets should work then! I would generally recommend that approach (i.e. get websockets working) over disabling websockets, because certain software / clients (i.e. shinyloadtest) are dependent on websockets.

Yeah, I kept the disable websocket line but I'll remove it and adapt your approach also to my shiny app redirect. It seems like a better option.

Thanks again for all your help, Cole! :grin:

Now I finally have the app working 100% everywhere! :raised_hands:

I'm just finishing some R/shiny code improvements and then I'll be able to make it (securely) public thanks to you :+1:

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.