Daniel Holm
Daniel Holm

Reputation: 4457

Ruby on Rails in nginx server, HTTPS redirects to HTTP

I have a client that wanted SSL on its site so I got the certificate and set up the nginx conf (below is the config) with it. If I dont point the root of the HTTPS part to the real server root it works, but if I set the root to the site files HTTPS gets redirected to HTTP. No error messages.

Any ideas?

user  www-data;
worker_processes  4;

error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}

http {
    passenger_root /usr/local/rvm/gems/ruby-1.9.3-p448/gems/passenger-4.0.14;
    passenger_ruby /usr/local/rvm/wrappers/ruby-1.9.3-p448/ruby;

    include       mime.types;
    default_type  application/octet-stream;

    #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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  www.nope.se;

    passenger_enabled on; 
    root /var/www/current/public/;

        #charset koi8-r;

        #access_log  logs/host.access.log main;

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #    root   html;
        #}

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    server {
        listen       443;
        server_name  www.nope.se;

        ssl                  on;
        ssl_certificate      /opt/nginx/cert/www.nope.se.crt;
        ssl_certificate_key  /opt/nginx/cert/www.nope.se.key;

        ssl_session_timeout  10m;

        #ssl_protocols  SSLv2 SSLv3 TLSv1;
        #ssl_ciphers  HIGH:!aNULL:!MD5;
        #ssl_prefer_server_ciphers   on;

    passenger_enabled on;
        root /var/www/current/public/;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    }

}

Upvotes: 1

Views: 1140

Answers (1)

Litmus
Litmus

Reputation: 10986

I honestly do not understand your question. But here is some gyan on how a typical nginx-https configuration is done. hope you find it useful.

SSL is a protocol that works one layer below HTTP. Think of it as a tunnel inside which HTTP protocol travels. Hence your SSL certificates are loaded, no matter where you specify them, before any HTTP related configuration. This is also the reason why there should be only one SSL setting per nginx instance.

I recommend that you move your ssl certificate related logic to a separate server block like this.

server {
   listen                    443 ssl default_server;
   ssl_certificate           ssl/website.pem;
   ssl_certificate_key       ssl/website.key;
   ssl_trusted_certificate   ssl/ca.all.pem;
   ssl_session_cache         builtin:1000     shared:SSL:10m;  
   ssl_session_timeout       5m;


   ssl_protocols             SSLv3 TLSv1 TLSv1.1 TLSv1.2; # default on newer versions
   ssl_prefer_server_ciphers on;

   # The following is all one long line. We use an explicit list of ciphers to enable
   # forward secrecy without exposing ciphers vulnerable to the BEAST attack

   ssl_ciphers  ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:RC4-SHA:RC4-MD5:ECDHE-RSA-AES256-SHA:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:AES128-SHA;

   # The following is for reference. It needs to be specified again
   # in each virtualhost, in both HTTP and non-HTTP versions.
   # All this directive does it to tell the browser to use HTTPS version of the site and remember this for a month
  add_header                Strict-Transport-Security    max-age=2592000;
}

I also recommend that you set a 301 redirect in your non-https server block as shown below.

Change this:

 server {
    listen       80;
    server_name  www.nope.se;  
    ... 
 }

to something like this:

server {
    listen       80;
    server_name  www.nope.se;
    add_header   Strict-Transport-Security  max-age=7200;
    return       301                        https://$host$request_uri;
 }

With this in place, when a user visits http://www.nope.se they will be automatically redirected to https://www.nope.se

Upvotes: 2

Related Questions