Nginx no-www na www i www na no-www


497

Używam nginx w chmurze Rackspace po samouczku i po przeszukaniu sieci i jak dotąd nie mogę tego posortować.

Chcę, aby www.mysite.com przechodziła do mysite.com jak zwykle w .htaccess z SEO i innych powodów.

Mój /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;
       }

Próbowałem też

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

Też próbowałem. Obie drugie próby powodują błędy pętli przekierowania.

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

Mój DNS jest skonfigurowany standardowo:

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

(przykładowe adresy IP i foldery zostały użyte jako przykłady i aby pomóc ludziom w przyszłości). Używam Ubuntu 11.


1
Czuję się zmuszony do skomentowania, że ​​jeśli pracujesz ze stroną WordPress, sprawdź Dashboard > Settings > General Settingsi upewnij się, że nie ma żadnych wwwadresów URL adresu / adresu strony WordPress. Bez względu na to, jak skonfigurujesz swój nginx, jeśli masz www w tych adresach URL, zostanie przekierowane do tego z www w nim.
Abhinav Sood

Odpowiedzi:


792

Rozwiązanie HTTP

Z dokumentacji „właściwym sposobem jest zdefiniowanie osobnego serwera dla 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;
    ...
}

Rozwiązanie HTTPS

Dla tych, którzy chcą rozwiązania, w tym 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...

        }
}

Uwaga: pierwotnie nie https://zawarłem rozwiązania, ponieważ korzystamy z loadbalancerów, a nasz serwer https: // to serwer płatności SSL o dużym ruchu: nie mieszamy https: // i http: //.


Aby sprawdzić wersję nginx, użyj nginx -v.

Usuń www z adresu URL z przekierowaniem 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#
}

Musisz mieć DWIE kody serwerów.

Dodaj www do adresu URL za pomocą przekierowania nginx

Jeśli potrzebujesz czegoś przeciwnego, aby przekierować z domain.com na www.domain.com, możesz użyć tego:

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

Jak możesz sobie wyobrazić, jest odwrotnie i działa tak samo jak w pierwszym przykładzie. W ten sposób nie obniżysz znaków SEO, ponieważ jest to pełne przekierowanie perm i ruch. Brak stron WWW jest wymuszony, a katalog pokazany!

Niektóre z mojego kodu pokazano poniżej dla lepszego widoku:

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

3
@ puk to doceniam. Nginx jest niesamowity, ale dobra dokumentacja, która jest na bieżąco z wersją serwera oraz zmianami systemu operacyjnego i sprzętu serwera, jest dość męcząca. Najlepszym zasobem, który mi służy, jest howtoforge.com, ponieważ obsługuje wersje chmurowe RackSpace. Niektóre z powyższych poleceń nie będą działać w późniejszych wersjach. Ale ten nginx / 0.8.54 - wierzy mi, najlepszy serwer nginx) nie wymaga aktualizacji ani aktualizacji. Działa w porządku. 100 000 unikalnych trafień dziennie ze średnią 4200 transakcji dziennie. Nginx jest RAPID. jak korzystanie z witryny bez ruchu.
TheBlackBenzKid

17
Twoje przepisania powinny stać się zwrotami, jak w return 301 $scheme://domain.com$request_uri;. Nie ma potrzeby rejestrować żadnych wzorów, patrz pułapki Nginx
Roberto,

4
@TheBlackBenzKid Przepraszamy, może coś przeoczyłem, ale zaktualizowane rozwiązanie nie działa. To dlatego, że słuchaj 80 - przy tym mówisz, że tylko HTTP pasuje do tego. Powinno być więcej portów do nasłuchiwania, jeśli ta sama konfiguracja jest używana dla HTTP i HTTPS ... Lub? Ale zdecydowanie mi pomógł, +1. Dzięki za odpowiedź. Twoje zdrowie.
tomis

3
@TheBlackBenzKid To była tylko notatka. Znalazłem działające rozwiązanie. W twoim przykładzie należy dodać tylko Listen 443 i zakończyć działanie.
tomis

2
odpowiedź jest zła. przekierowuje wszystkie subdomeny na www.
r3wt

398

W rzeczywistości nie potrzebujesz nawet przepisywania.

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

Ponieważ moją odpowiedzią jest coraz więcej głosów, ale także powyższe. Nigdy nie należy używać rewritew tym kontekście. Dlaczego? Ponieważ nginx musi przetworzyć i rozpocząć wyszukiwanie. Jeśli używasz return(który powinien być dostępny w dowolnej wersji nginx), to bezpośrednio zatrzymuje wykonywanie. Jest to preferowane w dowolnym kontekście.

