ติดตั้ง SSL Certificate บน Nginx Server ทีละขั้นตอน

Nginx เป็น Web Server ยอดนิยมที่ใช้บน VPS Linux ทั่วโลก แต่การติดตั้ง SSL Certificate บน Nginx มีขั้นตอนที่แตกต่างจาก Apache พอสมควร บทความนี้ครอบคลุมทั้งแบบ SSL Certificate ที่ซื้อจาก CA (DV/OV) และแบบ Let's Encrypt ฟรีผ่าน Certbot พร้อมตั้งค่า redirect HTTP→HTTPS และการต่ออายุอัตโนมัติ

สิ่งที่ต้องมีก่อน: VPS Ubuntu 20.04/22.04, ติดตั้ง Nginx แล้ว, มี Domain ที่ DNS ชี้มายัง IP ของเซิร์ฟเวอร์นี้แล้ว, Root หรือ Sudo access

ส่วนที่ 1 — ก่อนติดตั้ง: สิ่งที่ต้องมี

ก่อนเริ่มติดตั้ง SSL ตรวจสอบรายการต่อไปนี้ให้ครบ:

ส่วนที่ 2 — ติดตั้ง SSL แบบซื้อ (Commercial) บน Nginx

เมื่อซื้อ SSL จาก CA (เช่น RapidSSL, DigiCert) คุณจะได้รับไฟล์ Certificate มาทาง Email ให้ทำตามขั้นตอนนี้:

2.1 อัปโหลดและจัดเก็บไฟล์ Certificate

# สร้าง directory เก็บ SSL
sudo mkdir -p /etc/nginx/ssl/example.com

# อัปโหลด/วางไฟล์ certificate ที่ได้จาก CA
sudo cp your_domain.crt /etc/nginx/ssl/example.com/fullchain.pem
sudo cp your_private.key /etc/nginx/ssl/example.com/privkey.pem

# ถ้า CA ส่ง intermediate certificate มาด้วย ให้รวมกันก่อน
cat your_domain.crt intermediate.crt > /etc/nginx/ssl/example.com/fullchain.pem

# ตั้ง permission ให้ปลอดภัย
sudo chmod 600 /etc/nginx/ssl/example.com/privkey.pem
sudo chmod 644 /etc/nginx/ssl/example.com/fullchain.pem

2.2 ตั้งค่า Nginx Server Block

sudo nano /etc/nginx/sites-available/example.com
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;

    # SSL Protocol ที่ปลอดภัย
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    root /var/www/example.com;
    index index.html index.php;

    location / {
        try_files $uri $uri/ =404;
    }
}

# Redirect HTTP → HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
# เปิดใช้งาน site
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# ทดสอบ config ก่อน reload
sudo nginx -t

# ถ้าผ่าน ให้ reload
sudo systemctl reload nginx

ส่วนที่ 3 — ติดตั้ง Let's Encrypt บน Nginx ด้วย Certbot

Let's Encrypt เป็น SSL ฟรีที่ใช้งานได้จริงสำหรับ Production Certbot จะจัดการทุกอย่างให้อัตโนมัติ ตั้งแต่ขอ Certificate ไปจนถึงแก้ไข Server Block

3.1 ติดตั้ง Certbot

sudo apt update
sudo apt install certbot python3-certbot-nginx -y

3.2 ขอ Certificate และตั้งค่าอัตโนมัติ

# Certbot จะแก้ไข Nginx config และตั้ง redirect ให้อัตโนมัติ
sudo certbot --nginx -d example.com -d www.example.com

Certbot จะถามอีเมลและข้อตกลง แล้วจะทำ ACME Challenge เพื่อยืนยัน Domain โดยอัตโนมัติ เมื่อสำเร็จ Nginx config จะถูกแก้ไขให้รองรับ HTTPS ทันที

ข้อดีของ Certbot --nginx: แก้ไข server block ให้อัตโนมัติ ไม่ต้องตั้งค่า SSL path เอง และตั้ง redirect HTTP→HTTPS ให้ด้วย

ส่วนที่ 4 — ตั้งค่า Redirect HTTP→HTTPS (แบบ Manual)

ถ้าต้องการตั้ง redirect เองโดยไม่ให้ Certbot แก้ไข ให้เพิ่ม server block นี้:

server {
    listen 80;
    server_name example.com www.example.com;
    # 301 = Permanent Redirect (ดีต่อ SEO)
    return 301 https://$host$request_uri;
}

⚠️ ระวัง Redirect Loop: อย่าใส่ return 301 ใน server block ที่ listen 443 เพราะจะทำให้วนซ้ำไม่รู้จบ ให้แยก server block 80 และ 443 ออกจากกันเสมอ

