SSL certificate และ HTTPS

ติดตั้ง SSL ฟรีบน VPS ด้วย Let's Encrypt และ Certbot

มิถุนายน 2026 · อ่าน 5 นาที

SSL ไม่ใช่แค่กุญแจล็อก มันส่งผลต่อ SEO, ความน่าเชื่อถือของเว็บ และ browser warning ที่จะขับไล่ผู้เยี่ยมชม บทความนี้อธิบายการติดตั้ง SSL ฟรีบน VPS ตั้งแต่ต้นจนจบ


Let's Encrypt คืออะไร

Let's Encrypt คือ Certificate Authority (CA) ที่ให้ SSL Certificate ฟรี ออกโดย Internet Security Research Group (ISRG) ซึ่งได้รับการสนับสนุนจาก Mozilla, Google, Cisco และอีกหลายองค์กร

Certificate มีอายุ 90 วัน แต่ Certbot จะต่ออายุอัตโนมัติ ไม่ต้องทำเองทุกครั้ง

ข้อกำหนดก่อนติดตั้ง

ติดตั้งบน Nginx (Ubuntu/Debian)

apt update
apt install certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.com

Certbot จะถาม email สำหรับแจ้งเตือนก่อน certificate หมดอายุ และถามว่าต้องการ redirect HTTP → HTTPS อัตโนมัติหรือไม่ แนะนำให้เลือก redirect

ติดตั้งบน Apache (Ubuntu/Debian)

apt install certbot python3-certbot-apache
certbot --apache -d example.com -d www.example.com

ทดสอบการต่ออายุอัตโนมัติ

certbot renew --dry-run

คำสั่งนี้จำลองการต่ออายุโดยไม่ได้ออก certificate จริง ใช้ตรวจสอบว่าระบบทำงานได้ถูกต้อง

Wildcard Certificate

ถ้าต้องการ SSL ครอบ subdomain ทั้งหมด เช่น *.example.com ต้องใช้ DNS challenge แทน HTTP challenge

certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d example.com

ระบบจะให้เพิ่ม TXT record ใน DNS ก่อน แล้วจึงออก certificate ให้

ตรวจสอบ Certificate ที่ได้

# ดู certificate ทั้งหมดที่ Certbot จัดการ
certbot certificates

# ตรวจสอบวันหมดอายุด้วย openssl
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates

# ตรวจว่า auto-renew timer ทำงานอยู่
systemctl status certbot.timer
Timer vs Cron: Ubuntu 22.04+ ใช้ systemd timer แทน cron ตรวจสอบด้วย systemctl status certbot.timer ถ้าเห็น active = ทำงานปกติ ถ้าไม่ active ให้รัน systemctl enable certbot.timer --now

ตั้งค่า HTTPS Redirect ใน Nginx

Certbot มักตั้ง redirect ให้อัตโนมัติ แต่ถ้าต้องการตั้งเองหรือแก้ไข:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # เพิ่ม HSTS บอก browser ให้ใช้ HTTPS เสมอ
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
}

แก้ปัญหาที่พบบ่อย

Error: "Connection refused on port 80" หรือ "Challenge failed"

Let's Encrypt ต้องเข้าถึง http://example.com/.well-known/acme-challenge/ ได้ในระหว่าง verify:

# ดูว่า web server กำลังรัน
systemctl status nginx   # หรือ apache2

# ตรวจ firewall ว่าเปิด port 80
ufw status | grep "80\|ALLOW"

# ทดสอบ path จากภายนอก
curl -I http://example.com/.well-known/acme-challenge/test
Cloudflare Orange Cloud: ปิด proxy (เปลี่ยนเป็น grey cloud) ชั่วคราวระหว่างออก certificate แล้วค่อยเปิดกลับ Certbot อ่าน IP จริงของ VPS ไม่ได้ถ้า proxy เปิดอยู่

Error: "Too many failed authorizations" หรือ "Too many certificates already issued"

Let's Encrypt จำกัด 5 certificate ต่อ domain ต่อชั่วโมง และ 50 ต่อสัปดาห์ ใช้ staging environment ทดสอบก่อนไม่ติด rate limit:

