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.

How do I set up Nginx conf file to force SSL on only one of the paths in my site and non-SSL on all the rest?

For example, I want all of the URLs under /user to be https but all the rest of the URLs to be http.

For the first part I have:

rewrite ^/user(.*) https://$http_host$request_uri?;

I don't want to use "if". I assume it would take advantage of order of operation but I don't want to end up in a loop.

share|improve this question

2 Answers 2

up vote 13 down vote accepted

In your nginx configuration, you should have two "server" areas. One for port 80, and one for port 443 (non-SSL and SSL). Simply add a location in your non-SSL website to redirect to your SSL page.

server {
    root /var/www/
    location / {
    }
    location /user {
        rewrite ^ https://$http_host$request_uri? permanent;
    }
}

it will forward all traffic that ends up at /user to your https:// server.

Then, in your 443 server, you do the opposite.

server {
    listen 443;
    root /var/www/
    location / {
        rewrite ^ http://$http_host$request_uri? permanent;
    }
    location /user {
    }
}
share|improve this answer
1  
Oh, man, that's so easy! Perfect, thanks. –  pbreitenbach May 16 '11 at 22:12
    
This approach is good, but it falls into a couple of common Pitfalls, specifically "Root inside location block" and "Taxing rewrites" –  kolbyjack May 17 '11 at 1:11
    
I edited. Does it look OK? I also took out listen 80 and added http_host. –  pbreitenbach May 18 '11 at 4:23
    
oh yes, thanks! –  Pineapple Under the Sea Aug 12 '12 at 1:54
    
thanks for the dual option, thats what im looking for –  Hayden Thring Jan 19 '13 at 11:04

Nginx allows to process both HTTP and HTTPS within the same server block. Thus you don't have to duplicate directives for both and can redirect the path you want to secure

server {
  listen 80 default_server;
  listen 443 ssl;
  ... ssl certificate and other configs ...

  location /user {
    if ($scheme = 'http') {
      rewrite ^ https://$http_host$request_uri? permanent;
    }
  }

  ... your basic configuration ...
}

Be sure not to put ssl on line there because it'll break plain HTTP.

Optionally, you can redirect all other requests from HTTPS back to HTTP the same way:

if ($scheme = 'https') {
  rewrite ^ http://$http_host$request_uri? permanent;
}

UPDATE: as Alexey Ten kindly points out in comments section, checking scheme on each request is not a very bright idea. You should follow declarative way of configuring your nginx. In this case, declare two server blocks with redirects by location, move common logic to a separate file and include it in both. So GruffTech's answer is better.

share|improve this answer
    
It's ineffective to make nginx check scheme for every request. –  Alexey Ten Jun 16 at 7:48
    
I know the question was answered 3 years ago, but I found it while struggling to do what I gradually did and just wanted to share my results with people who will follow my steps. –  Hnatt Jun 16 at 7:48
    
Well, you should read wiki.nginx.org/IfIsEvil –  Alexey Ten Jun 16 at 7:50
    
@AlexeyTen isn't it the case "when you can't avoid using an if"? Is there any other way to have same configuration for HTTP and HTTPS without duplicating directives? –  Hnatt Jun 16 at 7:52
    
It is. Two server blocks perfectly split requests without if –  Alexey Ten Jun 16 at 7:52

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.