การเพิ่ม Name-based Virtual Host ให้กับ Apache สำหรับใช้งานบน localhost

สวัสดีครับ หลังจากไม่ได้เขียนมานานเนื่องจากหลายๆ เหตุผลวันนี้ได้ฤกษ์เขียนอะไรที่พอมีประโยชน์ต่อซะที

จากชื่อบทความอาจจะฟังดูไร้สาระไปซักหน่อย เนื่องจากการทำให้เครื่องเราเป็น webserver เพื่อใช้ในการพัฒนาเว็บไซต์นั้น ถ้าทำแบบง่ายๆ ไม่ได้คิดอะไรมากก็แค่ลง WAMP ซักตัวหนึ่ง จากนั้นก็สร้าง subdirectory ขึ้นมาแล้วสร้างเว็บไซต์ไว้ใน subdirectory นั้น เมื่อเราจะเข้าดูผ่านเว็บไซต์ก็จะเข้าโดยการพิมพ์ลิ้ง localhost/subdirectory ที่เราต้องการเข้าแค่นั้น

แต่บทความนี้จะแนะนำวิธีการใช้ name-based virtual host เบื้องต้น ซึ่งจะส่งผลทำให้เราสามารถใช้ domain อะไรก็ได้ตามที่เรากำหนดไว้ ในการเข้าสู่เว็บไซต์บน localhost ของเรานั่นเอง(แต่ถ้า domain เหมือนกันกับที่มีอยู่แล้วบน internet เราก็จะไม่สามารถเข้าเว็บนั้นได้)

ในบทความนี้นั้นผมใช้ WampServer 2.5 ซึ่งเป็นแพ็กของซอฟต์แวร์ที่ใช้ในการทำ webserver สำหรับคำว่า WAMP นั้นไม่ได้หมายถึงตัวซอฟแวร์ตัวใดตัวหนึ่ง แต่หมายถึงซอฟแวร์ 3 ตัวที่นิยมใช้ในการทำ webserver : Windows, Apache, MySql, PHP จะมีอีกคำหนึ่งที่เห็นได้เหมือนกันคือ LAMP ซึ่งตัว L มาจาก Linux ซึ่งผู้ให้บริการ web hosting ส่วนใหญ่นิยมใช้ Linux ซึ่งฟรีมากกว่าใช้ Windows Server ซึ่งไม่ฟรีมาใช้งานอยู่แล้ว แต่ในกรณีทั่วไปที่คนส่วนใหญ่ไม่ได้ใช้ Linux ดังนั้น WAMP จึงเป็นตัวเลือกสำหรับคนใช้ windows นั่นเอง

สำหรับ WampServer 2.5 นั้นใช้ Apache 2.4.9 ซึ่งเวอร์ชั่นตรงนี้จะมีผลกับการเซตของเราด้วย ดังนั้นบทความนี้จะอาจจะใช้กับ Apache ที่เวอร์ชั่นต่ำกว่านี้ไม่ได้ ดังนั้นผมจะลงรายละเอียดที่เกี่ยวข้องไว้เท่าที่จะหาได้ไว้ในส่วนที่เกี่ยวข้องนะครับ

เพิ่ม domain name ให้กับไฟล์ hosts ของเรา

Windows ทุกเครื่องนั้นมีไฟล์ hosts อยู่ที่ C:\Windows\System32\drivers\etc ซึ่งไฟล์นี้นั้นถูกใช้โดย  TCP/IP ของ windows เองเปรียบเสมือน DNS server ตัวแรกหลักจากที่ web browser ของเราส่ง request ออกไปที่ DNS server ของ ISP(หรือตามแต่ที่เรากำหนด) ดังนั้งถ้าเราอยากจะเปลี่ยน IP ที่ domain name นั้นควรจะส่ง IP ที่ถูกต้องสำหรับ domain name นั้นคืนมา ไปเป็น IP อื่น ที่มันไม่ควรจะเป็น ก็จะสามารถทำได้ที่ไฟล์นี้เป็นด่านแรกนั่นเอง

