Nginx no-www เป็น www และ www เป็น no-www


497

ฉันใช้nginx บนคลาวด์ Rackspace ตามบทช่วยสอนและการค้นหาสุทธิและไม่สามารถเรียงลำดับได้

ฉันต้องการ www.mysite.com เพื่อไปที่ mysite.com ตามปกติใน. htaccess สำหรับ SEO และเหตุผลอื่น ๆ

/etc/nginx/sites-available/www.example.com.vhostของฉันตั้งค่า :

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


1
ฉันรู้สึกถูกบังคับให้แสดงความคิดเห็นว่าหากคุณกำลังทำงานกับเว็บไซต์ WordPress ให้ตรวจสอบDashboard > Settings > General Settingsและตรวจสอบให้แน่ใจว่าไม่มีwwwใน URL ที่อยู่ / ที่อยู่ไซต์ WordPress ไม่ว่าคุณจะกำหนดค่า nginx อย่างไรถ้าคุณมี www ใน URL เหล่านี้มันจะถูกเปลี่ยนเส้นทางไปยังที่มี www อยู่
Abhinav Sood

คำตอบ:


792

โซลูชัน 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://ในโซลูชันเนื่องจากเราใช้ loadbalancer และ https: // เซิร์ฟเวอร์ของเราเป็นเซิร์ฟเวอร์ชำระเงิน SSL ที่มีปริมาณการใช้งานสูง: เราไม่ได้ผสม https: // และ http: //


ในการตรวจสอบเวอร์ชั่น nginx ให้ใช้ nginx -vใช้

ดึง www จาก url ด้วยการเปลี่ยนเส้นทาง 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#
}

ดังนั้นคุณต้องมีรหัสเซิร์ฟเวอร์สองตัว

เพิ่ม 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;
       }
}

3
@puk ขอบคุณมัน Nginx เป็นสิ่งที่น่าอัศจรรย์ แต่เอกสารที่ดีซึ่งเป็นข้อมูลล่าสุดเกี่ยวกับเวอร์ชันของเซิร์ฟเวอร์และระบบปฏิบัติการและการเปลี่ยนแปลงฮาร์ดแวร์เซิร์ฟเวอร์นั้นค่อนข้างน่าเบื่อ ทรัพยากรที่ดีที่สุดที่ให้บริการฉันคือ howtoforge.com เนื่องจากรองรับระบบคลาวด์รุ่น RackSpace คำสั่งบางส่วนด้านบนจะไม่ทำงานในรุ่นที่ใหม่กว่า แต่สิ่งนี้ nginx / 0.8.54 - คือเชื่อฉันเซิร์ฟเวอร์ nginx ที่ดีที่สุด) ไม่จำเป็นต้องอัปเกรดหรืออัปเดต ทำงานได้ดี ยอดฮิตที่ไม่ซ้ำใครต่อวันด้วย 4200 ธุรกรรมเฉลี่ยต่อวัน Nginx คือ RAPID ชอบใช้ไซต์ที่ไม่มีทราฟฟิก
TheBlackBenzKid

17
การเขียนใหม่ของคุณควรกลับมาเหมือนreturn 301 $scheme://domain.com$request_uri;เดิม ไม่จำเป็นต้องจับรูปแบบใด ๆ ดูข้อผิดพลาด Nginx
Roberto

4
@TheBlackBenzKid ขออภัยฉันอาจพลาดบางอย่าง แต่โซลูชันที่อัปเดตแล้วไม่ทำงาน เป็นเพราะฟัง 80 - คุณกำลังบอกว่ามีเพียง HTTP เท่านั้นที่ตรงกับสิ่งนี้ ควรมีพอร์ตที่จะรับฟังมากกว่านี้หากใช้การกำหนดค่าเดียวกันสำหรับ HTTP และ HTTPS ... หรือ แต่แน่นอนช่วยฉัน +1 ขอบคุณสำหรับการตอบ. ไชโย
tomis

3
@TheBlackBenzKid มันก็แค่ทราบ ฉันได้พบวิธีแก้ปัญหาการทำงาน ในตัวอย่างของคุณควรเพิ่ม 443 Listen เท่านั้นและทำงานได้อย่างสมบูรณ์
tomis

2
คำตอบนั้นผิด มันเปลี่ยนเส้นทางโดเมนย่อยทั้งหมดไปที่ www
r3wt

398

จริงๆแล้วคุณไม่จำเป็นต้องมีการเขียนซ้ำ

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

เช่นเดียวกับคำตอบของฉันคือการได้รับคะแนนเสียงมากขึ้นเรื่อย ๆ คุณไม่ควรใช้ a 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...
}

ฉันคิดว่าคุณคงนึกภาพสารประกอบอื่นด้วยรูปแบบนี้ได้ด้วยตัวเองตอนนี้

มากกว่า configs ของฉัน? ไปที่นี่และที่นี่


3
Chrome ของคุณไม่ควรไปที่โดเมนwwwของคุณหากคุณใช้ HSTS โปรดเปิดคำถามใหม่ที่มีรายละเอียดมากที่สุดเท่าที่จะเป็นไปได้และเราจะช่วยคุณ (คุณสามารถโพสต์ URL ไปยังคำถามเป็นความคิดเห็นได้ที่นี่)
Fleshgrinder

1
@Fleshgrinder ฉันพยายามใช้การตั้งค่าของคุณ แต่รับปัญหาต่อไปนี้ที่stackoverflow.com/questions/29451409/…มีข้อเสนอแนะใด ๆ เกี่ยวกับวิธีการทำงาน
YPCrumble

4
ในบล็อกที่สอง "เปลี่ยนเส้นทางทั้งไม่ใช่ SSL และ SSL ไปยังคู่ที่ไม่ใช่ www:" บล็อกเซิร์ฟเวอร์ทั้งสองควรมีคำสั่ง SSL เนื่องจากเบราว์เซอร์จำเป็นต้องตรวจสอบใบรับรองสำหรับ www.example.com ก่อนที่จะเปลี่ยนเส้นทางไปยังตัวอย่าง .com
Jeff Tsay

1
แน่นอนฉันเพิ่มว่าเช่นเดียวกับข้อมูลสั้น ๆ เกี่ยวกับ HSTS
Fleshgrinder

1
@ YPCrumble ใช่มันเร็วกว่ามากเพราะเราไม่ได้ทำการจับคู่นิพจน์ปกติในแต่ละคำขอ เราเปลี่ยนเส้นทางก็ต่อเมื่อเรารู้ว่าเราต้องเปลี่ยนเส้นทาง ไม่มีการตรวจสอบไม่มีการตรวจสอบไม่มีอะไร: เพียงแค่เปลี่ยนเส้นทาง =)
Fleshgrinder

37

คุณอาจพบว่าคุณต้องการใช้การกำหนดค่าเดียวกันสำหรับโดเมนเพิ่มเติม

ตัวอย่างต่อไปนี้ลบ www ก่อนโดเมนใด ๆ :

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

7
ฉันชอบวิธีนี้ดีกว่าบล็อกเซิร์ฟเวอร์เฉพาะ เปลี่ยนhttpเป็น$scheme
ck_

2
ดีกว่าไม่น่าเชื่อว่าโดเมน hardcode จำนวนมากจะกลายเป็น config สำหรับงานนี้
MrYellow

1
@Oli ลิงก์นั้นไม่ได้ (ณ วันนี้) พูดถึงประสิทธิภาพ แต่บอกว่ามันไม่ปลอดภัย 100% มันบอกว่า "สิ่งที่ปลอดภัย 100% เท่านั้นซึ่งอาจทำได้ภายในหากอยู่ในบริบทของสถานที่คือ: return ...และrewrite ... last" ลิงก์ที่อัปเดตใด ๆ ไปยังปัญหาเรื่องประสิทธิภาพ
อดัม

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ได้รับข้อผิดพลาดบนเบราว์เซอร์ที่ระบุว่าการตอบสนองไม่ถูกต้อง
Nico Brenner

1
น่าเสียดายที่ฉันไม่พบวิธีที่ไม่มี "ถ้า" ฉันใช้การกำหนดค่าเดียวกันสำหรับหลายโดเมนการเข้ารหัสชื่อโดเมนไม่ใช่ตัวเลือก ข้อเสนอแนะ / ความคิดเห็นใด ๆ ที่มีความนิยม!
Martin Höger

27

คุณต้องมีเซิร์ฟเวอร์สองบล็อก

