Skip to content

Instantly share code, notes, and snippets.

@danieldraper
Forked from petelacey/beanstalk_nginx.conf
Created April 3, 2016 23:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danieldraper/2b986bb98d213765d136fadccac58bdc to your computer and use it in GitHub Desktop.
Save danieldraper/2b986bb98d213765d136fadccac58bdc to your computer and use it in GitHub Desktop.
Nginx always-on SSL config for ElasticBeanstalk
files:
"/etc/nginx/conf.d/000_APP_NAME.conf":
mode: "000755"
owner: root
group: root
content: |
upstream APP_NAME_app {
server unix:///var/run/puma/my_app.sock;
}
map $uri $preferred_proto {
default "https";
~^/(assets|public)/ "none";
~^/health "http";
}
server {
listen 80;
if ($preferred_proto = "http") {
set $http_x_forwarded_proto $preferred_proto;
}
if ($preferred_proto = "none") {
set $preferred_proto $http_x_forwarded_proto;
}
if ($preferred_proto != $http_x_forwarded_proto) {
rewrite ^(.*) $preferred_proto://$host$request_uri redirect;
}
location / {
proxy_pass http://APP_NAME_app;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
location /assets {
alias /var/app/current/public/assets;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
location /public {
alias /var/app/current/public;
gzip_static on;
gzip on;
expires max;
add_header Cache-Control public;
}
}
Using ElasticBeanstalk to deploy a Rails app using Puma?
Want always on SSL even when the downstream app doesn't speak SSL?
Also want health checks from ELB?
Then drop the file below into your .ebextensions directory
To use, change instances of "APP_NAME" to some other string. In my case it's "synclinical." You'll likely want other
changes to. For instance, the upstream server communication protocol and the path to your health check action.
This is cobbled together from other places on the web, mostly this: http://www.redant.com.au/ruby-on-rails-devops/manage-ssl-redirection-in-nginx-using-maps-and-save-the-universe/
The premise is: a connection is made to ELB over HTTP or HTTPS. That request is sent to nginx over HTTP, which sets
$http_x_forwarded_proto to 'https'. In addition, ELB is periodically pinging http://health on the backend too.
All HTTP requests that are not for /health, /assets, or /public, get redirected to the same HTTPS path. If the request
is for /assets or /public, then it will be passed through regardless of the protocol, that is, it will not be redirected.
And if the request is for /health, it will only be good for HTTP. In short:
/health --> HTTP
/assets --> HTTP/HTTPS
/public --> HTTP/HTTPS
all others --> redirected to HTTPS
When the request is proxied to the Rails (or whatever) backend, we set X-REAL-IP, X-FORWARDED-FOR, and
X-FORWARDED-PROTO. Among other things, this lets you set: 'config.force_ssl = true' in your production.rb environment
file (even though the application host, e.g. Puma, is not really running SSL), which will turn on Strict Transport Security,
and secure cookies.
The 'location' settings for /assets and /public simply allow nginx to serve up these static assets (JS, CSS, images) instead
of Rails, compressed and with maximal cache control headers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment