Wirtualne hosty oparte na nazwie nginx na IPv6

44

Mam serwer Nginx obsługujący prawie pół tuzina różnych stron internetowych. Działa na Linode, który właśnie ma natywną obsługę IPv6 (centrum danych Dallas), i próbuję skonfigurować większość moich stron do pracy z dwoma stosami. Pierwszą uruchomiłem przy użyciu subdomeny opartej tylko na IPv6, takiej jak:

server {
    listen [::]:80 ipv6only=on;
    listen 80;

    server_name example.com ipv6.example.com;

    root /var/www/example.com/htdocs;

    #More stuff, including PHP, WordPress
}

Działa to świetnie - na przykład example.com jest tylko IPv4 (na razie), a ipv6.example.com jest tylko IPv6 (głównie tam do celów testowych). Mogę ping6 ipv6.example.com, a nawet wget ipv6.example.comnie przerywając potu - było to przyjemnie bezbolesne (po znalezieniu „gotcha” w sposób, w jaki nginx wiąże wirtualnych hostów, co wymaga ipv6only=onargumentu i podwójnych listendyrektyw).

Jednak próbuję teraz rozwinąć to, aby obsługiwać moje inne domeny, zaczynając od static.example.com; jednak, gdy przyjmuję takie samo podejście jak powyżej (podwójne listendyrektywy, w tym ipv6only=onargument), pojawia się następujący błąd podczas restartowania nginx:

* Starting Nginx Server...
nginx: [emerg] a duplicate listen options for [::]:80 in /etc/nginx/sites-enabled/example.com.conf:3

Wydaje się, że być może metoda wiązania przez Nginx IPv6 nie pozwala na wirtualne hosty oparte na nazwie? Czy będę musiał uzyskać dodatkowe adresy IPv6 od mojego hosta (to nie problem) i korzystać z wirtualnego hostingu opartego na IP na IPv6 z wirtualnym hostingiem opartym na nazwach przez IPv4? A może brakuje mi rozwiązania, które pozwoli zachować spójność moich konfiguracji na obu stosach?

Miałem nadzieję, że moja strona w pełni znajdzie się na stosie IPv6 na czas Światowego Dnia IPv6 , ale jeśli nie uda mi się szybko tego wyczyścić, mogę nie być gotowy. Nie jest to żadna wielka sprawa z praktycznego punktu widzenia - żadna z moich stron nie kwalifikuje się jako „duża organizacja” pod żadnym względem wyobraźni - ale pomóżcie mi ocalić moją wiedzę maniaka!

Edytowano, aby dodać:

Dzięki odpowiedzi @kolbyjack mam teraz w pełni funkcjonalny serwer internetowy z dwoma stosami. Dla jasności edytuję rozwiązanie, które mi dał, aby każdy mógł wyraźnie zobaczyć, jaka jest odpowiedź.

Mój domyślny vhost typu catchall ma następujące listendyrektywy:

listen 80 default_server;
listen 8080 default_server;
listen [::]:80 default_server ipv6only=on;
listen [::]:8080 default_server ipv6only=on;

Nie wiem, czy kolejność ma znaczenie, ale tak jest. Następnie każdy dodatkowy vhost ma następujące listendyrektywy:

listen 80;
listen [::]:80;

(Lub 8080 dla tego, który nasłuchuje na tym porcie). Ważną częścią wydaje się tutaj całkowity brak jakichkolwiek dodatkowych argumentów we wszystkich listendyrektywach oprócz domyślnego vhosta - tj. Brak powtarzania ipv6only=on.

Ponownie wielkie podziękowania dla @kolbyjack za rozwiązanie tutaj!

Kromey
źródło
Z nginx 1.2.1 nie musiałem określać ipv6only=on. Wszystko inne pozostało jednak takie samo, dzięki za to!
BeepDog

Odpowiedzi:

46

Potrzebujesz tylko opcji nasłuchiwania dla jednej deklaracji dla gniazda. Zasadniczo umieściłbyś je na deklaracji, która zawiera również flagę default_server, ale dla niektórych opcji, myślę, że możesz po prostu ustawić je na dowolnej dyrektywie Listen. Po prostu usuń ipv6only = on ze wszystkich słuchaczy oprócz jednego.

kolbyjack
źródło
2
Czekaj, jestem zdezorientowany. Myślałem, że wymagana jest co najmniej jedna dyrektywa nasłuchująca na deklarację serwera - w przeciwnym razie nginx wiedziałby, z którym blokiem serwera ma odpowiadać na jakich portach? Nie wspomniałem o tym powyżej, ponieważ nie uważałem tego za istotne, ale mam jeden serwer na 8080, reszta na 80, i zamierzam zaoferować 443 za parę, jak tylko się to rozwiążę i następnie zdobądź certyfikat SSL.
Kromey
OK, patrząc ponownie na dokumentację, strony znajdujące się na porcie 80 wyglądają, jakby nie potrzebowały w ogóle dyrektywy nasłuchującej, tylko jedna z flagą default_server na moim hoście catchall. Jednak nadal nie działa to na moim serwerze 8080, dla którego używam również domyślnego catchall (catchall jest napisany, aby po prostu zignorować wszelkie żądania nazwy hosta, której jawnie nie skonfigurowałem w innym vhostie).
Kromey
1
Nie mówię o usunięciu wszystkich dyrektyw słuchania. Wystarczy usunąć flagę ipv6only = on ze wszystkich oprócz jednego. Bez dyrektywy Listen na każdym serwerze domyślnie będą słuchać tylko 80; który może, ale nie musi obejmować ipv6. Myślę, że poprawnym podejściem jest włączenie obu dyrektyw nasłuchu na każdym serwerze, ale włączenie ipv6only = tylko na jednym z serwerów.
kolbyjack
4
Ach, rozumiem teraz, co masz na myśli. Źle odczytałem twój post. To zadziałało dla mnie: ipv6only=onjest wymienione (dla każdego portu, na którym słucham) tylko w moim domyślnym vhostie (obok default_server); każdy vhost następnie określa listen 80;i listen [::]:80(bez żadnych dodatkowych parametrów), aby działał zarówno na IPv4, jak i IPv6. Teraz wszystko, co muszę zrobić, to dokończyć dodawanie rekordów AAAA dla moich domen z dwoma stosami i powinienem być tutaj. Dzięki!
Kromey
1
działało również dla mnie, ale nie rozumiem, dlaczego i nginx może słuchać na ipv4 dla wielu bloków, ale nie ipv6. . możesz wytłumaczyć ?
Adeerlike