เมื่อพัฒนาเว็บหรือ API ใน Local Environment หรือ Staging Server นักพัฒนาหลายคนต้องการทดสอบฟีเจอร์ที่ต้องการ HTTPS เช่น Service Worker, Geolocation API, Mixed Content Policy หรือ HTTP/2 แต่ยังไม่อยากติดตั้ง SSL Certificate จริงในขั้นนี้ Self-Signed SSL Certificate ที่สร้างด้วย OpenSSL คือทางออกที่เร็วและฟรีที่สุด บทความนี้อธิบายวิธีสร้าง Self-Signed SSL ทุกขั้นตอนพร้อมตัวอย่างคำสั่งจริง ทั้งสำหรับ Linux, macOS และ Windows รวมถึงวิธีกำหนดค่า Web Server ให้ใช้งาน Certificate ที่สร้างขึ้น

Self-Signed SSL Certificate คืออะไร และใช้เมื่อไหร่

Self-Signed SSL Certificate คือใบรับรองความปลอดภัยแบบ X.509 ที่สร้างและลงนามโดยตัวเองโดยไม่ผ่าน Certificate Authority (CA) ภายนอกเช่น DigiCert, Sectigo หรือ Let's Encrypt ซึ่งหมายความว่า Browser และ OS จะไม่รู้จัก CA ผู้ออกใบรับรอง จึงแสดงคำเตือน "Your connection is not private" หรือ "NET::ERR_CERT_AUTHORITY_INVALID" เสมอ

อย่างไรก็ตาม Self-Signed SSL มีประโยชน์มากในหลายสถานการณ์:

ข้อควรจำ: ห้ามใช้ Self-Signed SSL บน Production Server ที่ผู้ใช้ทั่วไปเข้าถึง เพราะจะทำให้ผู้ใช้เห็นหน้าเตือน "Not Secure" ซึ่งสร้างความไม่น่าเชื่อถือและอาจทำให้ผู้ใช้ออกจากเว็บได้ สำหรับ Production ควรใช้ SSL Certificate จาก CA ที่ Browser เชื่อถือ

ทำความเข้าใจโครงสร้าง SSL Certificate ก่อนเริ่ม

ก่อนสร้าง Certificate ควรเข้าใจว่าไฟล์แต่ละประเภทคืออะไร เพื่อให้ใช้งานได้ถูกต้อง:

ไฟล์/นามสกุล ความหมาย ใช้กับ
server.key Private Key — กุญแจส่วนตัว ห้ามเผยแพร่ Web Server (Apache/Nginx)
server.csr Certificate Signing Request — คำขอรับใบรับรอง ส่งให้ CA (ใน Self-Signed ใช้ Sign เอง)
server.crt Certificate — ใบรับรองที่ใช้งาน (PEM format) Web Server + ติดตั้งใน Browser Trust Store
server.pem PEM format — เหมือน .crt แต่บางระบบต้องการนามสกุลนี้ Linux CA Store, Docker, Node.js
server.pfx / .p12 PKCS#12 — รวม Key + Cert ในไฟล์เดียว Windows IIS, .NET, Java KeyStore

สำหรับ Linux/Apache/Nginx ในบทความนี้จะทำงานกับไฟล์ .key และ .crt เป็นหลัก ซึ่งใช้ PEM format (ข้อความ Base64 ที่ขึ้นต้นด้วย -----BEGIN CERTIFICATE-----)

ตรวจสอบ OpenSSL และเตรียม Environment

OpenSSL มักติดตั้งมาพร้อมกับ Linux และ macOS ส่วน Windows ต้องติดตั้งเพิ่มเติม ตรวจสอบว่ามี OpenSSL อยู่แล้วด้วยคำสั่ง:

openssl version

ผลลัพธ์ที่ควรได้:

OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

ถ้ายังไม่มี OpenSSL ให้ติดตั้งตามระบบปฏิบัติการ:

# Ubuntu/Debian
sudo apt-get update && sudo apt-get install -y openssl

# CentOS/RHEL/Rocky Linux
sudo dnf install -y openssl

# macOS (ผ่าน Homebrew)
brew install openssl