ขั้นตอนแรกให้เปิดไฟล์ hosts ที่ C:\Windows\System32\drivers\etc ขึ้นมาก่อน ด้วย text editor ตัวใดก็ได้  ถ้ายังไม่ได้เพิ่มเติมอะไรเลย ไฟล์ที่ได้จะเป็นแบบนี้

hosts before
C:\Windows\System32\drivers\etc\hosts

สังเกตที่บรรทัดสุดท้ายซึ่งเป็นบรรทัดที่คำสั่งถูกใช้งานจริงๆ  และฝั่งซ้ายมือจะเป็น IP ของเครื่องเราเอง ฝั่งขวาจะเป็น Domain name ซึ่งต่อไปนี้ผมจะขอเรียกว่า hostname แทน ให้เราทำการเพิ่ม host name ที่เราต้องการตามรูปแบบที่มีอยู่คือ IP ที่แสดงถึงเครื่องของเราเอง(127.0.0.1)อยู่ทางด้านซ้าย เว้นวรรคด้วย tab จากนั้น ก็ใส่ชื่อ hostname ที่เราต้องการลงทางด้านขวา จะได้เป็นแบบนี้

C:\Windows\System32\drivers\etc\hosts

จากนั้นก็ให้ทำการเซฟ สำหรับคนที่เซฟไม่ได้(ปกติก็ไม่น่าจะะมีใครเซฟได้) เช่น ถ้าใช้ notepad จะบอกว่าไม่มี permission หรือถ้าใช้ notepad++ จะบอกว่า มีโปรแกรมอื่นใช้อยู่ ให้เราทำการเพิ่ม permission ให้กับ user ของเรากับไฟล์นี้ก่อน โดยให้คลิกขวาที่ไฟล์ > Properties > Security tab > Edit จากนั้นให้คลิกที่ user เราและที่ช่องด้านล่างให้ติกที่ Write เสร็จแล้วให้กด OK หากมีหน้าขึ้นมาให้ยืนยัน เท่านี้เราก็จะสามารถเซฟไฟล์ hosts ได้แล้วและอย่าลืมแก้ permission คืนด้วยหลังจากเซฟเสร็จ

หลังจากขั้นตอนนี้สิ่งที่ได้มาคือ ผมได้เพิ่ม host name ชื่อ sakura.moe เข้าไป(domain name อันนี้ในอินเตอร์เน็ตมีคนจดไว้แล้ว) การทำงานหลังจากนี้คร่าวๆ(รู้แค่นี้ TwT) เมื่อเราพิมพ์ลิ้งไปที่ sakura.moe web browser จะได้รับ IP ของเครื่องเรากลับคืนมาเองและ web browser ก็จะใช้ IP นี้ access เข้าไปที่ web server(apache) ซึ่ง ก็หมายถึงเครื่องเรานั่นเอง

เพิ่ม Virtual Host ให้กับ Apache

Virtual host นั้นมีด้วยการ 2 แบบ name-based กับ IP-based ความต่างของทั้งสองอย่างนี้แบบเข้าใจง่ายๆ คือ name-based จะยึดตาม request ที่เข้ามาว่าต้องการ hostname อันไหนก่อนส่งข้อมูลนั้นกลับไปที่ client ส่วน IP-based จะยึดตามว่าต้องการ connection ของ IP ไหน ทำให้จำเป็นต้องใช้ IP แยกตาม host(website) ส่งผลให้สิ้นเปลือง IP ดังนั้นปกติจะไม่ได้ใช้แบบ IP-based กัน แต่จะใช้แบบ Name-based ที่จะทำให้หลาย host สามารถแชร์ IP เดียวกันได้

