Nginx без www для www и www для no-www

426

Я использую nginx в облаке Rackspace после учебника и просматривая сеть и до сих пор не могу ее отсортировать.

Я хочу, чтобы www.mysite.com перешел на mysite.com как обычно в .htaccess для SEO и других причин.

Мой /etc/nginx/sites-available/www.example.com.vhost config:

server {
       listen 80;
       server_name www.example.com example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

Я также пробовал

server {
       listen 80;
       server_name example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

Я тоже пробовал. Обе второй попытки дают ошибки цикла перенаправления.

if ($host = 'www.example.com' ) {
rewrite ^ http://example.com$uri permanent;
}

Мой DNS настроен как стандартный:

site.com 192.192.6.8 A type at 300 seconds
www.site.com 192.192.6.8 A type at 300 seconds

(примеры IP-адресов и папок использовались для примеров и помогали людям в будущем). Я использую Ubuntu 11.

  • 0
    Я чувствую себя обязанным прокомментировать, что, если вы работаете с сайтом WordPress, проверьте « Dashboard > Settings > General Settings и убедитесь, что в URL-адресах WordPress-адресов / адресов сайтов нет www . Независимо от того, как вы сконфигурируете свой nginx, если у вас есть www в этих URL, он будет перенаправлен на тот, в котором есть www.
Теги:
nginx
redirect
rackspace
no-www

16 ответов

788
Лучший ответ

Решение HTTP

Из документации, "правильный способ - определить отдельный сервер для example.org":

server {
    listen       80;
    server_name  example.com;
    return       301 http://www.example.com$request_uri;
}

server {
    listen       80;
    server_name  www.example.com;
    ...
}

Решение HTTPS

Для тех, кто хочет решение, включая https://...

server {
        listen 80;
        server_name www.domain.com;
        # $scheme will get the http protocol
        # and 301 is best practice for tablet, phone, desktop and seo
        return 301 $scheme://domain.com$request_uri;
}

server {
        listen 80;
        server_name domain.com;
        # here goes the rest of your config file
        # example 
        location / {

            rewrite ^/cp/login?$ /cp/login.php last;
            # etc etc...

        }
}

Примечание. Я изначально не включил https:// в мое решение, так как мы используем loadbalancers, а наш https://сервер - это SSL-сервер с высоким трафиком: мы не смешиваем https://и http://.


Чтобы проверить версию nginx, используйте nginx -v.

Strip www from url с перенаправлением nginx

server {
    server_name  www.domain.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}

server {
    server_name  domain.com;
    #The rest of your configuration goes here#
}

Таким образом, вам нужно иметь два кода сервера.

Добавить www в URL с перенаправлением nginx

Если вам нужно обратное, чтобы перенаправить с domain.com на www.domain.com, вы можете использовать это:

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    server_name  www.domain.com;
    #The rest of your configuration goes here#
}

Как вы можете себе представить, это просто противоположное и работает так же, как в первом примере. Таким образом, вы не снижаете оценки SEO, так как это полная перенаправление и перемещение. Нет WWW принудительно и каталог показан!

Некоторые из моих кодов, показанных ниже для лучшего обзора:

server {
    server_name  www.google.com;
    rewrite ^(.*) http://google.com$1 permanent;
}
server {
       listen 80;
       server_name google.com;
       index index.php index.html;
       ####
       # now pull the site from one directory #
       root /var/www/www.google.com/web;
       # done #
       location = /favicon.ico {
                log_not_found off;
                access_log off;
       }
}
  • 26
    +1 За уровень детализации
  • 3
    @puk ценю это. Nginx удивителен, но хорошая документация, которая обновляется с учетом версии сервера и изменений ОС и серверного оборудования, довольно утомительна. Лучший ресурс, который мне подходит, это howtoforge.com, поскольку он поддерживает облачные версии RackSpace. Некоторые из приведенных выше команд не будут работать в более поздних версиях. Но этот nginx / 0.8.54 - это, поверьте, лучший сервер nginx) не нужно обновлять или обновлять. Работает отлично. 100 000 уникальных хитов в день, в среднем 4200 транзакций в день. Nginx БЫСТРО. как использовать сайт без трафика.
Показать ещё 20 комментариев
363

На самом деле вам даже не нужно переписывать.

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...
}

В качестве ответа я получаю все больше голосов, но выше. Вы не должны использовать rewrite в этом контексте. Зачем? Потому что nginx должен обработать и начать поиск. Если вы используете return (который должен быть доступен в любой версии nginx), он сразу останавливает выполнение. Это предпочтительнее в любом контексте.

