I know this must have been answered already, but I have been searching for quite a while, and cannot find the answer. Just not looking in the right place I guess, maybe someone can help me out.

Basically I am running phpmyadmin through SSL on a non-standard port, in this example 12345.

Now I have https://mydomain.com:12345 set up ok, it works and everything. Now I want to add the ability to just type http://mydomain.com:12345 and be redirected to the https://.

I asumed the following would work, but it does not.

server {
  listen        12345;
  server_name   php.myadmin.com;

  if ( $scheme = http ) {
    rewrite ^ https://php.myadmin.com:12345$request_uri? redirect;
  }
  root         /var/www/php;

  ssl           on;

  [....]
}

This gives me a 400 bad request.

Now before posting an answer make sure to have a good look at the redirect form. Check the pitfall in the link bellow.

http://wiki.nginx.org/Pitfalls#Taxing_Rewrites

Further, it would be nice if this can even be done without an if-statement:

http://wiki.nginx.org/Pitfalls#Using_If

link|improve this question

feedback

4 Answers

up vote 6 down vote accepted

You can't have both http and https running on the same port.
They're mutually exclusive. What you're asking for is not possible.

link|improve this answer
No I do not want them both on the same port. I just want to redirect http to https. So only https runs on the port, but http is redirected. Or is even that not possible. There is just one site at that location – Saif Bechan Dec 7 '11 at 20:34
3  
Oh no I understand! The usual setup is http on port 80, and https on 443, and then 80 is redirected to 443. Now I want to redirect 12345 to 12345 and that is not possible. That makes sense. thanks! – Saif Bechan Dec 7 '11 at 20:37
feedback

Unfortunately, you can't handle http and https requests using a single port with nginx.

What you can do is have a proxy pre-handle requests, however. This is how we handle the scheme-processing:

set $real_scheme http;
if ($http_x_forwarded_proto) { set $real_scheme $http_x_forwarded_proto; }

set $target_scheme https;

if ($real_scheme != $target_scheme) {
  rewrite ^ $target_scheme://$host$request_uri redirect;
}
link|improve this answer
+1 Ok, I do not understand that piece of code at all. I will try it, but it looks pretty complicated. I think I will just access the domain using the complete url, begin php.myadmin.com:12345. – Saif Bechan Dec 7 '11 at 20:57
feedback

I do exactly this. gWaldo is correct, but you don't want to serve content over HTTP, just a redirect. The trick is to catch the http-on-an-https-port error and use that to bounce the client to the correct place.

server {
    listen   12345;
    server_name  my.domain.com;

    ssl on;
    ssl_certificate /etc/ssl/certs/your.pem;
    ssl_certificate_key /etc/ssl/private/your.key;

    # If they come here using HTTP, bounce them to the correct scheme
    error_page 497 https://$host:$server_port$request_uri;

    location / {
        # Your config here...
    }
}
link|improve this answer
feedback

You can redirect access to port 80 to port 443 (to work with the default ports). But this would require you to run iptables on that host.

Not sure if you would get a 400 as well because of the SSL, but that is basically how transparent proxying works.

 iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 443

Apart from that you can redirect http-requests from port 80 to port 443 (or any port combo) in nginx, but not have them work on the same port, just like mentioned above.

EDIT: As mentioned/commented below this approach will result in a 400 due to protocol mixture.

Would it be an option to programmatically solve the problem? Try to use something like the following snippet at the top of your starter file in phpMyAdmin. This should redirect your initial call to https. After that, the rest of your page is under the SSL context anyways as long as you configured it to be served via SSL (of course).

<?php
 if ($_SERVER['SERVER_PORT']!=443) {
     $url = "https://". $_SERVER['SERVER_NAME'] . ":443".$_SERVER['REQUEST_URI'];
     header("Location: $url");
 }
?>

(Doesn't explicitly save you from jumping in w/o SSL, e.g. via bookmark as long as your session is still valid)

link|improve this answer
Yeah I know about the 80 -> 433 port redirect. You do not need iptables for that in nginx, it's just a small config. The thing is I want to run phpmyadmin on non-standard ports, that's the whole issue. – Saif Bechan Dec 7 '11 at 20:55
You can't use iptables to do a http redirect, that's a protocol level function. The 400 error is coming in this case because http is taking over the port and the server can't figure out how to redirect to the same port on a different protocol (rightfully so as it's impossible). – Chris S Dec 7 '11 at 23:35
Thx for clarifying this. Updated my answer to reflect it. Maybe the programmers approach is helping tho. – Chris Dec 8 '11 at 9:30
feedback

Your Answer

 
or
required, but never shown

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