hosts virtuais baseados em nomes nginx no IPv6

44

Eu tenho um servidor nginx que atende quase meia dúzia de sites diferentes. Ele está sendo executado em um Linode que acabou de receber suporte nativo ao IPv6 (data center de Dallas) e estou tentando configurar a maioria dos meus sites para operação com pilha dupla. Coloquei o primeiro em funcionamento usando um subdomínio somente IPv6, da seguinte forma:

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
}

Isso funciona muito bem - example.com é somente IPv4 (por enquanto) e ipv6.example.com é apenas IPv6 (principalmente para fins de teste). Eu posso ping6 ipv6.example.com, e mesmo wget ipv6.example.comsem suar a camisa - isso foi agradavelmente indolor (depois de encontrar a "pegadinha" com a maneira como o nginx liga os hosts virtuais, exigindo o ipv6only=onargumento e as duas listendiretrizes).

No entanto, agora estou tentando expandir isso para dar suporte aos meus outros domínios, começando com static.example.com; embora eu adote a mesma abordagem acima (as listendiretivas duplas , incluindo o ipv6only=onargumento), recebo o seguinte erro ao reiniciar o nginx:

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

Parece que talvez o método de ligação do nginx para IPv6 não permita hosts virtuais baseados em nome? Terei que obter endereços IPv6 adicionais do meu host (não é um problema) e usar a hospedagem virtual baseada em IP no IPv6 com a hospedagem virtual baseada em nome no IPv4? Ou estou faltando uma solução que permita que minhas configurações permaneçam consistentes nas duas pilhas?

Eu esperava ter meu site totalmente na pilha do IPv6 a tempo do Dia Mundial do IPv6 , mas, a menos que eu possa esclarecer isso rapidamente, talvez não esteja pronto. Não é grande coisa do ponto de vista prático - nenhum dos meus sites se qualifica como "grande organização" por qualquer extensão da imaginação - mas ajude-me a economizar meu crédito nerd!

Editado para adicionar:

Graças à resposta de @kolbyjack, agora tenho um servidor da Web com pilha dupla totalmente funcional. Por uma questão de clareza, estou editando a solução que ele me deu para que todos possam ver claramente qual é a resposta.

Meu vhost catchall padrão possui as seguintes listendiretivas:

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

Não sei se a ordem importa, mas aí está. Em seguida, cada vhost adicional possui as seguintes listendiretivas:

listen 80;
listen [::]:80;

(Ou 8080 para o que escuta nessa porta.) A parte importante aqui parece ser a total falta de argumentos adicionais em todas as listendiretivas padrão do vhost, exceto as diretivas padrão do vhost - ou seja, nenhuma repetição de ipv6only=on.

Mais uma vez, muito obrigado a @kolbyjack pela solução aqui!

Kromey
fonte
Com o nginx 1.2.1, eu não precisava especificar ipv6only=on. Tudo o resto permaneceu o mesmo, no entanto, obrigado por isso!
BeepDog

Respostas:

46

Você só precisa de opções de escuta em uma declaração para um soquete. Geralmente você os colocaria na declaração que também inclui o sinalizador default_server, mas para algumas opções, acho que você pode configurá-los em qualquer diretiva de escuta. Apenas remova o ipv6only = on de todas as escutas, exceto uma.

kolbyjack
fonte
2
Espere, estou confuso. Eu pensei que pelo menos uma diretiva de escuta por declaração de servidor fosse necessária - caso contrário, como o nginx saberia com qual bloco de servidor se destina a responder em quais portas? Eu não mencionei acima, porque não achei relevante, mas tenho um servidor no 8080, o restante no 80, e pretendo oferecer 443 para um casal assim que resolver isso e então consiga um certificado SSL.
Kromey
Ok, olhando novamente para a documentação, os sites que estão na porta 80 parecem que na verdade não precisam de uma diretiva de escuta, apenas uma com a bandeira default_server no meu host de catchall. No entanto, isso ainda está falhando para o meu servidor no 8080, para o qual eu também uso uma catchall padrão (a catchall é gravada para simplesmente ignorar qualquer solicitação de um nome de host que eu não tenha configurado explicitamente em outro vhost).
Kromey
1
Não estou dizendo para remover todas as suas diretivas de escuta. Apenas remova o sinalizador ipv6only = on de todos, exceto um deles. Sem uma diretiva de escuta em cada servidor, eles terão como padrão apenas escutar 80; que pode ou não incluir o ipv6. Eu acho que a abordagem correta é incluir as duas diretivas de escuta em cada servidor, mas apenas coloque o ipv6only = em apenas um dos servidores.
precisa saber é o seguinte
4
Ah, agora entendo o que você quer dizer. Eu li errado sua postagem originalmente. Isso funcionou para mim: ipv6only=onestá listado apenas (para cada porta em que escuto) no meu vhost padrão (ao lado default_server); cada vhost simplesmente especifica listen 80;e listen [::]:80(sem parâmetros adicionais) funcionar no IPv4 e no IPv6. Agora tudo o que tenho a fazer é terminar de adicionar os registros AAAA para meus domínios de pilha dupla, e eu devo estar aqui. Obrigado!
Kromey
1
funcionou para mim também, mas não entendo por que o nginx pode ouvir no ipv4 vários blocos, mas não o ipv6. . você pode explicar ?
9788686105106Bom