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

Apache HTTP Server ยังคงเป็น Web Server ที่ได้รับความนิยมสูง โดยเฉพาะบน LAMP Stack ที่ใช้กันบน VPS การติดตั้ง SSL บน Apache ต้องเปิดใช้ mod_ssl และตั้งค่า VirtualHost สำหรับ HTTPS บทความนี้ครอบคลุมทั้ง SSL แบบซื้อและ Let's Encrypt ผ่าน Certbot Apache Plugin

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

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

ตรวจสอบว่า Apache กำลังทำงาน:

sudo systemctl status apache2

เปิด Port 80 และ 443 ใน UFW:

sudo ufw allow 80
sudo ufw allow 443
sudo ufw status

ทดสอบว่า Domain ชี้มาที่ IP เซิร์ฟเวอร์แล้ว:

dig example.com +short

ส่วนที่ 2 — เปิดใช้ mod_ssl บน Apache

Apache บน Ubuntu ต้องเปิดใช้ mod_ssl ก่อนจึงจะรับ HTTPS ได้:

# เปิด mod_ssl และ mod_rewrite (สำหรับ redirect)
sudo a2enmod ssl
sudo a2enmod rewrite

# Restart Apache เพื่อให้ module มีผล
sudo systemctl restart apache2

ตรวจสอบว่า mod_ssl เปิดใช้แล้ว:

apache2ctl -M | grep ssl

ถ้าเห็น ssl_module (shared) แสดงว่า mod_ssl พร้อมใช้งาน

ส่วนที่ 3 — ติดตั้ง SSL แบบซื้อ บน Apache

เมื่อได้รับไฟล์ Certificate จาก CA แล้ว ให้ทำตามขั้นตอนนี้:

3.1 วางไฟล์ Certificate

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

# วางไฟล์ certificate
sudo cp your_domain.crt /etc/apache2/ssl/example.com/certificate.crt
sudo cp your_private.key /etc/apache2/ssl/example.com/private.key

# ถ้า CA ให้ intermediate certificate มาด้วย
sudo cp intermediate.crt /etc/apache2/ssl/example.com/ca_bundle.crt

# ตั้ง permission
sudo chmod 600 /etc/apache2/ssl/example.com/private.key
sudo chmod 644 /etc/apache2/ssl/example.com/certificate.crt

3.2 สร้าง VirtualHost สำหรับ HTTPS

sudo nano /etc/apache2/sites-available/example.com-ssl.conf
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com

    SSLEngine on
    SSLCertificateFile      /etc/apache2/ssl/example.com/certificate.crt
    SSLCertificateKeyFile   /etc/apache2/ssl/example.com/private.key
    # ถ้ามี intermediate certificate
    SSLCertificateChainFile /etc/apache2/ssl/example.com/ca_bundle.crt

    <Directory /var/www/example.com>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-ssl-access.log combined
</VirtualHost>
# เปิดใช้งาน site ใหม่
sudo a2ensite example.com-ssl.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

ส่วนที่ 4 — ติดตั้ง Let's Encrypt ด้วย Certbot Apache Plugin

Certbot สำหรับ Apache จะจัดการทุกอย่างให้อัตโนมัติ รวมถึงการแก้ไข VirtualHost:

# ติดตั้ง Certbot และ Apache plugin
sudo apt update
sudo apt install certbot python3-certbot-apache -y

# ขอ Certificate สำหรับ Domain
sudo certbot --apache -d example.com -d www.example.com

Certbot จะถาม:

ข้อดีของ Certbot --apache: แก้ไข VirtualHost ให้อัตโนมัติ, เพิ่ม SSL directives ให้, และตั้ง Redirect ให้โดยไม่ต้องแก้ config เอง

ส่วนที่ 5 — ตั้งค่า VirtualHost + Redirect HTTP→HTTPS แบบ Manual

ถ้าต้องการตั้งค่า Redirect เองโดยไม่ผ่าน Certbot ให้แก้ VirtualHost Port 80:

sudo nano /etc/apache2/sites-available/example.com.conf
# VirtualHost Port 80: Redirect ทุก Request ไป HTTPS
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    # 301 Permanent Redirect
    Redirect permanent / https://example.com/
</VirtualHost>

# หรือใช้ mod_rewrite แบบ Flexible กว่า
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

⚠️ ระวัง: ถ้าใช้ Redirect permanent / จะต้องแน่ใจว่า VirtualHost HTTPS ทำงานก่อน มิฉะนั้นผู้เยี่ยมชมจะเจอ Error ทันที ทดสอบ HTTPS ให้ได้ก่อนเปิด Redirect เสมอ

ส่วนที่ 6 — ทดสอบ Configuration และ Reload

หลังแก้ไข config ทุกครั้ง ต้องทดสอบก่อน reload เสมอ:

# ตรวจสอบ Apache config syntax
sudo apache2ctl configtest

