I apologize if this seems like a deja vu. There are plenty of posts about similar issues, and I read them all (and tried them out unsuccessfully).
My setup: Rails 4, Puma, Nginx, SSL Cert for both https://www and https://
I am using a combined block so I get a redirect to SSL. However, I would like to redirect https://www.domain.com to https://domain.com Everything works fine with the setup you will see below until I add the redirect rule (return 301 https://$host$request_uri;), then I get a redirect loop.
I added "proxy_set_header X-Forwarded-Proto $scheme;" to my @app location for force_ssl (which is set to true in the Rails config file), but that did not solve the issue.
I would really appreciate expert advise here, and please, if you see any points of improvement in my setup, beyond just fixing the redirect loop, please let me know.
nginx.conf:
user root;
worker_processes 4;
pid /var/run/nginx.pid;
#setup where nginx will log errors to
# and where the nginx process id resides
error_log /var/log/nginx/error.log error;
#pid /var/run/nginx.pid;
events {
worker_connections 1024;
accept_mutex off;
use epoll;
}
http {
include /etc/nginx/mime.types;
types_hash_max_size 2048;
default_type application/octet-stream;
#access_log /tmp/nginx.access.log combined;
# use the kernel sendfile
sendfile on;
# prepend http headers before sendfile()
tcp_nopush on;
keepalive_timeout 25;
tcp_nodelay on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/html text/xml text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;
#Hide server info
server_tokens off;
upstream app_server {
server unix:/root/sites/mina_deploy/shared/tmp/sockets/puma.sock
fail_timeout=0;
}
# configure the virtual host
server {
server_name domain.com www.domain.com 162.555.555.162;
root /root/sites/mina_deploy/current/public;
# port to listen for requests on
listen 80 default deferred;
listen 443 ssl;
####### THIS REDIRECT CAUSES A LOOP ########
#return 301 https://$host$request_uri;
ssl_certificate /etc/ssl/ssl-bundle.crt;
ssl_certificate_key /etc/ssl/myserver.key;
#enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#Disables all weak ciphers
ssl_ciphers 'AES128+EECDH:AES128+EDH';
ssl_session_cache shared:SSL:10m;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/dhparam.pem;
# maximum accepted body size of client request
client_max_body_size 4G;
# the server will close connections after this time
keepalive_timeout 5;
add_header Strict-Transport-Security max-age=63072000;
#add_header X-Frame-Options DENY;
add_header Access-Control-Allow-Origin '*';
add_header X-Content-Type-Options nosniff;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
location ~ ^/(system|assets)/ {
gzip_static on;
error_page 405 = $uri;
expires max;
add_header Cache-Control public;
break;
}
try_files $uri/index.html $uri @app;
location @app {
# pass to the upstream unicorn server mentioned above
proxy_pass http://app_server;
proxy_redirect off;
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 $scheme;
proxy_read_timeout 300;
}
}
}
The thing I did was have multiple server blocks. You mentioned that you want www.domain.com to redirect to domain.com. In this case I would do
Then remove your www.domain.com from your server_name in your original block. Also I would break up your redirects from 80 to 443 in separate blocks as well. So you would repeat this process if a user tried to go to https://www.domain.com you would have a server that says similar things.
And one to listen for http traffic on the domain you want, but redirected to https traffic.
Then you can listen to just port 443 in your server block where you want everyone to go and no redirects are in that block.
You can view documentation for nginx here which will show you that this is the proper way to rewrite
Replying to your comment, Use the three blocks that I have written, and in your original server block, you will need to remove
and also remove
and add
Also, just making sure you know that for this to work, you will have to have your domain and www subdomain pointing at your server