ส่วนที่ 5 — ตรวจสอบ SSL ด้วย openssl

หลังติดตั้งเสร็จ ให้ตรวจสอบว่า SSL ทำงานถูกต้อง:

# ตรวจสอบ Certificate ที่ได้รับ
openssl s_client -connect example.com:443 -servername example.com

# ดูวันหมดอายุของ Certificate
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

# ทดสอบจาก curl
curl -I https://example.com

ตรวจสอบว่า Response header มี HTTP/2 200 และไม่มี Certificate Error ใดๆ นอกจากนี้ยังสามารถทดสอบผ่านเว็บ SSL Labs (ssllabs.com/ssltest) เพื่อดู Grade และรายละเอียด Security

ส่วนที่ 6 — ตั้ง Auto-Renewal สำหรับ Let's Encrypt

Certificate ของ Let's Encrypt หมดอายุทุก 90 วัน Certbot ติดตั้ง Cron Job / Systemd Timer ให้อัตโนมัติ ตรวจสอบได้ด้วย:

# ทดสอบว่า renewal ทำงานได้
sudo certbot renew --dry-run

# ดู timer ที่ Certbot ตั้งไว้
systemctl list-timers | grep certbot

Best Practice: หลัง Renewal ควร Reload Nginx ด้วย: sudo certbot renew --deploy-hook "systemctl reload nginx" เพื่อให้ Certificate ใหม่มีผลทันที

ติดตั้ง Let's Encrypt ด้วย Certbot ทีละขั้นตอนแบบละเอียด

หากต้องการเข้าใจการทำงานของ Certbot อย่างละเอียด หรือพบปัญหาในขั้นตอนอัตโนมัติ ลำดับด้านล่างนี้อธิบายทุกขั้นตอนตั้งแต่ต้นจนได้ Certificate ติดตั้งบน Nginx โดย Let's Encrypt เป็น SSL ฟรี ที่เบราว์เซอร์ทั่วโลกเชื่อถือ เหมาะกับเว็บไซต์ทั่วไปที่ต้องการ HTTPS โดยไม่มีค่าใช้จ่าย

ขั้นที่ 1 — เตรียม Server Block พื้นฐานสำหรับ Port 80

ก่อนรัน Certbot ต้องมี server block ที่ตอบ Port 80 และมี server_name ตรงกับ Domain เพราะ Certbot ใช้ HTTP-01 Challenge วางไฟล์ยืนยันใน Webroot ผ่าน Port 80

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
# ทดสอบ config แล้ว reload ให้ Nginx รับ server_name นี้
sudo nginx -t && sudo systemctl reload nginx

ขั้นที่ 2 — รัน Certbot และเลือกโหมดติดตั้งอัตโนมัติ

Certbot plugin --nginx จะอ่าน Nginx config ค้นหา server block ที่ server_name ตรงกับ Domain แล้วแก้ไขให้รองรับ HTTPS โดยอัตโนมัติ:

sudo certbot --nginx -d example.com -d www.example.com \
  --agree-tos -m [email protected] --redirect

ขั้นที่ 3 — แบบ Webroot (กรณีไม่ต้องการให้ Certbot แก้ config)

ถ้าต้องการคุม Nginx config เองทั้งหมด ใช้โหมด webroot เพื่อให้ Certbot ขอแต่ Certificate อย่างเดียว ไม่แตะ config:

sudo certbot certonly --webroot -w /var/www/example.com \
  -d example.com -d www.example.com

ไฟล์ Certificate จะถูกเก็บที่ /etc/letsencrypt/live/example.com/ ประกอบด้วย fullchain.pem (Certificate + Chain) และ privkey.pem (Private Key) ซึ่งนำไปอ้างใน server block ได้โดยตรง

เคล็ดลับ: โหมด webroot ไม่ต้องหยุด Nginx ระหว่างขอ Certificate ต่างจากโหมด standalone ที่ต้องการให้ Port 80 ว่าง — จึงเหมาะกับ Production ที่รัน Nginx อยู่แล้ว

ติดตั้ง SSL ที่ซื้อมา (Full Chain) บน Nginx แบบละเอียด

SSL ที่ซื้อจาก CA (DV/OV/EV) มักส่งไฟล์มาหลายไฟล์ ได้แก่ Certificate ของ Domain (.crt), Intermediate/Chain Certificate (.ca-bundle หรือ chain.crt) และ Private Key (.key) ที่สร้างตอน CSR สิ่งสำคัญที่สุดบน Nginx คือ ต้องรวม Certificate ของ Domain กับ Intermediate เป็นไฟล์ Full Chain เดียว มิฉะนั้นจะเกิดปัญหา chain ไม่สมบูรณ์