# ถ้า Syntax OK → reload Apache
sudo systemctl reload apache2

# ตรวจสอบ HTTPS ด้วย curl
curl -I https://example.com

# ตรวจสอบ Certificate ด้วย openssl
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

ผล apache2ctl configtest ที่ถูกต้องจะแสดง Syntax OK ถ้ามี Error ให้อ่าน Error message และแก้ไขก่อน reload

ทดสอบ Auto-Renewal สำหรับ Let's Encrypt

# ทดสอบ renewal โดยไม่ต่ออายุจริง
sudo certbot renew --dry-run

Auto-Renewal: Certbot ตั้ง systemd timer ให้อัตโนมัติ ตรวจสอบด้วย systemctl list-timers | grep certbot Certificate จะต่ออายุอัตโนมัติก่อนหมดอายุ 30 วัน

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

Let's Encrypt เป็น SSL ฟรีที่ออกใบรับรองแบบ DV (Domain Validation) อายุ 90 วัน และต่ออายุอัตโนมัติได้ Certbot Apache plugin เหมาะกับมือใหม่มากที่สุด เพราะแก้ไฟล์ VirtualHost ให้เองโดยที่เราแทบไม่ต้องแตะ config ด้วยตัวเอง ขั้นตอนตั้งแต่ต้นจนจบมีดังนี้

# 1) อัปเดต package list และติดตั้ง Certbot + Apache plugin
sudo apt update
sudo apt install certbot python3-certbot-apache -y

# 2) ตรวจว่า Apache มี VirtualHost พอร์ต 80 ที่ ServerName ตรงกับ domain
#    Certbot อ่าน ServerName/ServerAlias เพื่อรู้ว่าจะออก cert ให้ domain ไหน
sudo apache2ctl -S

# 3) ขอใบรับรองและให้ Certbot แก้ VirtualHost ให้อัตโนมัติ
sudo certbot --apache -d example.com -d www.example.com

# 4) ถ้าต้องการขอ cert เฉยๆ โดยไม่ให้ Certbot แตะ config (จัดการ VirtualHost เอง)
sudo certbot certonly --apache -d example.com -d www.example.com

เมื่อรัน certbot --apache ระบบจะถามอีเมลสำหรับแจ้งเตือนวันหมดอายุ ให้ยอมรับ Terms of Service และเลือกว่าจะ Redirect HTTP ไป HTTPS หรือไม่ (แนะนำเลือก Redirect) หลังจากนั้น Certbot จะสร้างไฟล์ example.com-le-ssl.conf ใน sites-available ให้โดยอัตโนมัติ และไฟล์ cert จะถูกเก็บไว้ที่ /etc/letsencrypt/live/example.com/

ข้อควรรู้ก่อนขอใบรับรองคือ Let's Encrypt จะตรวจสอบความเป็นเจ้าของ domain ผ่านวิธีที่เรียกว่า HTTP-01 challenge กล่าวคือเซิร์ฟเวอร์ของ Let's Encrypt จะส่งคำขอเข้ามาที่ domain ของเราทาง port 80 เพื่อยืนยันว่าเราควบคุมเว็บเซิร์ฟเวอร์นี้จริง ดังนั้นในตอนขอและตอนต่ออายุ port 80 ต้องเปิดและเข้าถึงได้จากภายนอกเสมอ หาก domain ยังไม่ได้ชี้มาที่ไอพีของเซิร์ฟเวอร์ หรือมี firewall ปิด port 80 อยู่ การออกใบรับรองจะล้มเหลวทันที จุดนี้เป็นสาเหตุที่มือใหม่มักติดบ่อยที่สุด แนะนำให้ตรวจ DNS ด้วยคำสั่ง dig และทดสอบเปิดหน้าเว็บผ่าน http ก่อนสั่งขอใบรับรองทุกครั้ง

กรณีเว็บไซต์ของคุณมีหลาย domain หรือหลาย subdomain บนเซิร์ฟเวอร์เดียวกัน สามารถใส่ -d ต่อท้ายได้หลายตัวในคำสั่งเดียว เช่น -d example.com -d www.example.com -d blog.example.com Certbot จะรวมทุก domain ไว้ในใบรับรองเดียว (เรียกว่า SAN certificate) ทำให้บริหารจัดการง่ายและต่ออายุพร้อมกันทั้งหมด อย่างไรก็ตามถ้าต้องการครอบคลุม subdomain แบบไม่จำกัด (เช่น ทุกอย่างที่ลงท้ายด้วย example.com) จะต้องใช้ Wildcard certificate ซึ่งต้องยืนยันผ่าน DNS-01 challenge แทน เป็นคนละวิธีกับ Apache plugin ทั่วไป