# Windows — ดาวน์โหลด Win32/Win64 OpenSSL จาก https://slproweb.com/products/Win32OpenSSL.html
# หรือใช้ WSL (Windows Subsystem for Linux) แล้วรันคำสั่ง Linux ปกติ

หลังจากนั้นสร้างโฟลเดอร์เก็บไฟล์ Certificate:

mkdir -p ~/ssl-certs && cd ~/ssl-certs

วิธีที่ 1 — สร้าง Self-Signed SSL แบบ Quick (1 คำสั่ง)

วิธีเร็วที่สุดคือสร้าง Private Key และ Certificate พร้อมกันในคำสั่งเดียว เหมาะสำหรับ Dev ที่ต้องการใช้งานทันที:

openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
  -days 365 -nodes \
  -subj "/C=TH/ST=Bangkok/L=Bangkok/O=MyCompany Dev/OU=Development/CN=localhost"

อธิบายพารามิเตอร์แต่ละตัว:

หลังรันคำสั่งจะได้ไฟล์ 2 ไฟล์: server.key (Private Key) และ server.crt (Certificate) พร้อมใช้งานกับ Web Server ได้ทันที

วิธีที่ 2 — สร้าง SSL พร้อม Subject Alternative Names (SAN)

Browser สมัยใหม่ต้องการให้ Certificate มี Subject Alternative Names (SAN) ไม่เช่นนั้นจะแสดงเตือน "Subject Alternative Name Missing" แม้จะยอมรับ Certificate แล้วก็ตาม วิธีนี้สร้าง Certificate ที่ครอบคลุมหลาย hostname:

# สร้างไฟล์ config สำหรับ SAN
cat > san.cnf << 'EOF'
[req]
default_bits       = 4096
prompt             = no
default_md         = sha256
distinguished_name = dn
x509_extensions    = v3_req

[dn]
C  = TH
ST = Bangkok
L  = Bangkok
O  = MyCompany Development
CN = localhost

[v3_req]
subjectAltName = @alt_names
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[alt_names]
DNS.1 = localhost
DNS.2 = *.localhost
DNS.3 = dev.local
DNS.4 = *.dev.local
DNS.5 = staging.myapp.com
IP.1  = 127.0.0.1
IP.2  = 192.168.1.100
EOF

# สร้าง Certificate จาก config ไฟล์
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
  -days 365 -nodes -config san.cnf

ด้วยวิธีนี้ Certificate เดียวจะครอบคลุม localhost, *.localhost, dev.local, *.dev.local, staging.myapp.com รวมถึง IP Address ที่กำหนด ทำให้ใช้ในสภาพแวดล้อม Dev ที่มีหลาย Domain ได้โดยไม่ต้องสร้าง Certificate หลายใบ

วิธีที่ 3 — สร้างแบบแยกขั้นตอน (สำหรับผู้ที่ต้องการความยืดหยุ่น)

ถ้าต้องการควบคุมทุกขั้นตอน หรือต้องการเก็บ CSR ไว้สำหรับใช้ในอนาคต สามารถแยกเป็น 3 ขั้นตอน:

ขั้นตอนที่ 1: สร้าง Private Key

# RSA 4096-bit (แนะนำ)
openssl genrsa -out server.key 4096

# หรือ ECDSA P-256 (เร็วกว่า RSA ทั้ง Gen และ Handshake)
openssl ecparam -genkey -name prime256v1 -out server.key

ขั้นตอนที่ 2: สร้าง CSR (Certificate Signing Request)

openssl req -new -key server.key -out server.csr \
  -subj "/C=TH/ST=Bangkok/L=Bangkok/O=MyOrg/CN=localhost"

ขั้นตอนที่ 3: Sign Certificate ด้วย Private Key ของตัวเอง

openssl x509 -req -in server.csr -signkey server.key \
  -out server.crt -days 365 \
  -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1")

การแยกขั้นตอนช่วยให้คุณเก็บ server.csr ไว้ได้ ซึ่งมีประโยชน์ถ้าต้องการส่งไปให้ Internal CA ขององค์กรลงนามแทนการ Self-Sign

ตรวจสอบ Certificate ที่สร้างขึ้น