ขั้นแรกให้ไปเปิด modules ที่ใช้กับการทำงานของ name-based virtual host ก่อน โดยการเข้าไปที่ \apache2.4.9\conf  จากนั้นเปิดไฟล์ httpd ด้วย text editor จากนั้นค้นหาบรรทัด LoadModule vhost_alias_module modules/mod_vhost_alias.so และให้ลบเครื่องหมาย # ด้านหน้าออก(ถ้ามี) อีกบรรทัดหนึ่งคือ Include conf/extra/httpd-vhosts.conf ถ้ามีเครื่องหมาย # ก็ให้ลบออกเช่นกัน เป็นอันเสร็จสิ้นขั้นตอนการเปิด modules ที่จำเป็นต้องใช้(ถ้าไม่ได้เปิดไว้ก่อน)

ก่อนไปถึงขั้นตอนต่อไปขออธิบายซักเล็กน้อย หลักจากที่เราทำการเปิดใช้ virtual host แล้ว และ IP ที่เรากำหนดให้ virtual host นั้นตรงกับ global host ที่มีอยู่ ตัว global host ที่เป็นตัวหลักซึ่งถูกเซตไว้ภายในไฟล์ httpd จะไม่สามารถใช้งานได้อีก ซึ่งตัว global host ตัวนี้นั้นจะถูกส่งให้ client เสมอในกรณีที่ไม่ตรงกับ virtual host ที่เรากำหนดไว้เลย ดังนั้นเราจะจำเป็นต้องเพิ่ม default virtual host ด้วย เพราะถ้าหากไม่มี virtual host ตัวไหนที่ตรงกับ request ที่เข้ามา virtual host ตัวแรกที่เรากำหนดไว้ จะถูกใช้ส่งให้นั้นเอง ดังนั้น default virtual host คือ virtual host ที่ถูกเพิ่มไว้ในอันดับแรก

ต่อไปให้เข้าไปที่ \apache2.4.9\conf\extra จากนั้นเปิดไฟล์ httpd-vhosts โดยใช้ text editor เพื่อเพิ่ม virtual host ด้วยการสร้าง  <VirtualHost> บล็อค โดยแต่ละบล็อคก็จะหมายถึงแต่ละ virtual host นั่นเอง เมื่อเปิดขึ้นมาจะมีตัวอย่างให้ดูตามนี้

httpd-vhost sample
\apache2.4.9\conf\extra\httpd-vhosts.conf

จากที่เห็น argument ของ <VirtualHost> เป็น “*:80” ใส่แบบนี้จะทำให้หลังจาก request เข้ามาแล้ว จะมองแต่ละบล็อคว่าสามารถเเป็น IP อะไรก็ได้ที่เรียกไปที่ port 80 ดังนั้น apache จะไปดูที่ ServerName แทนและดูที่ IP เพราะทุกบล็อคตอนนี้เป็น IP อะไรก็ได้แล้วนั่นเอง

ภายในบล็อค  <VirtualHost> คำสั่งที่จำเป็นจะต้องใส่มีเพียงแค่ 2 คำสั่งคือ ServerName ที่เอาไว้สำหรับบอก servername ของ virtual host กับ DocumentRoot เอาไว้ระบุ directory ของ virtual host นั้นเท่านั้น

จากด้านบนที่ผมอธิบายไปเรื่องที่ virtual host จะใช้งานไม่ได้ ดังนั้นเราจะต้องเพิ่ม default virtual host ก่อนเป็นอันดับแรก โดยผมจะตั้งเป็น localhost เหมือนเดิมก็จะได้ตามนี้

default virtual host
\apache2.4.9\conf\extra\httpd-vhosts.conf

อธิบายเพิ่มเติม ที่ผมเขียนเพียงแค่นี้ได้เพราะว่าที่ไฟล์ httpd ได้มี config ของ localhost อยู่แล้ว เช่น DocumentRoot, <Directory> ซึ่ง ServerName ที่ผมเขียนทับไปตรงนี้นั้นได้ override และใช้ค่าของ localhost เดิมที่ยังไม่มี config ใหม่มา override นั้นเอง

ตัวอย่างต่อไปเป็นการเพิ่ม virtual host ใหม่อีกอันหนึ่งโดยกำหนด ServerName เป็นตัวเดียวกันกับผมที่เขียนไว้ใน hosts ในขั้นตอนก่อนหน้า

sakura moe virtual host