ใส่สิ่งเหล่านี้ลงในไฟล์ปรับแต่งของคุณเช่น /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 A สองรายการ

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 ของคุณ


23

ต่อไปนี้เป็นวิธีทำสำหรับชื่อเซิร์ฟเวอร์หลาย www ถึง no-www (ฉันใช้ชื่อนี้กับโดเมนย่อย):

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

20
  1. แนวปฏิบัติที่ดีที่สุด: แยกserverw / ฮาร์ดโค้ดserver_name

วิธีปฏิบัติที่ดีที่สุดกับ nginx คือการใช้ตัวแยกserverสำหรับการเปลี่ยนเส้นทางเช่นนี้ (ไม่แชร์กับการserverกำหนดค่าหลักของคุณ) เพื่อ hardcode ทุกอย่างและไม่ใช้นิพจน์ทั่วไปเลย

นอกจากนี้ยังอาจจำเป็นต้อง hardcode โดเมนหากคุณใช้ 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
}

  1. ใช้นิพจน์ทั่วไปภายใน server_name

หากคุณมีเว็บไซต์จำนวนมากและไม่สนใจประสิทธิภาพสูงสุด แต่ต้องการให้ทุก ๆ เว็บไซต์มีนโยบายเดียวกันเกี่ยวกับwww.คำนำหน้าคุณสามารถใช้นิพจน์ทั่วไปได้ แนวปฏิบัติที่ดีที่สุดของการใช้งานแยกต่างหากserverจะยังคงอยู่

โปรดทราบว่าวิธีนี้จะยุ่งยากหากคุณใช้ https เนื่องจากคุณต้องมีใบรับรองหนึ่งฉบับเพื่อให้ครอบคลุมชื่อโดเมนทั้งหมดของคุณหากคุณต้องการให้สิ่งนี้ทำงานได้อย่างถูกต้อง


ไม่ใช่wwwเพื่อwwww / regex ในซิงเกิ้ลเฉพาะserverสำหรับไซต์ทั้งหมด:

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

wwwเป็น non- wwww / regex ในซิงเกิ้ลเฉพาะserverสำหรับทุกไซต์:

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

wwwเพื่อ non- wwww / regex ในแบบเฉพาะserverในบางเว็บไซต์เท่านั้น:

มันอาจจะเป็นสิ่งจำเป็นที่จะ จำกัด การ regex เพื่อให้ครอบคลุมเพียงคู่ของโดเมนแล้วคุณสามารถใช้บางอย่างเช่นนี้เพียงตรง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

คุณสามารถทดสอบว่า regex ทำงานได้ตามที่คาดหวังไว้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 ชื่อเซิร์ฟเวอร์ regex เมื่อ "เจ้าภาพ" ส่วนหัวมีจุดต่อท้าย


  1. โรย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;
}

อ้างอิง:


16

โซลูชันนี้มาจากประสบการณ์ส่วนตัวของฉัน เราใช้หลายบุ้งกี๋ Amazon S3 และเซิร์ฟเวอร์หนึ่งสำหรับการเปลี่ยนเส้นทางnon-wwwไปยังwwwชื่อโดเมนเพื่อให้ตรงกับS3 "เจ้าภาพ" นโยบายส่วนหัว

ฉันใช้การกำหนดค่าต่อไปนี้สำหรับเซิร์ฟเวอร์nginx :

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

นี้ตรงกับชื่อโดเมนทั้งหมดชี้ไปยังเซิร์ฟเวอร์ที่เริ่มต้นด้วยสิ่งที่ แต่และเปลี่ยนเส้นทางwww. www.<domain>ในลักษณะเดียวกับที่คุณสามารถทำตรงข้ามการเปลี่ยนเส้นทางจากไปwwwnon-www


เกี่ยวกับ https? หมายเหตุ: https ต้องใช้ใบรับรอง
Toskan

ไม่มีปัญหากับ HTTPS ที่นี่ หลังจากที่listen 80คุณต้องเพิ่มlisten 443 sslแล้วssl_certificateและssl_certificate_keyคำสั่ง
VisioN

ไม่มีใครใช้ http ในปัจจุบัน ฉันกำลังอ่านคู่มือที่ระบุไว้ด้านบนใน google ที่แสดงตัวอย่างของคุณเพียงแค่เพิ่มบรรทัดที่listen 443 ssl มีใบรับรองหายไป มันไม่ได้ผลและทำให้ปวดหัวอย่างรุนแรง
Toskan