certbot --nginx -d example.com --staging
# ถ้า staging สำเร็จ ค่อยออก certificate จริง (ไม่ต้องใส่ --staging)

Certificate ได้ Grade B หรือ C ที่ SSL Labs

เพิ่มใน Nginx server block เพื่อปิด protocol เก่าและ cipher ที่อ่อนแอ:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;

ทดสอบผลลัพธ์ที่ ssllabs.com/ssltest/ ควรได้ Grade A หรือ A+

Certbot renew ล้มเหลว: "Port 80 is already in use"

เกิดเมื่อใช้ standalone mode และ web server กำลังรันอยู่ แก้โดยใช้ webroot mode แทน:

# แก้ /etc/letsencrypt/renewal/example.com.conf
authenticator = webroot
webroot_path = /var/www/html

certbot renew --quiet

Wildcard certificate ขอแล้ว TXT record ไม่ผ่าน

Certbot ต้องการให้เพิ่ม TXT record ใน DNS ก่อน แล้วรอ propagate สักครู่ก่อนกด Enter:

# ตรวจว่า TXT record propagate แล้ว
dig TXT _acme-challenge.example.com +short

# รอให้ตรงกับค่าที่ certbot แสดง ค่อยกด Enter ใน certbot

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

Let's Encrypt ฟรีจริงไหม มีค่าใช้จ่ายซ่อนไหม?

ฟรีทั้งหมด ไม่มีแผนชำระเงิน Let's Encrypt เป็น non-profit ที่ได้รับการสนับสนุนจาก Mozilla, Google, Cisco และ EFF ข้อจำกัดคือเป็น Domain Validated (DV) เท่านั้น ไม่มี OV หรือ EV certificate ที่แสดงชื่อบริษัทใน address bar

ต้อง renew เองทุก 90 วันไหม?

ไม่ต้อง Certbot ติดตั้ง systemd timer หรือ cron job อัตโนมัติระหว่างติดตั้ง จะ renew เมื่อ certificate เหลือน้อยกว่า 30 วัน ทดสอบว่าระบบ auto-renew ทำงานได้ด้วย certbot renew --dry-run (ไม่ออก certificate จริง)

Let's Encrypt รองรับ wildcard *.example.com ไหม?

รองรับตั้งแต่ปี 2018 แต่ต้องใช้ DNS challenge ไม่ใช่ HTTP challenge และต้องมี DNS plugin รองรับ provider เช่น certbot-dns-cloudflare สำหรับ Cloudflare Wildcard ครอบ subdomain ชั้นเดียว *.example.com ครอบ mail.example.com แต่ไม่ครอบ a.b.example.com

ถ้า certificate หมดอายุโดยไม่ได้ renew จะเกิดอะไร?

Browser แสดงหน้าเตือน "Your connection is not private" พร้อม error NET::ERR_CERT_DATE_INVALID ผู้เยี่ยมชมส่วนใหญ่จะออกทันที Let's Encrypt ส่งอีเมลเตือนล่วงหน้า 20 วันและ 10 วันก่อนหมดอายุไปยัง email ที่ลงทะเบียนไว้

ใช้ Let's Encrypt กับ wildcard domain บน Cloudflare ยังไง?

ติดตั้ง plugin และสร้าง API token ของ Cloudflare ที่มีสิทธิ์แก้ DNS zone แล้วรัน Certbot:

pip install certbot-dns-cloudflare
# สร้างไฟล์ ~/.secrets/cloudflare.ini ใส่ dns_cloudflare_api_token = YOUR_TOKEN
certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d "example.com" -d "*.example.com"

สรุป

Let's Encrypt ลบข้อแก้ตัวเรื่อง "SSL แพง" ออกไปทั้งหมด ไม่มีเหตุผลที่เว็บสมัยนี้จะไม่มี HTTPS ขั้นตอนทั้งหมดใช้เวลาไม่ถึง 10 นาทีและทำงานอัตโนมัติหลังจากนั้น ถ้าพบปัญหาระหว่างออก certificate ให้ตรวจ port 80, firewall และ DNS ก่อนเสมอ