Переназначить как не-SSL, так и SSL для своего не-www-партнера:

server {
    listen               80;
    listen               443 ssl;
    server_name          www.example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    return 301 $scheme://example.com$request_uri;
}

server {
    listen               80;
    listen               443 ssl;
    server_name          example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    # rest goes here...
}

Переменная $scheme будет содержать только http, если ваш сервер только прослушивает порт 80 (по умолчанию), а параметр listen не содержит ключевое слово ssl. Не использовать переменную не принесет вам никакой производительности.

Обратите внимание, что вам нужно еще больше блоков сервера, если вы используете HSTS, потому что заголовки HSTS не должны отправляться по незашифрованным соединениям. Следовательно, вам нужны незашифрованные серверные блоки с переадресацией и зашифрованными серверными блоками с переадресацией и заголовками HSTS.

Перенаправить все на SSL (личная конфигурация в UNIX с IPv4, IPv6, SPDY,...):

#
# Redirect all www to non-www
#
server {
    server_name          www.example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:80;
    listen               *:443 ssl spdy;
    listen               [::]:80 ipv6only=on;
    listen               [::]:443 ssl spdy ipv6only=on;

    return 301 https://example.com$request_uri;
}

#
# Redirect all non-encrypted to encrypted
#
server {
    server_name          example.com;
    listen               *:80;
    listen               [::]:80;

    return 301 https://example.com$request_uri;
}

#
# There we go!
#
server {
    server_name          example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:443 ssl spdy;
    listen               [::]:443 ssl spdy;

    # rest goes here...
}

Я думаю, вы можете представить себе другие соединения с этим рисунком сейчас.

Больше моих конфигураций? Перейдите здесь и здесь.

  • 7
    Спасибо за это. Repped.
  • 0
    Нужна ли переменная $ схема?
Показать ещё 15 комментариев
30

Вы можете узнать, что хотите использовать одну и ту же конфигурацию для большего количества доменов.

Следующий фрагмент удаляет www перед любым доменом:

if ($host ~* ^www\.(.*)$) {
    rewrite / $scheme://$1 permanent;
}
  • 7
    Мне нравится этот способ лучше, чем выделенные серверные блоки. Изменить http на $scheme
  • 2
    Гораздо лучше, я не могу поверить, что многие из них жестко закодируют домены в конфиги для этой задачи.
Показать ещё 5 комментариев
27

Вам нужны два серверных блока.

Поместите их в ваш конфигурационный файл, например /etc/nginx/sites-available/sitename

Допустим, вы решили использовать http://example.com в качестве основного адреса.

Ваш конфигурационный файл должен выглядеть так:

server {
        listen 80;
        listen [::]:80;
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
}
server {
        listen 80;
        listen [::]:80;
        server_name example.com;

        # this is the main server block
        # insert ALL other config or settings in this server block
}

Первый блок сервера будет содержать инструкции для перенаправления любых запросов с префиксом "www". Он слушает запросы на URL с префиксом "www" и перенаправляет.

Больше ничего не делает.

Второй блок сервера будет содержать ваш основной адрес - URL, который вы хотите использовать. Все остальные настройки идут здесь, например, root, index, location и т.д. Проверьте файл по умолчанию для этих других настроек, которые вы можете включить в блок сервера.

Серверу нужны две DNS-записи.

Name: @ IPAddress: your-ip-address (for the example.com URL)

Name: www IPAddress: your-ip-address (for the www.example.com URL)

Для ipv6 создайте пару записей AAAA, используя ваш-ipv6-адрес.

22

Вот как это сделать для нескольких имен серверов www-no-www (я использовал это для поддоменов):

server {
        server_name 
             "~^www\.(sub1.example.com)$"
             "~^www\.(sub2.example.com)$"
             "~^www\.(sub3.example.com)$";
         return 301 $scheme://$1$request_uri ;
}
  • 1
    Это очень умно; плюс +1 за это.
  • 1
    Отличное решение, работает отлично! Спасибо :)
Показать ещё 1 комментарий
16

Это решение исходит из моего личного опыта. Мы использовали несколько кодов Amazon S3 и один сервер для перенаправления доменных имен non-www в www в соответствии с S3 "Host" .

Я использовал следующую конфигурацию для сервера nginx:

server {
    listen 80;
    server_name ~^(?!www\.)(?<domain>.+)$;
    return 301 $scheme://www.$domain$request_uri;
}