ฉันไม่รู้ว่าคุณกำลังพูดถึงไกด์อะไร ฉันมีการกำหนดค่านี้ทำงานได้สำเร็จเกือบสามปี ปีที่แล้วฉันเพิ่มการรองรับ SSL และทำงานได้ตามที่คาดไว้ และแน่นอนคุณต้องมีใบรับรองพร้อมรหัสส่วนตัวในมือ
VisioN

ดังนั้นสิ่งนี้จะปิดบังโดเมนย่อยทั้งหมดยกเว้น www ถูกต้องไหม
Metagrapher

15

ฉันรวมคำตอบง่ายๆที่ดีที่สุดทั้งหมดโดยไม่มีโดเมนที่เข้ารหัสยากไว้

การเปลี่ยนเส้นทางถาวร 301 จากที่ไม่ใช่ www ไปยัง www (HTTP หรือ HTTPS):

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

    # Regular location configs...
}

หากคุณต้องการที่ไม่ใช่ HTTPS, ไม่ใช่ www ถึง HTTPS, www redirect ในเวลาเดียวกัน:

server {
    listen 80;

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

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

11

เปลี่ยนเส้นทางไม่ใช่ 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 เป็น non-www สำหรับ Single Domain:

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

สำหรับโดเมนทั้งหมด:

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

คุณช่วยสร้างความแตกต่างระหว่าง80และ443?
Hassan Baig

1
ดูเหมือนว่าจะทำงานโดยไม่มีlistenคำสั่งสำหรับฉัน (nginx 1.4.6)
อิบราฮิม

11

ลองนี้

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

วิธีอื่น ๆ : Nginx no-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;
}

ทำไมผู้เขียนถึงให้คำสั่ง if ใน nginx แล้วบอกคนอื่นให้หลีกเลี่ยง ฟังดูพลิ้วไปหน่อย
Greg Smethells

4
มีการระบุว่า "ถ้าอยู่ในสถานที่เป็นสิ่งที่ชั่วร้าย" คุณสามารถใส่ได้อย่างปลอดภัยหากอยู่ในบล็อกเซิร์ฟเวอร์ของคุณ
Kukunin

อ้างโดยตรงจากลิงค์ด้านบน ... สิ่งที่ปลอดภัย 100% เท่านั้นที่สามารถทำได้ภายในหากในบริบทสถานที่ตั้ง: return ... ; เขียนใหม่ ... ล่าสุด;
Justin E

8

รูปแบบที่ไม่ซ้ำ:

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

1
คุณสามารถทำให้มันทั่วไปโดยการเขียนอย่างนี้: server { server_name "~^www\.(.*)$" ; return 301 $scheme://$1$request_uri ; }
Ramast


3

ไม่แน่ใจว่ามีใครสังเกตเห็นว่ามันอาจถูกต้องที่จะส่งคืน 301 แต่เบราว์เซอร์ทำให้หายใจไม่ออก

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

เร็วกว่า:

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


1
ความคิดเห็นของฉันถูกนำไปยังเบราว์เซอร์ไม่ให้มีประสิทธิภาพในด้าน nginx! ด้วยการเปลี่ยนเส้นทางเบราว์เซอร์ทำให้ 2 คำขอกับ 1 คำขอเมื่อ rewiting
steven

2

บล็อกผี

ในการทำให้ 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;  

2

หากคุณไม่ต้องการ hardcode ชื่อโดเมนคุณสามารถใช้บล็อกการเปลี่ยนเส้นทางนี้ โดเมนที่ไม่มี www นำหน้าจะถูกบันทึกเป็นตัวแปร$domainซึ่งสามารถนำมาใช้ซ้ำได้ในคำสั่งการเปลี่ยนเส้นทาง

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

REF: การเปลี่ยนเส้นทางโดเมนย่อยด้วยนิพจน์ปกติใน nginx



-6

หากคุณมีปัญหาในการทำให้การทำงานนี้คุณอาจต้องเพิ่มที่อยู่ 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

3
/etc/init.d/nginx reloadคุณสามารถreloadเซิร์ฟเวอร์ด้วยซึ่งไม่ก่อให้เกิดการหยุดทำงานใด ๆ
TheBlackBenzKid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.