Nginx без www для www и www для no-www
Я использую 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.
19 ответов
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
,
Уберите www с URL с помощью nginx redirect
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;
}
}
На самом деле вам даже не нужно переписывать.
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 (по умолчанию) и опция прослушивания не содержит 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...
}
Я предполагаю, что вы можете представить себе другие соединения с этим паттерном сами.
Лучшая практика: отдельно
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
}
Использование регулярных выражений в
server_name
Если у вас есть несколько сайтов, и вы не заботитесь о максимальной производительности, но хотите, чтобы у каждого из них была одинаковая политика в отношении www.
Префикс, то вы можете использовать регулярные выражения. Лучшая практика использования отдельного server
все равно будет стоять
Обратите внимание, что это решение становится сложным, если вы используете https, так как у вас должен быть один сертификат для всех ваших доменных имен, если вы хотите, чтобы это работало должным образом.
не- www
в www
с регулярным выражением в выделенном сингле server
для всех сайтов:
server {
server_name ~^(?!www\.)(?<domain>.+)$;
return 301 $scheme://www.$domain$request_uri;
}
www
не- www
с регулярным выражением в выделенном сингле server
для всех сайтов:
server {
server_name ~^www\.(?<domain>.+)$;
return 301 $scheme://$domain$request_uri;
}
www
не- www
с регулярным выражением в выделенном 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" имеет конечную точку.
кропить
if
в рамках существующихserver
/ HTTPS:
Это окончательное решение, как правило, не считается лучшей практикой, однако оно все еще работает и выполняет свою работу.
На самом деле, если вы используете HTTPS, это окончательное решение может оказаться проще в обслуживании, поскольку вам не придется копировать и вставлять целую кучу директив ssl между различными server
определения, и вместо этого может размещать фрагменты только на необходимые серверы, упрощая отладку и поддержку ваших сайтов.
не- www
в www
:
if ($host ~ ^(?!www\.)(?<domain>.+)$) {
return 301 $scheme://www.$domain$request_uri;
}
www
не- www
:
if ($host ~ ^www\.(?<domain>.+)$) {
return 301 $scheme://$domain$request_uri;
}
жесткое кодирование одного предпочтительного домена
Если вы хотите немного больше производительности, а также согласованность между несколькими доменами одного server
может использовать, все же имеет смысл явно жестко закодировать один предпочтительный домен:
if ($host != "example.com") {
return 301 $scheme://example.com$request_uri;
}
Рекомендации:
Вы можете узнать, что хотите использовать одну и ту же конфигурацию для большего количества доменов.
Следующий фрагмент удаляет www перед любым доменом:
if ($host ~* ^www\.(.*)$) {
rewrite / $scheme://$1 permanent;
}
Вам нужны два серверных блока.
Поместите их в свой конфигурационный файл, например /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-адрес.
Вот как это сделать для нескольких имен серверов с www на no-www (я использовал это для поддоменов):
server {
server_name
"~^www\.(sub1.example.com)$"
"~^www\.(sub2.example.com)$"
"~^www\.(sub3.example.com)$";
return 301 $scheme://$1$request_uri ;
}
Я объединил лучшие из всех простых ответов, без жестко закодированных доменов.
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;
}
Это решение исходит из моего личного опыта. Мы использовали несколько корзин 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
,
Попробуй это
if ($host !~* ^www\.){
rewrite ^(.*)$ https://www.yoursite.com$1;
}
Другой способ: Nginx без www на 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;
}
Перенаправить не-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 ;
}
Уникальный формат:
server {
listen 80;
server_name "~^www\.(.*)$" ;
return 301 https://$1$request_uri ;
}
Если вы не хотите жестко задавать доменное имя, вы можете использовать этот блок перенаправления. Домен без ведущего www сохраняется как переменная $domain
который может быть повторно использован в операторе перенаправления.
server {
...
# Redirect www to non-www
if ( $host ~ ^www\.(?<domain>.+) ) {
rewrite ^/(.*)$ $scheme://$domain/$1;
}
}
REF: перенаправление субдомена с регулярным выражением в nginx
location / {
if ($http_host !~ "^www.domain.com"){
rewrite ^(.*)$ $scheme://www.domain.com/$1 redirect;
}
}
Не уверен, если кто-то заметит, что это может быть правильным, чтобы вернуть 301, но браузеры не хотят делать это
rewrite ^(.*)$ https://yoursite.com$1;
быстрее чем:
return 301 $scheme://yoursite.com$request_uri;
Призрачный блог
чтобы сделать 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;
моя конфигурация была - Nginx + tomcat 9 + Ubuntu 20.04 + весеннее загрузочное приложение, все ответы выше не работают для меня - также не работают восходящие обозначения в файле Nginx - поэтому я меняю свои настройки на этом
спасибо Богу за certbot - эта утилита очень полезна, она генерирует базовый файл для вашего сайта, а затем я добавил свои изменения - для перенаправленияhttps://www.example.com
,http://www.example.com
только одномуhttps://example.com
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
}
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080; # This is upstream name, note the variable $scheme in it
proxy_redirect off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.example.com) {
return 301 https://example.com$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
Добавьте CNAME с помощью cloudflare и используйте этот формат в качестве файла конфигурации.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass "http://localhost:3000/";
}}
if ($host ~* ^www.example.com$) {
return 301 $scheme://example.com$request_uri;
}
Если у вас возникли проблемы с этим, вам может понадобиться добавить 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