หลังสร้าง Certificate แล้ว ควรตรวจสอบข้อมูลเพื่อให้แน่ใจว่าถูกต้องก่อนนำไปใช้งาน:

# ดูข้อมูล Certificate ทั้งหมด
openssl x509 -in server.crt -text -noout

# ดูแค่ Subject, Issuer, Validity
openssl x509 -in server.crt -subject -issuer -dates -noout

# ตรวจสอบว่า Private Key ตรงกับ Certificate
openssl x509 -noout -modulus -in server.crt | md5sum
openssl rsa -noout -modulus -in server.key | md5sum
# ถ้า md5 ตรงกัน แสดงว่า key กับ cert เป็น pair เดียวกัน

# ตรวจสอบ SAN
openssl x509 -in server.crt -text -noout | grep -A2 "Subject Alternative Name"

ผลลัพธ์จาก openssl x509 -text ที่ควรตรวจสอบ:

กำหนดค่า Web Server ให้ใช้งาน Self-Signed SSL

หลังสร้าง Certificate แล้ว ขั้นตอนต่อไปคือกำหนดค่า Web Server เพื่อเปิดใช้ HTTPS สมมติว่าเก็บไฟล์ Certificate ไว้ที่ /etc/ssl/self-signed/:

# คัดลอก Certificate ไปยังตำแหน่งมาตรฐาน
sudo mkdir -p /etc/ssl/self-signed
sudo cp server.key /etc/ssl/self-signed/server.key
sudo cp server.crt /etc/ssl/self-signed/server.crt
# กำหนดสิทธิ์ให้ Private Key อ่านได้เฉพาะ root
sudo chmod 600 /etc/ssl/self-signed/server.key
sudo chmod 644 /etc/ssl/self-signed/server.crt

กำหนดค่า Nginx