ตำแหน่งไฟล์ Let's Encrypt: fullchain.pem (cert + chain รวมกัน), privkey.pem (private key), cert.pem และ chain.pem — ทั้งหมดอยู่ใน /etc/letsencrypt/live/example.com/ โดย Certbot จะอ้างถึง fullchain.pem และ privkey.pem ใน VirtualHost ให้เอง

ตั้งค่า VirtualHost พอร์ต 443 ด้วยมือ (SSLCertificateFile / Key / Chain)

ถ้าใช้ SSL แบบซื้อ หรืออยากคุม config ของ Let's Encrypt เอง ให้สร้าง VirtualHost พอร์ต 443 และระบุไฟล์ certificate ทั้ง 3 ส่วนให้ครบ ได้แก่ certificate ของ domain, private key และ chain (intermediate) certificate

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com

    SSLEngine on
    # ไฟล์ certificate ของ domain (.crt หรือ cert.pem)
    SSLCertificateFile      /etc/apache2/ssl/example.com/certificate.crt
    # private key ที่ใช้ตอนสร้าง CSR (.key หรือ privkey.pem)
    SSLCertificateKeyFile   /etc/apache2/ssl/example.com/private.key
    # intermediate / chain certificate จาก CA (.ca-bundle หรือ chain.pem)
    SSLCertificateChainFile /etc/apache2/ssl/example.com/ca_bundle.crt

    # แนะนำ: เปิดเฉพาะ TLS 1.2 ขึ้นไป ปิดโปรโตคอลเก่าที่ไม่ปลอดภัย
    SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder     on

    <Directory /var/www/example.com>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-ssl-access.log combined
</VirtualHost>

สำหรับ Apache เวอร์ชัน 2.4.8 ขึ้นไป สามารถรวม cert + chain ไว้ในไฟล์เดียวแล้วใช้ SSLCertificateFile อย่างเดียวก็ได้ (ไม่ต้องใช้ SSLCertificateChainFile) แต่การแยกไฟล์ตามตัวอย่างจะอ่านง่ายและจัดการชัดเจนกว่า ตารางด้านล่างสรุป directive สำคัญและไฟล์ที่ใช้คู่กัน

หัวใจสำคัญที่ทำให้มือใหม่พลาดบ่อยคือเรื่องของ chain certificate หรือ intermediate certificate ใบรับรองที่ CA ออกให้นั้นไม่ได้ถูกเซ็นโดย Root CA โดยตรง แต่ถูกเซ็นผ่านใบกลางอีกชั้นหนึ่ง หากเราไม่ติดตั้งใบกลางนี้ด้วย เบราว์เซอร์บนคอมพิวเตอร์อาจยังพอเชื่อมโยงไปหา Root ได้เอง แต่เบราว์เซอร์บนมือถือหลายรุ่นจะแสดงข้อความว่าใบรับรองไม่สมบูรณ์หรือไม่น่าเชื่อถือ ดังนั้นเมื่อ CA ส่งไฟล์มาให้ ควรติดตั้งทั้งใบของ domain และใบ intermediate ให้ครบเสมอ และทดสอบด้วยเครื่องมือตรวจสอบ SSL จากภายนอกเพื่อยืนยันว่า chain ต่อกันสมบูรณ์

ส่วนของ private key ถือเป็นไฟล์ที่ต้องเก็บเป็นความลับสูงสุด เพราะใครก็ตามที่ได้ไฟล์นี้ไปจะสามารถปลอมตัวเป็นเว็บไซต์ของเราได้ จึงต้องตั้งสิทธิ์การเข้าถึงเป็น chmod 600 ให้เฉพาะ root อ่านได้เท่านั้น ห้ามอัปโหลด private key ขึ้นที่สาธารณะ ห้ามส่งผ่านอีเมลแบบไม่เข้ารหัส และไม่ควรนำไปใช้ซ้ำข้ามเซิร์ฟเวอร์โดยไม่จำเป็น หากสงสัยว่า private key รั่วไหล ควรเพิกถอน (revoke) ใบรับรองเดิมและออกใบใหม่ทันที

Directive ไฟล์ที่ใช้ คำอธิบาย
SSLCertificateFile certificate.crt / fullchain.pem certificate ของ domain ที่ CA ออกให้
SSLCertificateKeyFile private.key / privkey.pem private key คู่กับ CSR ต้อง chmod 600
SSLCertificateChainFile ca_bundle.crt / chain.pem intermediate cert ของ CA (เลี่ยง chain error บนมือถือ)

บังคับ HTTPS (Force Redirect) + เปิด HSTS บน Apache (.htaccess / VirtualHost)

หลังติดตั้ง SSL เรียบร้อยแล้ว ควรบังคับให้ทุก request ไปที่ HTTPS เสมอ และเปิด HSTS (HTTP Strict Transport Security) เพื่อบอก browser ให้จำว่า domain นี้ต้องเข้าผ่าน HTTPS เท่านั้น ทำได้ทั้งในระดับ VirtualHost และระดับ .htaccess