รวม Full Chain ให้ถูกลำดับ

ลำดับสำคัญมาก: Certificate ของ Domain ต้องอยู่บนสุด ตามด้วย Intermediate (ห้ามใส่ Root CA):

# ลำดับ: domain cert ก่อน → intermediate ตามหลัง
cat your_domain.crt intermediate.ca-bundle > fullchain.pem

# ย้ายเข้า directory และตั้ง permission
sudo mv fullchain.pem /etc/nginx/ssl/example.com/fullchain.pem
sudo cp your_private.key /etc/nginx/ssl/example.com/privkey.pem
sudo chmod 600 /etc/nginx/ssl/example.com/privkey.pem

อ้างถึงใน server block

ใช้ ssl_certificate ชี้ไปที่ไฟล์ Full Chain และ ssl_certificate_key ชี้ไปที่ Private Key พร้อมเพิ่มค่า Security ที่แนะนำ:

server {
    listen 443 ssl;
    http2 on;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;

    root /var/www/example.com;
    index index.html index.php;
}

⚠️ ห้ามใส่ Root CA ในไฟล์ Full Chain: CA จะส่ง Root Certificate มาด้วยบ้าง แต่ Browser มี Root อยู่แล้วใน Trust Store — ใส่ Root เพิ่มจะทำให้ขนาด handshake โตขึ้นโดยไม่จำเป็น ใส่แค่ Domain Cert + Intermediate ก็พอ

บังคับ HTTPS ด้วย return 301 + เปิด HSTS บน Nginx

หลังติดตั้ง SSL แล้ว ขั้นตอนสำคัญคือบังคับให้ผู้เข้าชมทุกคนใช้ HTTPS เสมอ ทำได้ 2 ชั้น: ชั้นแรกคือ redirect ทุก request จาก Port 80 ด้วย return 301 ชั้นที่สองคือเปิด HSTS (HTTP Strict Transport Security) เพื่อให้ Browser จำว่าให้ใช้ HTTPS เท่านั้นแม้ผู้ใช้พิมพ์ http://

Redirect HTTP→HTTPS ด้วย return 301

# server block แยกสำหรับ Port 80 เท่านั้น
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

เปิด HSTS ใน server block ที่ listen 443

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    # บังคับ HTTPS 1 ปี รวม subdomain
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # ... ssl_certificate และค่าอื่นๆ ตามด้านบน ...
}

⚠️ เปิด HSTS อย่างระวัง: เมื่อ Browser ได้รับ HSTS header แล้วจะ "ล็อก" ให้ใช้ HTTPS ตามระยะ max-age หาก SSL หมดอายุหรือถอด HTTPS ออกในช่วงนั้น เว็บจะเข้าไม่ได้เลย แนะนำเริ่มจาก max-age สั้นๆ (เช่น max-age=300) ก่อนค่อยขยายเป็น 1 ปี และอย่าเพิ่ม preload จนกว่าจะมั่นใจว่าทุก subdomain รองรับ HTTPS

ทดสอบ + ต่ออายุ + ปัญหาที่พบบ่อย

เมื่อติดตั้งเสร็จควรทดสอบให้ครบทั้ง chain การเชื่อมต่อ และเตรียมระบบต่ออายุ พร้อมรู้วิธีแก้ปัญหาที่พบบ่อยบน Nginx

ทดสอบ Chain และวันหมดอายุ

# ตรวจว่า chain สมบูรณ์ (ต้องไม่มี "unable to get local issuer")
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep -i "verify"

# ดูวันหมดอายุ
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

ต่ออายุ Let's Encrypt อัตโนมัติ

# ทดสอบ renewal และ reload Nginx อัตโนมัติเมื่อต่อสำเร็จ
sudo certbot renew --dry-run
sudo certbot renew --deploy-hook "systemctl reload nginx"

ปัญหาที่พบบ่อยและวิธีแก้

ปัญหาส่วนใหญ่ของ SSL บน Nginx มาจากสามจุดหลัก ได้แก่ chain ที่ไม่สมบูรณ์เพราะลืมรวม Intermediate, Port 443 ที่ยังไม่เปิดในไฟร์วอลล์ และ Mixed Content ที่เกิดจากหน้าเว็บยังเรียก resource ผ่าน http:// อยู่ ตารางด้านล่างสรุปอาการที่พบบ่อยพร้อมแนวทางแก้ไขให้ตรวจไล่ทีละข้อได้รวดเร็ว ก่อนนำเว็บไซต์ขึ้นใช้งานจริง ควรทดสอบผ่าน SSL Labs เพื่อยืนยันว่าได้เกรดที่ยอมรับได้และไม่มีคำเตือนเรื่อง chain หรือ protocol ที่ล้าสมัย