server {
    listen 80;
    server_name localhost dev.local;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name localhost dev.local;

    ssl_certificate     /etc/ssl/self-signed/server.crt;
    ssl_certificate_key /etc/ssl/self-signed/server.key;

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

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

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

กำหนดค่า Apache

<VirtualHost *:443>
    ServerName localhost
    ServerAlias dev.local

    SSLEngine on
    SSLCertificateFile    /etc/ssl/self-signed/server.crt
    SSLCertificateKeyFile /etc/ssl/self-signed/server.key

    SSLProtocol           all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite        HIGH:!aNULL:!MD5

    DocumentRoot /var/www/html
    <Directory /var/www/html>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# บังคับ HTTPS
<VirtualHost *:80>
    ServerName localhost
    Redirect permanent / https://localhost/
</VirtualHost>

หลังแก้ไข Config ให้ Reload Web Server:

# Nginx
sudo nginx -t && sudo systemctl reload nginx

# Apache
sudo apachectl configtest && sudo systemctl reload apache2

ติดตั้ง Certificate ใน Browser Trust Store

เพื่อให้ Browser ไม่แสดงคำเตือน "Not Secure" ใน Dev Environment ต้อง Import Certificate เข้า Trust Store ของแต่ละระบบปฏิบัติการ:

macOS

# วิธีที่ 1: ผ่าน Command Line
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain server.crt

# วิธีที่ 2: ผ่าน Keychain Access GUI
# 1. ดับเบิลคลิกไฟล์ server.crt
# 2. เปิด Keychain Access → ค้นหา CN ของ Certificate
# 3. ดับเบิลคลิก → Trust → "When using this certificate" → Always Trust

Linux (Ubuntu/Debian)

sudo cp server.crt /usr/local/share/ca-certificates/dev-localhost.crt
sudo update-ca-certificates
# ผลลัพธ์: 1 added, 0 removed; done.

Windows

# รัน PowerShell ในฐานะ Administrator
Import-Certificate -FilePath "C:\path\to\server.crt" `
  -CertStoreLocation Cert:\LocalMachine\Root

# หรือผ่าน GUI:
# 1. ดับเบิลคลิก server.crt → Install Certificate
# 2. Store Location: Local Machine → Next
# 3. Place all certificates in the following store → Browse
# 4. เลือก Trusted Root Certification Authorities → OK → Finish

เคล็ดลับ mkcert — เครื่องมือสร้าง Self-Signed SSL ที่ง่ายกว่า OpenSSL: ถ้าใช้บ่อยมาก ลองใช้ mkcert (github.com/FiloSottile/mkcert) ซึ่งสร้าง Local CA อัตโนมัติและติดตั้งเข้า System Trust Store ทุกระบบในคำสั่งเดียว: mkcert -install แล้วสร้าง Certificate ด้วย mkcert localhost 127.0.0.1 ::1 ได้เลยโดยไม่ต้องจัดการ OpenSSL config ซับซ้อน

สร้าง Self-Signed SSL สำหรับ Docker และ Node.js

นักพัฒนาที่ใช้ Docker หรือ Node.js มักต้องการ Self-Signed SSL สำหรับสร้าง HTTPS Server ภายใน Container หรือ Development Server ดังนี้:

Node.js HTTPS Server

const https = require('https');
const fs = require('fs');

const options = {
  key:  fs.readFileSync('/path/to/server.key'),
  cert: fs.readFileSync('/path/to/server.crt'),
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Hello HTTPS World!\n');
}).listen(443, () => {
  console.log('HTTPS Server running on port 443');
});

Docker Compose กับ Nginx + SSL

version: '3.8'
services:
  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./ssl/server.crt:/etc/ssl/certs/server.crt:ro
      - ./ssl/server.key:/etc/ssl/private/server.key:ro
      - ./html:/usr/share/nginx/html:ro

ปิดการตรวจสอบ SSL ใน Development Tools

บาง Tool ปฏิเสธ Self-Signed SSL โดยค่าเริ่มต้น สามารถปิดชั่วคราวได้:

# curl: ใช้ -k หรือ --insecure
curl -k https://localhost/api/health

# wget
wget --no-check-certificate https://localhost/file.zip

# Python requests
import requests
response = requests.get('https://localhost', verify=False)

# Node.js / npm (ตั้งค่า env var)
export NODE_TLS_REJECT_UNAUTHORIZED=0
node app.js

# Git
git config --global http.sslVerify false  # ⚠️ ควรตั้งเฉพาะ repo ไม่ใช่ global

คำเตือน: ปิดการตรวจสอบ SSL ใน Development เท่านั้น อย่าลืมเปิดกลับใน Production เพราะจะทำให้ Man-in-the-Middle Attack ทำได้ง่าย

สร้าง Certificate Authority (CA) ส่วนตัว สำหรับ Team Development

ถ้าทำงานเป็น Team และต้องการให้ทุกคนเชื่อถือ Certificate เดียวกันโดยไม่ต้อง Import ทีละเครื่อง วิธีที่ดีกว่าคือสร้าง Root CA ส่วนตัวแล้วแจกจ่าย CA Certificate ให้ทีมติดตั้งครั้งเดียว หลังจากนั้น Certificate ใหม่ที่ Sign โดย CA นี้จะได้รับความเชื่อถืออัตโนมัติ:

# ขั้นตอนที่ 1: สร้าง Root CA Private Key
openssl genrsa -out ca.key 4096

# ขั้นตอนที่ 2: สร้าง Root CA Certificate (อายุ 10 ปี)
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
  -out ca.crt \
  -subj "/C=TH/ST=Bangkok/O=MyCompany Dev CA/CN=MyCompany Development Root CA"

# ขั้นตอนที่ 3: สร้าง Private Key สำหรับ Server
openssl genrsa -out server.key 4096

# ขั้นตอนที่ 4: สร้าง CSR
openssl req -new -key server.key -out server.csr \
  -subj "/C=TH/ST=Bangkok/O=MyCompany/CN=dev.mycompany.local"

# ขั้นตอนที่ 5: Sign CSR ด้วย CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365 -sha256 \
  -extfile <(printf "subjectAltName=DNS:dev.mycompany.local,DNS:*.dev.mycompany.local,IP:192.168.1.100")

แจกจ่าย ca.crt ให้สมาชิก Team ติดตั้งเข้า Trust Store แต่ละเครื่องครั้งเดียว จากนั้นทุก Server Certificate ที่ Sign ด้วย CA นี้จะเชื่อถือโดยอัตโนมัติ โดยไม่ต้อง Import ทีละใบ

Renew Self-Signed SSL Certificate

เมื่อ Certificate ใกล้หมดอายุ สร้างใหม่แทนการ Renew เพราะ Self-Signed ไม่มีกระบวนการ Renewal จาก CA:

# ตรวจสอบวันหมดอายุ
openssl x509 -in server.crt -noout -enddate
# ผลลัพธ์: notAfter=Jun  9 00:00:00 2027 GMT

# สร้างใหม่ด้วย config เดิม (ถ้าเก็บ san.cnf ไว้)
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
  -days 365 -nodes -config san.cnf

# หรือถ้ามี Shell Script สำหรับ Automation
cat > renew-ssl.sh << 'EOF'
#!/bin/bash
openssl req -x509 -newkey rsa:4096 \
  -keyout /etc/ssl/self-signed/server.key \
  -out /etc/ssl/self-signed/server.crt \
  -days 365 -nodes -config /etc/ssl/san.cnf
systemctl reload nginx
echo "SSL Certificate renewed: $(date)"
EOF
chmod +x renew-ssl.sh

สามารถตั้ง Cron Job เพื่อ Renew อัตโนมัติก่อนหมดอายุ 30 วัน หรือใช้ Script ตรวจสอบและแจ้งเตือนผ่าน Email เมื่อ Certificate ใกล้หมดอายุ

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

Self-Signed SSL กับ SSL Certificate จาก CA ต่างกันอย่างไร

Self-Signed SSL คือใบรับรองที่คุณออกให้ตัวเองโดยใช้ OpenSSL ไม่ผ่าน Certificate Authority (CA) ดังนั้น Browser จึงไม่เชื่อถือและแสดงคำเตือน "Your connection is not private" ส่วน SSL จาก CA เช่น DigiCert, GlobalSign ได้รับความเชื่อถือจาก Browser และระบบปฏิบัติการทั่วโลก Self-Signed SSL เหมาะใช้เฉพาะ Dev/Staging/Internal ที่ควบคุมผู้ใช้งานได้ ไม่ควรใช้บน Production Server ที่ผู้ใช้ภายนอกเข้าถึง

Self-Signed SSL ใช้บน Production ได้ไหม

ไม่แนะนำอย่างยิ่ง เพราะ Browser ทุกตัว (Chrome, Firefox, Safari, Edge) จะแสดงหน้าเตือน "Not Secure" ก่อนที่ผู้ใช้จะเข้าถึงเว็บไซต์ ทำให้ผู้ใช้ทั่วไปรู้สึกไม่ปลอดภัยและอาจออกจากเว็บทันที สำหรับ Production ควรใช้ SSL Certificate จาก CA ที่ได้รับการรับรอง

วิธีทำให้ Browser เชื่อถือ Self-Signed SSL Certificate ทำอย่างไร

ต้อง Import Certificate (.crt หรือ .pem) เข้า Trust Store ของระบบปฏิบัติการหรือ Browser โดยตรง บน Windows ใช้ certmgr.msc → Trusted Root Certification Authorities → Import บน macOS ใช้ Keychain Access → Certificates → ลาก .crt เข้า → เปลี่ยน Trust เป็น Always Trust บน Linux (Ubuntu/Debian) คัดลอกไฟล์ .crt ไปที่ /usr/local/share/ca-certificates/ แล้วรัน sudo update-ca-certificates

Self-Signed SSL Certificate มีอายุนานแค่ไหน และต้อง Renew บ่อยไหม

คุณกำหนดอายุได้เองเมื่อสร้างด้วยพารามิเตอร์ -days เช่น -days 365 (1 ปี) หรือ -days 3650 (10 ปี) สำหรับ Dev/Staging นิยมตั้ง 365-3650 วัน เพื่อไม่ต้อง Renew บ่อย แต่ Browser ใหม่อาจมีปัญหากับ Certificate อายุยาวกว่า 825 วัน ควรสร้างใหม่เป็นประจำทุกปีหรือเมื่อข้อมูลใน Certificate เปลี่ยน

SSL Certificate ทุกประเภทที่ AsiaGB

DV OV EV Wildcard SSL เริ่มต้น 1,000 บาท/ปี พร้อม Installation Support

ดู SSL Certificate