วิธีที่ 1 — Redirect ใน VirtualHost พอร์ต 80

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    # 301 ถาวร ไปยัง HTTPS
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

วิธีที่ 2 — Force HTTPS ใน .htaccess (เหมาะกับ shared/DocumentRoot)

# วางไว้ที่ไฟล์ .htaccess ใน DocumentRoot (ต้องเปิด AllowOverride All)
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

วิธีที่ 3 — เปิด HSTS header

เพิ่ม HSTS header ใน VirtualHost พอร์ต 443 (ต้องเปิด mod_headers ด้วย sudo a2enmod headers ก่อน):

# ใน VirtualHost *:443 หลังจากตั้งค่า SSL แล้ว
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

⚠️ ระวัง HSTS: เมื่อ browser จำ HSTS แล้วจะ บังคับ HTTPS ตลอด max-age ที่ตั้งไว้ ถ้า SSL หมดอายุหรือพัง ผู้ใช้จะเข้าเว็บไม่ได้เลย — ควรเปิด HSTS หลังจากมั่นใจว่า HTTPS ทำงานเสถียรและต่ออายุอัตโนมัติได้แล้วเท่านั้น และอย่าเพิ่งใส่ preload จนกว่าจะพร้อมจริง

เปิด module ssl, ทดสอบ (apachectl configtest), ต่ออายุ + ปัญหาที่พบบ่อย

ก่อน reload ทุกครั้ง ให้ตรวจ syntax และยืนยันว่า module ที่จำเป็นเปิดอยู่ครบ ขั้นตอนตรวจสอบและคำสั่งที่ใช้บ่อยมีดังนี้

# เปิด module ที่จำเป็น (ssl, rewrite, headers)
sudo a2enmod ssl rewrite headers

# ตรวจ syntax ของ config ก่อน reload เสมอ
sudo apachectl configtest        # เทียบเท่า apache2ctl configtest

# ถ้าได้ Syntax OK → reload ให้ config มีผล
sudo systemctl reload apache2

# ต่ออายุ Let's Encrypt แบบทดสอบ (ไม่ต่อจริง)
sudo certbot renew --dry-run

# ตรวจวันหมดอายุของ cert ทั้งหมด
sudo certbot certificates

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

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

Let's Encrypt ฟรีจริงไหม ต่างจาก SSL แบบเสียเงินอย่างไร?

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

ติดตั้ง SSL บน Apache แล้วเว็บยังขึ้นว่า "ไม่ปลอดภัย" เพราะอะไร?

สาเหตุที่พบบ่อยคือยังมี mixed content (โหลดรูป/สคริปต์ผ่าน http://), ลืมใส่ SSLCertificateChainFile ทำให้ chain ไม่ครบ หรือยังไม่ได้บังคับ redirect ไป HTTPS ให้ตรวจ mixed content ใน Console ของเบราว์เซอร์ และเพิ่ม intermediate certificate ให้ครบ

ต้อง restart หรือ reload Apache หลังติดตั้ง SSL?

ใช้ sudo systemctl reload apache2 ก็เพียงพอสำหรับการโหลด config ใหม่โดยไม่ตัดการเชื่อมต่อที่กำลังทำงานอยู่ ส่วน restart จะใช้เมื่อเปิด/ปิด module (เช่น mod_ssl) ครั้งแรก และต้อง configtest ผ่านก่อนทุกครั้ง

Certbot ต่ออายุ Let's Encrypt อัตโนมัติจริงไหม ต้องตั้ง cron เองหรือไม่?

Certbot รุ่นใหม่ติดตั้ง systemd timer ให้อัตโนมัติแล้ว ไม่ต้องตั้ง cron เอง ตรวจได้ด้วย systemctl list-timers | grep certbot และทดสอบด้วย sudo certbot renew --dry-run ขอแค่ port 80 เปิดไว้ ใบรับรองจะต่ออายุก่อนหมด 30 วันโดยอัตโนมัติ

Checklist ติดตั้ง SSL บน Apache

  1. ติดตั้ง Apache, เปิด mod_ssl และ mod_rewrite
  2. ตรวจสอบ DNS A Record ชี้มาที่ IP เซิร์ฟเวอร์
  3. วางไฟล์ Certificate และ Key ด้วย permission 600/644
  4. สร้าง VirtualHost สำหรับ Port 443 พร้อม SSLCertificateFile directives
  5. เพิ่ม VirtualHost Port 80 สำหรับ Redirect → HTTPS
  6. รัน apache2ctl configtest ก่อน reload เสมอ
  7. ตรวจสอบด้วย curl -I และ openssl s_client
  8. สำหรับ Let's Encrypt: ทดสอบ renewal ด้วย --dry-run

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

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

ดู SSL Certificate