Przekieruj zarówno non-SSL, jak i SSL na ich odpowiednik inny niż 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...
}

$schemeZmienna będzie zawierać tylko httpjeśli serwer nasłuchuje tylko na porcie 80 (domyślnie) i opcji nie zawierają słuchać sslsłowa kluczowego. Nieużywanie zmiennej nie przyniesie żadnej wydajności.

Pamiętaj, że potrzebujesz więcej bloków serwerów, jeśli używasz HSTS, ponieważ nagłówki HSTS nie powinny być wysyłane przez niezaszyfrowane połączenia. Dlatego potrzebujesz niezaszyfrowanych bloków serwera z przekierowaniami i szyfrowanych bloków serwera z przekierowaniami i nagłówkami HSTS.

Przekieruj wszystko do SSL (konfiguracja osobista w UNIX z 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...
}

Myślę, że możesz sobie teraz wyobrazić inne związki z tym wzorem.

Więcej moich konfiguracji? Idź tu i tutaj .


3
Twój Chrome nie powinien mieć dostępu do Twojej domeny www, jeśli korzystasz z HSTS. Otwórz nowe pytanie, podając jak najwięcej szczegółów, a pomogę ci (tutaj możesz opublikować adres URL pytania).
Fleshgrinder,

1
@Fleshgrinder Próbuję wdrożyć konfigurację, ale otrzymuję następujący problem na stackoverflow.com/questions/29451409/... Masz jakieś pomysły, jak to zrobić?
YPCrumble

4
W drugim bloku „Przekieruj zarówno non-SSL, jak i SSL do ich odpowiednika innego niż www:”, oba bloki serwera powinny mieć dyrektywy SSL, ponieważ przeglądarka musi zweryfikować cert dla www.example.com, zanim przekieruje do przykładu .com.
Jeff Tsay,

1
Oczywiście dodałem to, a także krótką informację o HSTS.
Fleshgrinder,

1
@YPCrumble tak, w ten sposób jest O DUŻO szybszy, ponieważ nie wykonujemy dopasowywania wyrażeń regularnych dla każdego żądania. Przekierowujemy tylko wtedy, gdy wiemy, że musimy przekierować. Bez czeków, sprawdzania poprawności, nic: po prostu przekieruj. =)
Fleshgrinder

37

Możesz dowiedzieć się, że chcesz użyć tej samej konfiguracji dla większej liczby domen.

Poniższy fragment usuwa www przed dowolną domeną:

if ($host ~* ^www\.(.*)$) {
    rewrite / $scheme://$1 permanent;
}

7
Podoba mi się to lepiej niż bloki serwerów dedykowanych. Zmień httpna$scheme
ck_

2
O wiele lepiej, nie mogę uwierzyć, że tak wiele domen koduje domeny na konfiguracje do tego zadania.
MrYellow

1
@Oli Ten link nie wspomina (na dzień dzisiejszy), ale raczej nie jest w 100% bezpieczny. Mówi: „Jedyne w 100% bezpieczne rzeczy, które można zrobić wewnątrz, jeśli w kontekście lokalizacji to: return ...i rewrite ... last”. Jakieś zaktualizowane linki do problemów z wydajnością?
Adam

1
To nie działało dla mnie. Wystąpił błąd w przeglądarce z nieprawidłową odpowiedzią.
Nico Brenner

1
Niestety nie znalazłem sposobu bez „if”. Używam tej samej konfiguracji dla wielu domen, kodowanie nazw domen nie jest opcją. Wszelkie sugestie / komentarze są mile widziane!
Martin Höger,

27

Potrzebujesz dwóch bloków serwera.

Umieść je w pliku konfiguracyjnym, np /etc/nginx/sites-available/sitename

Powiedzmy, że decydujesz się na http://example.com jako główny adres do użycia.

Twój plik konfiguracyjny powinien wyglądać następująco:

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
}

Pierwszy blok serwera będzie zawierał instrukcje przekierowywania wszelkich żądań z prefiksem „www”. Nasłuchuje żądań adresu URL z prefiksem „www” i przekierowuje.

Nie robi nic więcej.

Drugi blok serwera pomieści twój główny adres - adres URL, którego chcesz użyć. Wszystkie pozostałe ustawienia jak tu iść root, index, location, itd. Sprawdź plik domyślny dla innych ustawień, które można zawrzeć w bloku serwera.

