Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I'd like only my base domain www.domain.com to be rewritten to https://www.domain.com By default in my https block I have it reroute to http:// if it's not ~uri = "/" (base domain) or static content.

server {
  listen              443;
  set $ssltoggle 2;
  if ($uri ~ ^/(img|js|css|static)/) {
      set $ssltoggle 1;
  }
  if ($uri = '/') {
      set $ssltoggle 1;
  }
  if ($ssltoggle != 1) {
      rewrite ^(.*)$ http://$server_name$1 permanent;
  }
}

So in my http block I need to do the rewrite if it has to https:

server {
  listen              80;
  if ($uri = '/') {
      set $ssltoggle 1;
  }
  if ($ssltoggle = 1) {
      rewrite ^(.*)$ https://$server_name$1 permanent;
  }
}

If I don't have the $uri = '/' if-statement in the http block, then https works fine if I go directly to it, but I won't get redirected if I go to regular http which is expected. If I do put that in-statement in the http block then everything stops working within minutes. It might work for a few requests, but will always stop within a minute or so. In browsers I just get a blank page for all requests. If I restart nginx it continues to not work until I remove both if-statement blocks in both the https and http blocks and restart nginx. When I look in the error logs I don't see anything logged. When I look in the access log I see this message:

"-" 400 0 "-" "-"

which I assume means a 400 error. I don't understand why this doesn't work for me. My end goal is to have the base domain be https-only while all other pages default to http. How can I achieve this?

share|improve this question
add comment

2 Answers 2

You dont need all the if statements. You should work with location satements.

server {
    listen              80;
    #rewrite base (/) to ssl
    location = / {
        rewrite ^(.*)$ https://$server_name$1 permanent;
    }

    #serve anything else
    location / {
        [serve non-ssl page ...]
    }
}

server {
    listen              443;

    #serve base url
    location = / {
        [serve ssl page ...]
    }

    #serve assets
    location ~ ^/(img|js|css|static)/ {
        [serve ssl assets ...]
    }

    #rewrite anything else
    location / {
        rewrite ^(.*)$ https://$server_name$1 permanent;
    }
}

This is untested and might contian errors but should work

share|improve this answer
    
I just provided a far simplified version of my config file to show my issue. The IF statements serve multiple purposes. With your solution I believe domain.com?arg1=1&arg2=2 would fall into location = / and then rewrite to https. If it's $uri I'm looking at then if there arguments it'll stay http. I actually tried this already though and just got redirect loops on the based domain which I have a difficult time understanding. It feels like the IF statements are still active even if I put the location statement first. –  jchysk Sep 30 '12 at 18:31
    
The location statement does the same as your if statement in respect to checking the paths. I think there is no difference if you are using parameters. I'd have to check that. –  Christopher Perrin Sep 30 '12 at 18:36
add comment
up vote 1 down vote accepted

I ended up changing the $uri to $request_uri so args can be handled without redirect loops.

server {
  listen              443;
  set $ssltoggle 2;
  if ($uri ~ ^/(img|js|css|static)/) {
      set $ssltoggle 1;
  }
  if ($request_uri = '/') {
      set $ssltoggle 1;
  }
  if ($ssltoggle != 1) {
      rewrite ^(.*)$ http://$server_name$1 permanent;
  }
}

Then I changed the http block to do an immediate rewrite if the location was = /

server {
  listen              80;
  location = / {
      rewrite ^(.*)$ https://$server_name$1 permanent;
  }
  if ($ssltoggle = 1) {
      rewrite ^(.*)$ https://$server_name$1 permanent;
  }
}

I have the IF statements still to handle other rewrites and then all the specific serving is done below those. It's probably just my specific configuration that results in redirect loops and errors when I attempt to handle everything as Christopher suggested or the way I originally presented in my question.

share|improve this answer
    
if curious here's my entire nginx file: pastebin.com/FewnrnFU –  jchysk Sep 30 '12 at 18:52
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.