คำตอบสั้น ๆ: ตั้งค่า Nginx ให้รันหลายเว็บไซต์บนเซิร์ฟเวอร์และ IP เดียว แยก Log ของแต่ละเว็บ และตั้ง Default Server ปฏิเสธโดเมนที่ไม่รู้จัก
คู่มือนี้อธิบาย Nginx Server Block ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
เซิร์ฟเวอร์หนึ่งเครื่องที่มี IP เดียวสามารถให้บริการหลายเว็บไซต์ได้ เพราะเบราว์เซอร์ส่งชื่อโดเมนที่ต้องการมาใน Header Host (และใน SNI สำหรับ HTTPS) Nginx ใช้ค่านี้เลือกว่าจะตอบด้วยการตั้งค่าชุดใด การตั้งค่าแต่ละชุดเรียกว่า Server Block ซึ่งเทียบได้กับ VirtualHost ของ Apache
บทความนี้สาธิตการตั้งค่าสองเว็บไซต์ คือ example.com (เว็บ PHP) และ example.net (เว็บ HTML ล้วน) บนเครื่องเดียวกัน พร้อมการตั้ง Default Server เพื่อไม่ให้โดเมนแปลกปลอมที่ชี้มาที่ IP ของคุณแสดงเนื้อหาเว็บใดเว็บหนึ่ง บทความนี้สมมติว่าคุณติดตั้ง Nginx และ PHP-FPM แล้วตาม ติดตั้ง Nginx, PHP-FPM และ MariaDB (LEMP) บน Ubuntu
สิ่งที่ต้องเตรียม (Nginx Server Block)
- Ubuntu 22.04/24.04 หรือ AlmaLinux/Rocky Linux 8-9 ที่ติดตั้ง Nginx แล้ว
- ผู้ใช้ที่มีสิทธิ์
sudo - โดเมนทุกโดเมนชี้ A Record มาที่ IP ของเซิร์ฟเวอร์ (ตัวอย่างใช้
203.0.113.10) - สำรองโฟลเดอร์ Config เดิมไว้ก่อนแก้ไข:
sudo cp -a /etc/nginx /etc/nginx.bak-$(date +%F)
โครงสร้างไฟล์ Config บนแต่ละ Distro (Nginx Server Block)
| Ubuntu | AlmaLinux / Rocky Linux | |
|---|---|---|
| ตำแหน่งไฟล์ Server Block | /etc/nginx/sites-available/ แล้วสร้าง Symlink ไปที่ /etc/nginx/sites-enabled/ | /etc/nginx/conf.d/*.conf (ไฟล์ต้องลงท้าย .conf) |
| ผู้ใช้ที่ Nginx รัน | www-data | nginx |
| Socket ของ PHP-FPM | /run/php/php8.3-fpm.sock (24.04) หรือ /run/php/php8.1-fpm.sock (22.04) | /run/php-fpm/www.sock |
| Default Site ที่มากับแพ็กเกจ | sites-enabled/default | บล็อก server ใน /etc/nginx/nginx.conf |
ตรวจชื่อ Socket ของ PHP-FPM บนเครื่องคุณด้วย ls /run/php/ (Ubuntu) หรือ ls /run/php-fpm/ (AlmaLinux/Rocky) เพราะชื่อจะเปลี่ยนตามเวอร์ชัน PHP ที่ติดตั้ง
ขั้นตอนที่ 1: สร้างโฟลเดอร์ของแต่ละเว็บ (Nginx Server Block)
sudo mkdir -p /var/www/example.com/public /var/www/example.net/public
echo '<?php echo "example.com OK";' | sudo tee /var/www/example.com/public/index.php
echo '<h1>example.net OK</h1>' | sudo tee /var/www/example.net/public/index.html
ไฟล์ทดสอบนี้ใช้ยืนยันว่าแต่ละโดเมนไปถึงโฟลเดอร์ที่ถูกต้อง ภายหลังค่อยแทนที่ด้วยไฟล์เว็บจริง
ขั้นตอนที่ 2: สร้าง Server Block สำหรับเว็บ PHP (Nginx Server Block)
บน Ubuntu สร้างไฟล์ /etc/nginx/sites-available/example.com บน AlmaLinux/Rocky สร้าง /etc/nginx/conf.d/example.com.conf เนื้อหาเหมือนกัน ยกเว้นบรรทัด fastcgi_pass:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.php index.html;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
คำอธิบาย:
server_nameคือรายชื่อโดเมนที่ Server Block นี้รับ ใส่ทั้งแบบมีและไม่มีwwwtry_filesบรรทัดนี้เหมาะกับ WordPress และเฟรมเวิร์กที่ส่งทุก Request ไปที่index.phplocation ~ /\.(?!well-known)ปฏิเสธการเข้าถึงไฟล์ที่ขึ้นต้นด้วยจุด เช่น.gitหรือ.envแต่ยังปล่อย.well-knownไว้ให้ Let's Encrypt ใช้- Log แยกของแต่ละเว็บทำให้หาสาเหตุ Error ได้ง่ายกว่ารวมในไฟล์เดียว
บน AlmaLinux/Rocky ไม่มีไฟล์ snippets/fastcgi-php.conf ให้ใช้บล็อก PHP แบบนี้แทน:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
ขั้นตอนที่ 3: สร้าง Server Block สำหรับเว็บ HTML ล้วน
server {
listen 80;
listen [::]:80;
server_name example.net www.example.net;
root /var/www/example.net/public;
index index.html;
access_log /var/log/nginx/example.net.access.log;
error_log /var/log/nginx/example.net.error.log;
location / {
try_files $uri $uri/ =404;
}
}
บันทึกเป็น /etc/nginx/sites-available/example.net (Ubuntu) หรือ /etc/nginx/conf.d/example.net.conf (AlmaLinux/Rocky)
ขั้นตอนที่ 4: ตั้ง Default Server ที่ปฏิเสธโดเมนที่ไม่รู้จัก
เมื่อมี Request ที่ Header Host ไม่ตรงกับ server_name ใดเลย เช่น มีคนเข้าด้วย IP ตรง ๆ หรือโดเมนของคนอื่นชี้มาที่ IP คุณ Nginx จะใช้ Server Block ที่มี default_server หรือถ้าไม่มี ก็ใช้บล็อกแรกที่อ่านเจอ ซึ่งอาจเป็นเว็บลูกค้าของคุณ ผลคือเว็บของคุณไปปรากฏใต้โดเมนอื่นและกระทบ SEO ได้ ให้สร้างบล็อก Default ที่ตัดการเชื่อมต่อทิ้ง:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
444 เป็นรหัสพิเศษของ Nginx ที่ปิดการเชื่อมต่อทันทีโดยไม่ส่งคำตอบกลับ
บน Ubuntu ให้บันทึกเป็น /etc/nginx/sites-available/000-default-deny แล้วปิดไซต์ Default เดิมเพราะมี default_server อยู่แล้ว และจะชนกัน:
sudo rm /etc/nginx/sites-enabled/default
บน AlmaLinux/Rocky ให้บันทึกเป็น /etc/nginx/conf.d/000-default-deny.conf แล้วเปิด /etc/nginx/nginx.conf ดูบล็อก server เดิมที่มากับแพ็กเกจ หากบรรทัด listen ในบล็อกนั้นมีคำว่า default_server (พบในบางเวอร์ชัน) ให้ลบคำนั้นออก หรือใส่ # หน้าบล็อกทั้งหมดหากไม่ได้ใช้