Serwer potrzebuje dwóch rekordów DNS A.

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

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

W przypadku ipv6 utwórz parę rekordów AAAA, używając swojego adresu-ipv6.


23

Oto jak to zrobić dla wielu nazw serwerów www do no-www (użyłem tego dla subdomen):

server {
        server_name 
             "~^www\.(sub1.example.com)$"
             "~^www\.(sub2.example.com)$"
             "~^www\.(sub3.example.com)$";
         return 301 $scheme://$1$request_uri ;
}

20
  1. Najlepsza praktyka: osobno serverw / hardcodedserver_name

Najlepszą praktyką w przypadku nginx jest użycie oddzielnego serverdla takiego przekierowania (nieudostępnionego w servergłównej konfiguracji), zakodowanie wszystkiego na sztywno i nie używanie wyrażeń regularnych.

Konieczne może być również zakodowanie domen na stałe, jeśli używasz HTTPS, ponieważ musisz z góry wiedzieć, które certyfikaty będziesz zapewniał.

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. Używanie wyrażeń regularnych w obrębie server_name

Jeśli masz wiele witryn i nie dbasz o najwyższą wydajność, ale chcesz, aby każda z nich miała takie same zasady dotyczące www.prefiksu, możesz użyć wyrażeń regularnych. Najlepsza praktyka korzystania z osobnego servernadal będzie obowiązywać .

Pamiętaj, że to rozwiązanie staje się trudne, jeśli używasz protokołu https, ponieważ musisz mieć jeden certyfikat na wszystkie nazwy domen, jeśli chcesz, aby działał poprawnie.


nie- wwwdo wwww / regex w dedykowanym pojedynczy serverdla wszystkich stron:

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

wwwdo non- wwww / regex w dedykowanym singlu serverdla wszystkich witryn:

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

wwwdo non- wwww / regex w dedykowanym tylko serverdla niektórych witryn:

Konieczne może być ograniczenie wyrażenia regularnego, aby obejmowało tylko kilka domen, wtedy możesz użyć czegoś takiego, aby dopasować www.example.org, www.example.comiwww.subdomain.example.net :

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

Testowanie wyrażeń regularnych w / nginx

Możesz sprawdzić, czy wyrażenie regularne działa zgodnie z oczekiwaniami pcretestw twoim systemie, co jest dokładnie takie samopcre biblioteką, której twój nginx będzie używał do wyrażeń regularnych:

% 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> 

Zauważ, że nie musisz się martwić kropkami ani wielkością liter, ponieważ nginx już się tym zajmuje, tak jak w wyrażeniu regularnym nazwy serwera nginx, gdy nagłówek „Host” ma kropkę końcową .


  1. Posyp ifw istniejącymserver / HTTPS:

To ostateczne rozwiązanie na ogół nie jest uważane za najlepszą praktykę, jednak nadal działa i działa.

W rzeczywistości, jeśli używasz HTTPS, to końcowe rozwiązanie może okazać się łatwiejsze w utrzymaniu, ponieważ nie musisz kopiować i wklejać całego zestawu dyrektyw ssl między różnymi serverdefinicjami, a zamiast tego możesz umieścić fragmenty tylko w potrzebnych serwerów, co ułatwia debugowanie i zarządzanie witrynami.


non- wwwto www:

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

wwwdo non- www:

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

zakodować na stałe jedną preferowaną domenę

Jeśli chcesz nieco większej wydajności, a także spójności między wieloma domenami, z których jedna servermoże korzystać, nadal może być sensowne jawne zakodowanie jednej preferowanej domeny:

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

Bibliografia:


16

To rozwiązanie pochodzi z mojego osobistego doświadczenia. Użyliśmy kilku segmentów Amazon S3 i jednego serwera do przekierowywania non-wwwdo wwwnazw domen w celu dopasowania do zasad nagłówka S3 „Host” .

Użyłem następującej konfiguracji serwera nginx :

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

To pasuje do wszystkich nazw domen wskazanych na serwer, zaczynając od cokolwiek oprócz www.i przekierowuje do www.<domain>. W ten sam sposób możesz wykonać przekierowanie przeciwne wwwdo non-www.


co z https? Uwaga: https POTRZEBUJĄ certyfikatu
Toskan

Tutaj absolutnie nie ma problemu z HTTPS. Po listen 80musisz dodać, listen 443 ssla następnie ssl_certificatei ssl_certificate_keydyrektyw.
VisioN