Это соответствует всем доменным именам, указанным на сервере, начиная с любого, кроме www., и перенаправляется на www.<domain>. Таким же образом вы можете сделать противоположное перенаправление от www до non-www.

  • 0
    что насчет https? примечание: https НУЖЕН сертификат
  • 0
    Здесь нет абсолютно никаких проблем с HTTPS. После listen 80 необходимо добавить директивы listen 443 ssl а затем директивы ssl_certificate и ssl_certificate_key .
Показать ещё 3 комментария
11

попробуйте это

    if ($host !~* ^www\.){
        rewrite ^(.*)$ https://www.yoursite.com$1;
    }

Другой способ: Nginx no-www to www

server {
  listen       80;
  server_name  yoursite.com;
  root /path/;
  index index.php;
  return       301 https://www.yoursite.com$request_uri;
}

и www на no-www

server {
  listen       80;
  server_name  www.yoursite.com;
  root /path/;
  index index.php;
  return       301 https://yoursite.com$request_uri;
}
  • 1
    Как правило, лучше избегать If, как указано ниже: wiki.nginx.org/IfIsEvil
  • 0
    Почему авторы предоставили if-заявление в nginx, а затем сказали людям избегать его? Звучит легкомысленно для меня.
Показать ещё 2 комментария
10

Я объединил лучшие из всех простых ответов, без жестко закодированных доменов.

301 постоянная переадресация с не-www на www (HTTP или HTTPS):

server {
    if ($host !~ ^www\.) {
        rewrite ^ $scheme://www.$host$request_uri permanent;
    }

    # Regular location configs...
}

Если вы предпочитаете не-HTTPS, не-www для HTTPS, перенаправление WWW в одно и то же время:

server {
    listen 80;

    if ($host !~ ^www\.) {
        rewrite ^ https://www.$host$request_uri permanent;
    }

    rewrite ^ https://$host$request_uri permanent;
}
  • 0
    Отличный ответ. Я слышал, что использование Else было "злом"?
8

Перенаправить не-www на www

Для одного домена:

server {
        server_name example.com;
        return 301 $scheme://www.example.com$request_uri;
}

Для всех доменов:

server {
        server_name "~^(?!www\.).*" ;
        return 301 $scheme://www.$host$request_uri;
}

Перенаправить www на не-www Для одного домена:

server {
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
}

Для всех доменов:

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
}
  • 0
    Не могли бы вы указать разницу между 80 и 443 ?
  • 0
    Они не будут работать без директив listen
Показать ещё 1 комментарий
7

Уникальный формат:

server {
  listen 80;
  server_name "~^www\.(.*)$" ;
  return 301 https://$1$request_uri ;
}
  • 1
    Вы можете сделать его общим, написав его так: server { server_name "~^www\.(.*)$" ; return 301 $scheme://$1$request_uri ; }
4
location / { 
    if ($http_host !~ "^www.domain.com"){ 
        rewrite ^(.*)$ $scheme://www.domain.com/$1 redirect; 
    } 
}
  • 1
    $scheme://www.domain.com$1 чтобы избежать двойной косой черты
3

не уверен, что кто-нибудь заметит, что может быть правильно вернуть 301, но браузер заставляет его делать

rewrite ^(.*)$ https://yoursite.com$1; 

быстрее, чем:

return 301 $scheme://yoursite.com$request_uri;
  • 1
    Нет, это не так: nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/…
  • 1
    мой комментарий был направлен на браузер, а не на эффективность на стороне nginx! с редиректом браузер делает 2 запроса против 1 запроса при переключении
2

Блог призраков

чтобы сделать рекомендованный nginx метод с return 301 $scheme://example.com$request_uri; работать с Ghost, вам нужно добавить в свой основной серверный блок:

proxy_set_header    X-Real-IP           $remote_addr;
proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
proxy_set_header    Host                $http_host;
proxy_set_header    X-Forwarded-Proto   $scheme;
proxy_set_header    X-NginX-Proxy       true;

proxy_pass_header   X-CSRF-TOKEN;
proxy_buffering     off;
proxy_redirect      off;  
0
  1. Рекомендация: отдельный server с жестко server_name

Лучшая практика с nginx - использовать отдельный server для перенаправления, подобного этому (не используется совместно с server вашей основной конфигурации), жестко кодировать все и вообще не использовать регулярные выражения.

Также может быть необходимо жестко закодировать домены, если вы используете HTTPS, потому что вы должны заранее знать, какие сертификаты вы будете предоставлять.

server {
    server_name www.example.com;
    return  301 $scheme://example.com$request_uri;
}
server {
    server_name www.example.org;
    return  301 $scheme://example.org$request_uri;
}
server {
    server_name example.com example.org;
    # real configuration goes here
}

  1. Использование регулярных выражений внутри server_name

Если у вас есть несколько сайтов, и вы не заботитесь о максимальной производительности, но хотите, чтобы у каждого из них была одинаковая политика в отношении www. Префикс, то вы можете использовать регулярные выражения. Лучшая практика использования отдельного server остается в силе.

Обратите внимание, что это решение становится сложным, если вы используете https, так как у вас должен быть один сертификат, чтобы покрыть все ваши доменные имена, если вы хотите, чтобы это работало должным образом.


non- с www по www с regex на отдельном server для всех сайтов:

server {
    server_name ~^(?!www\.)(?<domain>.+)$;
    return  301 $scheme://www.$domain$request_uri;
}

www to non- www w/regex на отдельном выделенном server для всех сайтов:

server {
    server_name ~^www\.(?<domain>.+)$;
    return  301 $scheme://$domain$request_uri;
}

www to non- www w/regex на выделенном server для некоторых сайтов:

Может быть необходимо ограничить регулярное выражение только для нескольких доменов, тогда вы можете использовать что-то подобное, чтобы соответствовать только www.example.org, www.example.com и www.subdomain.example.net:

server {
    server_name ~^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$;
    return  301 $scheme://$domain$request_uri;
}

Тестирование регулярных выражений с nginx

Вы можете проверить, что регулярное выражение работает, как и ожидалось, с pcretest в вашей системе, которая является той же самой библиотекой pcre которую ваш nginx будет использовать для регулярных выражений:

% pcretest 
PCRE version 8.35 2014-04-04

  re> #^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$#
data> test
No match
data> www.example.org
 0: www.example.org
 1: example.org
data> www.test.example.org
No match
data> www.example.com
 0: www.example.com
 1: example.com
data> www.subdomain.example.net
 0: www.subdomain.example.net
 1: subdomain.example.net
data> subdomain.example.net
No match
data> www.subdomain.example.net.
No match
data> 

Обратите внимание, что вам не нужно беспокоиться о конечных точках или регистре, поскольку nginx уже позаботился об этом, согласно регулярному выражению имени сервера nginx, когда заголовок "Host" имеет конечную точку.


  1. Посыпать, if внутри существующего server/HTTPS:

Это окончательное решение, как правило, не считается лучшей практикой, однако оно все еще работает и выполняет свою работу.

На самом деле, если вы используете HTTPS, то это окончательное решение может оказаться проще в обслуживании, поскольку вам не придется копировать и вставлять целую кучу директив ssl между различными определениями server, а вместо этого можно размещать только фрагменты на необходимые серверы, что облегчает отладку и поддержку ваших сайтов.


non- с www на www:

if ($host ~ ^(?!www\.)(?<domain>.+)$) {
    return  301 $scheme://www.$domain$request_uri;
}

www по non- www:

if ($host ~ ^www\.(?<domain>.+)$) {
    return  301 $scheme://$domain$request_uri;
}

жесткое кодирование одного предпочтительного домена

Если вам нужна чуть более высокая производительность, а также согласованность между несколькими доменами, которые может использовать один server, все равно может иметь смысл явно жестко кодировать один предпочтительный домен:

if ($host != "example.com") {
    return  301 $scheme://example.com$request_uri;
}

Рекомендации:

0
if ($host ~* ^www.example.com$) {
    return 301 $scheme://example.com$request_uri;
}
-6

Если у вас возникли проблемы с этим, вам может потребоваться добавить IP-адрес вашего сервера. Например:

server {
listen XXX.XXX.XXX.XXX:80;
listen XXX.XXX.XXX.XXX:443 ssl;
ssl_certificate /var/www/example.com/web/ssl/example.com.crt;
ssl_certificate_key /var/www/example.com/web/ssl/example.com.key;
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}

где XXX.XXX.XXX.XXX - это IP-адрес (очевидно).

Примечание: ssl crt и местоположение ключа должны быть определены для правильной перенаправления запросов https

Не забудьте перезапустить nginx после внесения изменений:

service nginx restart
  • 3
    /etc/init.d/nginx reload вы также можете reload сервер, что не вызывает простоев.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню