Background – I have my site hosted on AWS EC2 server which is behind ELB (Elastic Load Balancing). I wanted my site to work on HTTPS. So I provisioned SSL certificate through AWS certificate manager and uploaded it on ELB. ELB receives traffic on both ports 80 and 443 and forwards it to single port 80 on server.
Setup – EC2 server, ELB, nginx, SSL certificate from AWS certificate manager, ROR
Problem – As port 80 is open on ELB, even non secure connection can be established to my site. To avoid this I had 2 choices
- Block port 80 and accept request only on port 443. But that is not a good user experience as he will always have to type https:// in url.
- Redirect all traffic coming to port 80 to port 443 so that connection gets converted to secure connection.
I decided to go with option 2 and then my search started on how to do it. After searching a lot I did not find single place which gave solution to my problem. But could get lot of pointers. After combining all these pointers I came up with following solution.
Solution –
Step 1- Forward traffic coming on port 80 of ELB and 443 to two different ports on server. In this example I am using port 8080 and 80. Forwarding traffic coming to port 80 of ELB to port 8080 of server and traffic coming on port 443 to port 80 of server.
Allow inbound traffic for both ports 80 and 8080 on your server.
Step 2 – Add 2 server blocks in nginx config as follows. Port 80 will serve actual site and port 8080 will be used to redirect traffic coming to it, to https.
server {
listen 80 default;
server_name http://www.mysite.com mysite.com;
root /www/mysite/current/public;
passenger_enabled on;
rails_env production;
. . . . . . . . .
}
server {
listen 8080;
return 301 https://www.mysite.com/$request_uri;
}
In case you have multiple domains then nginx server setup can be done as follows
server {
listen 80 default;
server_name sales.mysite.com sales.my-new-site.com;
root /www/mysite/current/public;
passenger_enabled on;
rails_env production;
. . . . . . . . .
}
server {
listen 8080;
server_name sales.mysite.com sales.my-new-site.com;
return 301 https://$host$request_uri;
}
I hope this will help you and save your time in doing this setup.