nikt obecnie nie używa http. Czytałem najczęściej listen 443 ssl używany przewodnik w Google, który pokazał twój przykład tylko z dodaną linią z brakującym certyfikatem. To nie zadziała i spowoduje poważny ból głowy.
Toskan

Nie wiem o jakim przewodniku mówisz. Mam tę konfigurację z powodzeniem działającą przez prawie trzy lata. W zeszłym roku dodałem obsługę protokołu SSL i działa on zgodnie z oczekiwaniami. I oczywiście musisz mieć certyfikat z kluczem prywatnym w ręku.
VisioN

więc spowoduje to zamknięcie wszystkich subdomen oprócz www, prawda?
Metagrapher

15

Połączyłem najlepsze ze wszystkich prostych odpowiedzi, bez domen zakodowanych na stałe.

301 stałe przekierowanie z non-www na www (HTTP lub HTTPS):

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

    # Regular location configs...
}

Jeśli wolisz inne niż HTTPS, inne niż www niż HTTPS, przekierowuj www jednocześnie:

server {
    listen 80;

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

    rewrite ^ https://$host$request_uri permanent;
}

11

Przekieruj non-www na www

W przypadku pojedynczej domeny:

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

Dla wszystkich domen:

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

Przekieruj www na inną niż www dla pojedynczej domeny:

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

Dla wszystkich domen:

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

Czy możesz podać rozróżnienie między 80i 443?
Hassan Baig

1
Wydaje mi się, że działa bez listendyrektyw (nginx 1.4.6).
Ibrahim,

11

Spróbuj tego

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

Inna droga: 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;
}

i www do no-www

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

Dlaczego autorzy podali w instrukcji nginx instrukcję if, a następnie powiedzieli innym, aby jej unikali? Brzmi dla mnie łobuzersko.
Greg Smethells

4
Stwierdzono „JEŻELI lokalizacja jest zła”. Możesz bezpiecznie umieścić w swoim bloku serwera
Kukunin

Bezpośredni cytat z powyższego linku ... Jedyne w 100% bezpieczne rzeczy, które można zrobić w środku, jeśli w kontekście lokalizacji to: powrót ...; przepisz ... ostatnie;
Justin E

8

Unikalny format:

server {
  listen 80;
  server_name "~^www\.(.*)$" ;
  return 301 https://$1$request_uri ;
}

1
Możesz uczynić to ogólnym, pisząc w ten sposób: server { server_name "~^www\.(.*)$" ; return 301 $scheme://$1$request_uri ; }
Ramast

5
location / { 
    if ($http_host !~ "^www.domain.com"){ 
        rewrite ^(.*)$ $scheme://www.domain.com/$1 redirect; 
    } 
}

1
$scheme://www.domain.com$1uniknąć podwójnego cięcia
karimhossenbux

3

nie jestem pewien, czy ktokolwiek zauważy, że zwrócenie 301 może być poprawne, ale przeglądarki się do tego dławią

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

jest szybszy niż:

return 301 $scheme://yoursite.com$request_uri;


1
mój komentarz został skierowany do przeglądarki, a nie do wydajności po stronie nginx! przekierowanie powoduje, że przeglądarka wysyła 2 żądania w porównaniu z 1 żądaniem podczas ponownego pisania
Steven

2

Blog widmo

aby stworzyć zalecaną przez nginx metodę return 301 $scheme://example.com$request_uri;pracy z Ghostem, musisz dodać w głównym bloku serwera:

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;  

2

Jeśli nie chcesz na stałe kodować nazwy domeny, możesz użyć tego bloku przekierowań. Domena bez wiodącego www jest zapisywana jako zmienna, $domainktórą można ponownie wykorzystać w instrukcji przekierowania.

server {
    ...
    # Redirect www to non-www
    if ( $host ~ ^www\.(?<domain>.+) ) {
       rewrite ^/(.*)$ $scheme://$domain/$1;
    }
}

ODNIESIENIE: Przekierowanie poddomeny z wyrażeniem regularnym w nginx


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

-6

Jeśli masz problemy z uruchomieniem tej funkcji, może być konieczne dodanie adresu IP serwera. Na przykład:

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

gdzie XXX.XXX.XXX.XXX to adres IP (oczywiście).

Uwaga: aby poprawnie przekierować żądania https, należy zdefiniować ssl crt i lokalizację klucza

Nie zapomnij zrestartować nginx po dokonaniu zmian:

service nginx restart

3
/etc/init.d/nginx reloadmożesz reloadtakże serwer, który nie powoduje żadnych przestojów.
TheBlackBenzKid
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.