Skip to content

Instantly share code, notes, and snippets.

@cosmincatalin
Last active October 27, 2022 10:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62 to your computer and use it in GitHub Desktop.
Save cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62 to your computer and use it in GitHub Desktop.
Shiny community server with OAuth on Amazon EC2
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
# This server should only run on HTTPS
listen 443 default ssl;
# Replace shiny.example.com with your domain name
# You need to have mapped the domain with your DNS
# provider by using either an A record
server_name shiny.example.com;
ssl_certificate /etc/nginx/certificates/cert.bundle;
ssl_certificate_key /etc/nginx/certificates/cert.key;
add_header Strict-Transport-Security max-age=2592000;
location / {
# This is where the second reverse proxy lives
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass_header Upgrade;
proxy_pass_header Connection;
proxy_connect_timeout 1;
proxy_send_timeout 30;
proxy_read_timeout 30;
# Enabled websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# The line below resets the header. It would otherwise
# make oauth2_proxy unhappy for some reason
proxy_set_header Sec-Websocket-Extensions "";
}
}
index index.html index.htm;
}
mkdir -p /etc/nginx/certificates
cat /home/ec2-user/nginx.conf > /etc/nginx/nginx.conf
cp /home/ec2-user/cert.* /etc/nginx/certificates
# If the server is initially stopped, it will look like a failure.
# You can ignore that as long as the server actually start after that
service nginx restart
upstreams = [
# This where the Shiny server lives
"http://127.0.0.1:3838/",
]
request_logging = false
email_domains = [
# All users under this domain will be granted access
# Replace this
"example.com"
]
# Replace this
client_id = "1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1.apps.googleusercontent.com"
# Replace this
client_secret = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d"
# Randomly generate a seed for the cookie secret
# Replace this
cookie_secret = "m7m7m7m7m7m7m7m7m7m7m77m"
yum -y install go
GOPATH="/home/ec2-user/.go" go get github.com/cosmincatalin/oauth2_proxy # A custom build 2 forks far from the source
cp oauth2_proxy.cfg /home/ec2-user/.go/bin
/home/ec2-user/.go/bin/oauth2_proxy -config /home/ec2-user/.go/bin/oauth2_proxy.cfg

Shiny community server with OAuth on Amazon EC2

Description

This is detailed description of how to set-up a Shiny server (community edition) on an AWS EC2 instance, behind an OAuth2 security layer (Google OAuth2 in this case, but it can be something else).

Prerequisites

  • A Google Developer account
  • An Amazon Web Services account
  • a VPC with a public subnet
  • A domain (or subdomain, or wildcard domain) certificate bundle and key files.

Steps you will need to take

EC2 instance
  • Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/.
  • From the Amazon EC2 console dashboard, choose Launch Instance.
  • On the Choose an Amazon Machine Image (AMI) page, choose the Amazon Linux AMI.
  • On the Choose an Instance Type page, select the hardware configuration and size of the instance to launch. Choose something larger than a t2.medium.
  • On the Configure Instance Details page, choose a VPC and a corresponding public subnet. (You have to know in advance which of the subnets is public http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-ip-addressing.html#vpc-public-ip-addresses)
  • On the Configure Security Group page, use security groups that allow you at least SSH access to you and world wide access to HTTPS.

Make sure you have access to the private key that is used to connect to the instance. This needs to be loaded in your SSH agent.

Elastic IP
  • Open the Amazon VPC console at https://console.aws.amazon.com/vpc/.
  • In the navigation pane, choose Elastic IPs.
  • Choose Allocate New Address, and then Yes, Allocate.
  • Select the Elastic IP address from the list, choose Actions, and then choose Associate Address.
  • In the dialog box, choose Instance from the Associate with list, and then select your instance from the Instance list. Choose Yes, Associate.
certificates

The two certificate files (bundle certificate and private key) need to be placed on the server. Assuming you are in a folder that conatins both of them, you can easily scp them to the future Shiny server. Replace x.x.x.x with the Elastic IP you have previusly created.

  • scp cert.bundle ec2-user@x.x.x.x:
  • scp cert.key ec2-user@x.x.x.x:
nginx

nginx is the first reverse proxy used. It is nginx which will redirect all traffic to a second reverse proxy. To execute this step, you will first need to be logged in the EC2 instance via SSH. The user you should be using is ec2-user and you must start from the home folder /home/ec2-user.

  • sudo yum -y install nginx
  • wget https://gist.github.com/cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62/raw/nginx.conf.
  • Dont' forget to modify the server_name shiny.example.com in this file after downloading it, so vim nginx.conf.
  • wget https://gist.github.com/cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62/raw/nginx.sh
  • sudo bash nginx.sh
Shiny

This is why you're here, right?

  • wget https://gist.github.com/cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62/raw/shiny.sh.
  • Modify Shiny server version if you want. So vim shiny.sh
  • sudo bash shiny.sh
DNS

Create an A record with your DNS provider so that you point the domain name to the Elastic IP. If this is done correctly you should be able to see something working when accessing your domain similar to https://shiny.example.com.

Google

You now need to setup a Google OAuth2 client. This part of the guide was shamelessly copied from https://github.com/bitly/oauth2_proxy#google-auth-provider.

  • Create a new project: https://console.developers.google.com/project
  • Choose the new project from the top right project dropdown (only if another project is selected)
  • In the project Dashboard center pane, choose "Enable and manage APIs"
  • In the left Nav pane, choose "Credentials"
  • In the center pane, choose "OAuth consent screen" tab. Fill in "Product name shown to users" and hit save.
  • In the center pane, choose "Credentials" tab.
  • Open the "New credentials" drop down
  • Choose "OAuth client ID"
  • Choose "Web application"
  • Application name is freeform, choose something appropriate
  • Authorized JavaScript origins is your domain ex: https://shiny.example.com
  • Authorized redirect URIs is the location of oath2/callback ex: https://shiny.example.com/oauth2/callback
  • Choose "Create"
  • Take note of the Client ID and Client Secret
oauth2_proxy

This is the second reverse proxy to which nginx is communicating with. It is this proxy that ensures security and authentication.

  • wget https://gist.github.com/cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62/raw/oauth2_proxy.cfg
  • You will need to edit the oauth2_proxy.cfg by modifying the following:
  • client_id which can be found in Google Cloud Console > API Manager > Credentials > Your OAuth2 ClientID > Client ID
  • client_secret which can be found in Google Cloud Console > API Manager > Credentials > Your OAuth2 ClientID > Client secret
  • cookie_secret something random and decently sized.
  • email_domains this how you restrict access to allow only users having emails under specific domains.
  • wget https://gist.github.com/cosmincatalin/221d9c563ca3cad6ce09a70e87d2ac62/raw/oauth2_proxy.sh
  • sudo bash oauth2_proxy.sh &

That's it, you're done. Open https://shiny.example.com and you should be asked to authenticate. After a successful authentication, you should be able to see a working sample page from the Shiny server. You can of course choose to configure oauth2_proxy with other credential providers, too.

If you have questions, you can always reach me via email.

Other interesting material

Take a look at my other Related gists:

yum -y install R
su - -c "R -e \"install.packages('shiny', repos='https://cran.rstudio.com/')\""
wget https://download3.rstudio.org/centos5.9/x86_64/shiny-server-1.5.4.869-rh5-x86_64.rpm
yum -y install --nogpgcheck shiny-server-1.5.4.869-rh5-x86_64.rpm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment