How to get nginx to redirect from www to non-www domain?
Let's say I want to redirect from www.example.com to example.com and I want to do this using nginx. I looked around and did not see any good documentation on this so I figured I would ask and answer my own question.
I also looked at this on the Nginx wiki and other blogs and the best way performance wise is to do the following:
To redirect from www.example.com to example.com using nginx (version 1.0.12 at time of writing).
server {
server_name www.example.com;
rewrite ^ $scheme://example.com$request_uri permanent;
# permanent sends a 301 redirect whereas redirect sends a 302 temporary redirect
# $scheme uses http or https accordingly
}
server {
server_name example.com;
# the rest of your config goes here
}
When requests come to example.com, no if statements are used for performance. And it uses $request_uri rather than having to create a $1 match which taxes the rewrite (see Nginx Common Pitfalls page).
Sources:
- https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#server-name-if
- http://wiki.nginx.org/NginxHttpCoreModule#.24scheme
After some digging around and some missteps, here is the solution. The gotcha I ran into is to make sure to use "http://example.com$uri". Inserting a / in front of $uri results in a redirect to http://example.com//
server {
listen 80;
server_name www.example.com;
rewrite ^ http://example.com$uri permanent;
}
# the server directive is nginx's virtual host directive.
server {
# port to listen on. Can also be set to an IP:PORT
listen 80;
# Set the charset
charset utf-8;
# Set the max size for file uploads to 10Mb
client_max_body_size 10M;
# sets the domain[s] that this vhost server requests for
server_name example.com;
# doc root
root /var/www/example.com;
# vhost specific access log
access_log /var/log/nginx_access.log main;
# set vary to off to avoid duplicate headers
gzip off;
gzip_vary off;
# Set image format types to expire in a very long time
location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ {
access_log off;
expires max;
}
# Set css and js to expire in a very long time
location ~* ^.+\.(css|js)$ {
access_log off;
expires max;
}
# Catchall for everything else
location / {
root /var/www/example.com;
access_log off;
index index.html;
expires 1d;
if (-f $request_filename) {
break;
}
}
}
Please visit this question in SO: https://stackoverflow.com/a/11733363/846634
From the better answer:
Actually you don't even need a rewrite.
server {
#listen 80 is default
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}
server {
#listen 80 is default
server_name example.com;
## here goes the rest of your conf...
}
As my answer is getting more and more up votes but the above as well. You should never use a rewrite
in this context. Why? Because nginx has to process and start a search. If you use return
(which should be available in any nginx version) it directly stops execution. This is preferred in any context.