เมื่อเพิ่มเสร็จแล้วให้ restart apache สำหรับผมจะลองเข้าไปที่ http://sakura.moe ดู ถ้าทำมาแค่นี้ก็จะเจอ

sakura 403 forbiden

อย่างที่เห็น apache แจ้งว่าเราไม่มีสิทธิ์ในการเข้าถึงไฟล์ การเพิ่ม permission ให้แต่ละ directory สามารถทำได้ผ่าน <Directory> บล็อคโดยสามารถใส่ไว้ได้ภายใน <VirtualHost> บล็อค โดยที่ config ต่างๆ ที่อยู่ภายใน <VirtualHost> จะจำกัดอยู่แค่บล็อคนั้นๆ ถึงแม้เราจะกำหนด argument ของ <Directory> ซึ่งเป็น directory path ที่ <VirtualHost> บล็อคอื่นใช้ด้วยก็ตาม แต่เราก็สามารถวาง <Directory> บล็อคไว้ภายในไฟล์ httpd และ config ต่างๆ จะถูกใช้งานกับทุก <VirtualHost> ที่ใช้ directory path เดียวกันเหมือนกัน สำหรับผมจะขอเลือกอย่างหลังคือใส่ไว้ภายในไฟล์ httpd โดยข้างล่างนี้เป็นตัวอย่าง เดี๋ยวผมจะอธิบายคำสั่งต่างๆ ภายในทีละอันครับ

directory vhost
\apache2.4.9\conf\httpd.conf

อย่างแรกคือ argument ของ <Directory> จะเป็น directory path จริงๆ แล้ว directory path สามารถใช้ได้ทั้ง back slash ซึ่งใช้บน windows หรือ forward slash เหมือนกับ Unix-like OS ก็ได้ แต่ถ้าเราจะใช้ back slash นั้นจำเป็นจะต้องใส่ double quote ครอบไว้ด้วย

Options ใช้กำหนดว่าจะมี features อะไรที่สามารถใช้ได้ใน directory นั้นได้บ้าง FollowSymLinks หมายถึง ถ้าลิ้งที่ถูกป้อนเข้ามาเป็น symbolic links ก็จะใช้ symbolic links นั้น ส่วน Indexes หมายถึง ถ้าภายใน DocumentRoot ไม่มีไฟล์ index อยู่เลย ก็จะแสดงภายใน directory นั้นเป็นหน้า index ออกมาแบบด้านล่างนี้

indexes
ตัวอย่างอันนี้ผมทำการเปลี่ยน DocumentRoot ไปที่อื่น

AllowOverride ใช้บอกว่า ถ้า server เจอไฟล์ .htaccess คำสั่งอะไรที่อยู่ภายใน .htaccess จะสามารถ override config ที่มีอยู่ก่อนได้บ้าง สุดท้ายคือ Require  ใช้สำหรับจำกัดว่าใครสามารถเข้าถึงไฟล์ได้บ้าง ซึ่งเมื่อเซตคำสั่งนี้เป็น  all granted แล้วทุกคนจะสามารถเข้าถึงไฟล์ได้  เมื่อเราเพิ่ม <Directory> เข้าไปที่ไฟล์ httpd เรียบร้อยแล้ว เราก็จะสามารถใช้งาน virtual host ที่เป็น name-based ของเราได้แล้ว

sakura moe complete

ทั้งหมดนี้ก็เป็นวิธีการเพิ่ม name-based virtual host เบื้องต้น ซึ่งจริงๆ แล้วผมศึกษามาจากที่นี่ทั้งหมดเลย ถ้าผมมีความรู้เพิ่มขึ้นจะมาอัพเดทให้อีกนะครับ สำหรับใครที่เข้ามาอ่านแล้วเห็นว่ามีตรงไหนที่ผมอธิบายไว้ผิดพลาดตรงไหน ก่อนจะเอาไปเม้าว่าผมเขียนมั่ว ช่วยเขียนแนะนำไว้ให้ผมด้วยครับ เพราะผมจะได้มีความรู้ด้วย TwT