We have a Ruby/Rails website we're migrating from Heroku to AWS. The original dev is not available. I'm now trying to complete the migration. My background is in the Windows / .NET world. This Linux / Ruby/Rails environment is quite foreign to me...
Here's the current environment I've set-up:
Route 53
Record Name | Record Type | Alias | Alias Route Traffic To |
---|---|---|---|
foo.example.com | A | yes | cloudfront: xyz.cloudfront.net |
CloudFront
Domain Name | Alternate Domain Names | Origin Domain | Origin Protocol | Behavior Protocol |
---|---|---|---|---|
xyz.cloudfront.net | foo.example.com | foo.us-west-2.elb.amazonaws.com | HTTP only | Redirect HTTP to HTTPS |
The CloudFront distribution:
- uses an AWS issued SSL cert
- handles the http to https redirect
- forwards the request to the ELB over http (not https)
Load Balancer
DNS Name | Listener Rule | Forward To |
---|---|---|
foo.us-west-2.elb.amazonaws.com | HTTP 80: default action | Target Group: foo-ec2 |
Target Group: foo-ec2
contains a single Ubuntu ec2 instance running nginx/1.18.0 Phusion Passenger 6.0.10 to serve up the Ruby/Rails site.
nginx config
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL Config - we should NEVER receive 443/https traffic;
# CloudFront manages https traffic => AWS ELB => http to this server
#listen 443 ssl default_server;
#listen [::]:443 ssl default_server;
server_name foo.example.com
foo.us-west-2.elb.amazonaws.com;
# Tell Nginx and Passenger where the app's 'public' directory is
root /var/www/foo_example/public;
# Turn on Passenger
passenger_enabled on;
passenger_app_env production;
passenger_ruby /home/ubuntu/.rbenv/versions/2.6.8/bin/ruby;
}
Issue
The rails app starts up without error and is served over https. However, when a user attempts to log in / authenticate, the
Once the new origin request policy has been created:
- head back to the CloudFront distributions
- click your distribution's Id so you can edit it
- click the "Behaviors" tab
- select your behavior and edit
- scroll down to "Cache key and origin requests"
- make sure the "Cache policy and origin request policy (recommended)" is selected
- under the "Origin request policy - optional", select your new policy, i.e., "my origin request policy"
- save changes
The behavior will look like this (I'm using no caching for now to verify the ec2 instance is getting all the requests):
That's it. The host header is now correctly passed through to the ELB and ec2 instance. Nothing else needs to be done with the ELB.
I verified the host header was being used in all requests by modifying the nginx logging option to include the $host
variable in the log file (and did a bit more customization to the OOB format):
# prefixed log with '[my-log]', but it's not needed; remove.
log_format my-log '[my-log] $http_x_forwarded_for - $remote_user [$time_local] '
'"$request_method $scheme://$host$request_uri $server_protocol" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL Config - we should NEVER receive 443/https traffic;
# CloudFront manages https traffic => AWS ELB => http to this server
#listen 443 ssl default_server;
#listen [::]:443 ssl default_server;
server_name foo.example.com
foo.us-west-2.elb.amazonaws.com;
# create the our log file
access_log /var/log/nginx/my-log.access.log my-log;
# Tell Nginx and Passenger where the app's 'public' directory is
root /var/www/foo_example/public;
# Turn on Passenger
passenger_enabled on;
passenger_app_env production;
passenger_ruby /home/ubuntu/.rbenv/versions/2.6.8/bin/ruby;
}
Surely this will help future me as well as others.