host virtual berbasis nama nginx di IPv6

44

Saya memiliki server nginx yang melayani hampir setengah lusin situs web yang berbeda. Ini berjalan pada Linode yang baru saja mendapatkan dukungan asli IPv6 (pusat data Dallas), dan saya mencoba mengkonfigurasi sebagian besar situs saya untuk operasi dual-stack. Saya mendapatkan yang pertama dan berjalan menggunakan subdomain khusus IPv6 seperti:

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
}

Ini berfungsi dengan baik - example.com adalah IPv4-only (untuk saat ini), dan ipv6.example.com adalah IPv6-only (terutama di sana untuk tujuan pengujian). Saya bisa ping6 ipv6.example.com, dan bahkan wget ipv6.example.comtanpa berkeringat - hal ini menyenangkan tanpa rasa sakit (setelah menemukan "gotcha" dengan cara nginx mengikat host virtual, memerlukan ipv6only=onargumen dan listenarahan ganda ).

Namun, saya sekarang mencoba memperluas ini untuk mendukung domain saya yang lain, dimulai dengan static.example.com; ketika saya mengambil pendekatan yang sama seperti di atas, ( listenarahan ganda , termasuk ipv6only=onargumen), saya mendapatkan kesalahan berikut saat me-restart nginx:

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

Tampaknya mungkin metode nginx untuk IPv6 tidak mengizinkan host virtual berbasis nama? Apakah saya harus mendapatkan alamat IPv6 tambahan dari host saya (bukan masalah) dan menggunakan hosting virtual berbasis IP di IPv6 dengan hosting virtual berbasis nama melalui IPv4? Atau apakah saya melewatkan solusi yang akan memungkinkan konfigurasi saya tetap konsisten pada kedua tumpukan?

Saya berharap situs saya sepenuhnya berada di tumpukan IPv6 tepat waktu untuk Hari IPv6 Dunia , tetapi kecuali saya bisa menghapusnya dengan cepat, saya mungkin tidak siap. Bukan masalah besar dari sudut pandang praktis - tidak ada situs saya memenuhi syarat sebagai "organisasi besar" oleh imajinasi - tetapi membantu saya menyimpan kredibilitas geek saya!

Diedit untuk menambahkan:

Berkat jawaban dari @kolbyjack, saya memiliki server web dual-stack yang berfungsi penuh sekarang. Demi kejelasan saja, saya mengedit dalam solusi yang dia berikan kepada saya sehingga semua orang dapat melihat dengan jelas apa jawabannya.

Catchall vhost default saya memiliki listenarahan berikut :

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

Saya tidak tahu apakah pesanan itu penting, tetapi itu dia. Kemudian, setiap vhost tambahan memiliki listenarahan berikut :

listen 80;
listen [::]:80;

(Atau 8080 untuk salah satu yang mendengarkan pada port itu sebagai gantinya.) Bagian penting di sini tampaknya tidak ada argumen tambahan pada semua kecuali listenarahan vhost default - yaitu tidak ada pengulangan ipv6only=on.

Sekali lagi, terima kasih banyak kepada @kolbyjack untuk solusinya di sini!

Kromey
sumber
Dengan nginx 1.2.1 saya tidak perlu menentukan ipv6only=on. Namun semuanya tetap sama, terima kasih untuk ini!
BeepDog

Jawaban:

46

Anda hanya perlu opsi mendengarkan pada satu deklarasi untuk soket. Secara umum Anda akan meletakkannya di deklarasi yang juga menyertakan flag default_server, tetapi untuk beberapa opsi, saya pikir Anda bisa mengaturnya di salah satu perintah dengarkan. Hapus saja ipv6only = on dari semua yang mendengarkan kecuali satu.

kolbyjack
sumber
2
Tunggu, saya bingung. Saya pikir paling tidak satu perintah mendengarkan per deklarasi server diperlukan - jika tidak, bagaimana nginx tahu dengan blok server mana yang dimaksudkan untuk merespons pada port mana? Saya tidak menyebutkannya di atas karena saya pikir itu tidak relevan, tetapi saya memiliki satu server pada 8080, sisanya pada 80, dan saya bermaksud untuk menawarkan 443 untuk pasangan juga begitu saya mendapatkan ini disetrika dan lalu dapatkan sendiri sertifikat SSL.
Kromey
Oke, melihat lagi pada dokumentasi, situs-situs yang ada di port 80 terlihat seperti mereka tidak akan benar-benar membutuhkan arahan sama sekali, hanya satu dengan flag default_server di catchall vhost saya. Namun, ini masih gagal untuk server saya di 8080, di mana saya juga menggunakan catchall default (catchall ditulis untuk mengabaikan permintaan untuk nama host yang belum saya konfigurasikan secara eksplisit di vhost lain).
Kromey
1
Saya tidak mengatakan untuk menghapus semua arahan mendengarkan Anda. Hapus saja ipv6only = on flag dari semua kecuali satu. Tanpa arahan mendengarkan di setiap server, mereka akan secara default hanya mendengarkan 80; yang mungkin atau mungkin tidak termasuk ipv6. Saya pikir pendekatan yang benar adalah dengan memasukkan keduanya mendengarkan arahan di setiap server, tetapi hanya menempatkan ipv6only = hanya di salah satu server.
kolbyjack
4
Ah, sekarang saya mengerti apa maksud Anda. Saya salah membaca posting Anda pada awalnya. Ini berhasil bagi saya: ipv6only=onhanya terdaftar (untuk setiap port yang saya dengarkan) di vhost default saya (bersama default_server); masing-masing vhost hanya menentukan listen 80;dan listen [::]:80(tidak ada parameter tambahan sama sekali) berfungsi pada IPv4 dan IPv6. Sekarang yang harus saya lakukan adalah menyelesaikan menambahkan catatan AAAA untuk domain dual-stack saya, dan saya harus baik-baik saja untuk pergi di sini. Terima kasih!
Kromey
1
bekerja untuk saya juga, tetapi saya tidak mengerti mengapa saya nginx dapat mendengarkan pada ipv4 untuk beberapa blok, tetapi tidak ipv6. . dapatkah kamu menjelaskan
Adeerlike