อาการ สาเหตุ + วิธีแก้
Chain incomplete / unable to get local issuer ไม่ได้รวม Intermediate ใน ssl_certificate — รวม domain cert + intermediate เป็น fullchain.pem แล้ว reload
เข้า https ไม่ได้ / connection refused Port 443 ไม่เปิดใน Firewall — รัน ufw allow 443 และตรวจ listen 443 ssl; ใน server block
Mixed content (กุญแจไม่เขียว) หน้าเว็บโหลด resource ผ่าน http:// — แก้ลิงก์รูป/CSS/JS เป็น https:// หรือ relative path
Redirect loop (ERR_TOO_MANY_REDIRECTS) ใส่ return 301 ใน server block ที่ listen 443 — ย้ายไปไว้ใน block Port 80 เท่านั้น

สรุป Checklist ติดตั้ง SSL บน Nginx

  1. ตรวจสอบ DNS A Record ชี้มายัง IP เซิร์ฟเวอร์แล้ว
  2. เปิด Port 80 และ 443 ใน UFW Firewall
  3. วางไฟล์ Certificate และ Key ใน directory ที่ปลอดภัย (permission 600/644)
  4. ตั้งค่า ssl_certificate และ ssl_certificate_key ใน server block
  5. เพิ่ม server block แยก Port 80 เพื่อ Redirect → HTTPS
  6. รัน nginx -t ก่อน reload เสมอ
  7. ทดสอบด้วย openssl s_client หรือ SSL Labs
  8. สำหรับ Let's Encrypt: ตั้ง --deploy-hook เพื่อ reload Nginx อัตโนมัติ

คำถามที่พบบ่อย (FAQ)

Let's Encrypt ฟรีกับ SSL ที่ซื้อ ต่างกันอย่างไรบน Nginx?

การตั้งค่าใน Nginx เหมือนกันแทบทั้งหมด — ทั้งคู่ใช้ ssl_certificate และ ssl_certificate_key ความต่างคือ Let's Encrypt ฟรี ออกแบบ DV อายุ 90 วันต่ออายุอัตโนมัติ ส่วน SSL ที่ซื้อมีให้เลือกทั้ง DV/OV/EV อายุ 1 ปี และมีการรับประกัน (Warranty) จาก CA ที่ AsiaGB SSL แบบ DV เริ่มต้น 1,000 บาท/ปี ส่วน Let's Encrypt ฟรีก็ใช้ได้บนเซิร์ฟเวอร์ของเรา

ทำไมติดตั้งแล้ว Browser ยังเตือนว่า chain ไม่สมบูรณ์?

เพราะ ssl_certificate ของ Nginx ต้องชี้ไปที่ไฟล์ที่รวม Certificate ของ Domain กับ Intermediate ไว้ด้วยกัน (Full Chain) ต่างจาก Apache ที่แยกไฟล์ chain ได้ ให้รัน cat your_domain.crt intermediate.crt > fullchain.pem แล้วชี้ ssl_certificate ไปที่ไฟล์นั้น จากนั้น reload Nginx

ต้อง restart หรือ reload Nginx หลังเปลี่ยน Certificate?

ใช้ sudo systemctl reload nginx ก็พอ ไม่ต้อง restart — reload จะโหลด config และ Certificate ใหม่โดยไม่ตัดการเชื่อมต่อที่กำลังทำงานอยู่ และควรรัน sudo nginx -t ตรวจ syntax ก่อน reload ทุกครั้ง

SSL หมดอายุทุก 90 วันจัดการอย่างไรไม่ให้ลืม?

Certbot ติดตั้ง systemd timer ให้อัตโนมัติตั้งแต่ตอนติดตั้ง ตรวจได้ด้วย systemctl list-timers | grep certbot และเพิ่ม --deploy-hook "systemctl reload nginx" เพื่อให้ Nginx โหลด Certificate ใหม่ทันทีหลังต่ออายุ สำหรับ SSL ที่ซื้อแบบ 1 ปี ระบบของ AsiaGB จะมีการแจ้งเตือนก่อนหมดอายุ

SSL Certificate สำหรับเว็บไซต์ของคุณ

AsiaGB มี SSL จาก RapidSSL, GeoTrust และ DigiCert เริ่มต้น 1,000 บาท/ปี รับรองโดย CA ระดับโลก ติดตั้งง่าย มีทีมซัพพอร์ตช่วยเหลือ

ดู SSL Certificate