本指南將帶你完成在 Apache HTTP Server 上使用 mod_ssl 安裝 SSL 證書的全過程——從上傳檔案到加固 TLS 設定,再到排查常見錯誤。適用於來自 GetHTTPS、Certbot 或任何憑證授權機構的證書。
如果你還沒有證書,5 分鐘內免費獲取一個。
前提條件
- Apache 2.4+ 已安裝並在 HTTP(埠 80)上提供網站服務
- Root/sudo 訪問許可權
- 證書檔案 — Apache 需要三個獨立檔案:
cert.pem— 你的證書(僅終端實體)privkey.pem— 你的私鑰chain.pem— 中間憑證授權機構證書鏈
為什麼需要三個檔案? 不同於 Nginx(使用單個
fullchain.pem),Apache 傳統上需要將證書和證書鏈分開存放。Apache 2.4.8+ 可以在SSLCertificateFile中使用fullchain.pem並省略SSLCertificateChainFile。格式詳情 →
第一步:上傳證書檔案
# Create a secure directory
sudo mkdir -p /etc/ssl/gethttps
# Copy files to the server
sudo cp cert.pem chain.pem privkey.pem /etc/ssl/gethttps/
# Lock down the private key
sudo chmod 600 /etc/ssl/gethttps/privkey.pem
sudo chmod 644 /etc/ssl/gethttps/cert.pem /etc/ssl/gethttps/chain.pem
sudo chown root:root /etc/ssl/gethttps/*
如果透過 SCP 傳輸:
scp cert.pem chain.pem privkey.pem user@your-server:/tmp/
# On the server:
sudo mv /tmp/{cert,chain,privkey}.pem /etc/ssl/gethttps/
第二步:啟用所需的 Apache 模組
# Debian/Ubuntu
sudo a2enmod ssl # Core SSL module
sudo a2enmod headers # For HSTS and security headers
sudo a2enmod rewrite # For HTTP→HTTPS redirect (if using .htaccess)
sudo systemctl restart apache2
# CentOS/RHEL/Amazon Linux
sudo yum install mod_ssl # Usually installs and enables in one step
sudo systemctl restart httpd
驗證 mod_ssl 已載入:
apachectl -M | grep ssl
# Expected: ssl_module (shared)
第三步:配置 HTTPS VirtualHost
建立或編輯你網站的 SSL 配置。在 Debian/Ubuntu 上,通常位於 /etc/apache2/sites-available/yourdomain-ssl.conf:
# ─── HTTPS server ────────────────────────────
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
# Certificate files
SSLEngine on
SSLCertificateFile /etc/ssl/gethttps/cert.pem
SSLCertificateKeyFile /etc/ssl/gethttps/privkey.pem
SSLCertificateChainFile /etc/ssl/gethttps/chain.pem
# TLS protocol — only 1.2 and 1.3
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLCompression off
# OCSP stapling (faster cert verification for clients)
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/apache2/ssl_stapling(128000)"
# Security headers
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
# Your site
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
</Directory>
</VirtualHost>
# ─── HTTP redirect ───────────────────────────
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
各指令說明:
| 指令 | 用途 |
|---|---|
SSLEngine on | 為此 VirtualHost 啟用 SSL/TLS |
SSLCertificateFile | 證書路徑 |
SSLCertificateKeyFile | 私鑰路徑 |
SSLCertificateChainFile | 中間憑證授權機構證書的路徑 |
SSLProtocol | 僅允許 TLS 1.2/1.3 — 舊版本已棄用 |
SSLHonorCipherOrder off | 讓用戶端選擇最佳加密套件 |
SSLCompression off | 防止 CRIME 攻擊 |
SSLUseStapling | 伺服器預取 OCSP 響應 |
Strict-Transport-Security | HSTS — 瀏覽器記住始終使用 HTTPS |
Redirect permanent | 301 重新導向 HTTP → HTTPS |
第四步:啟用站點並測試
# Debian/Ubuntu
sudo a2ensite yourdomain-ssl.conf
sudo apachectl configtest # Must say "Syntax OK"
sudo systemctl reload apache2
# CentOS/RHEL
sudo apachectl configtest
sudo systemctl reload httpd
如果 configtest 報告錯誤,它會告訴你確切的行號——在重新載入之前修復它。
第五步:驗證
瀏覽器: 訪問 https://yourdomain.com。點選鎖頭圖示 → 驗證簽發者為”Let’s Encrypt”。
命令列:
echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
線上工具: 使用 SSL Labs Server Test 進行綜合評分。目標:A 或 A+。
Apache 與 Nginx:證書檔案差異
| Apache | Nginx | |
|---|---|---|
| 證書 | SSLCertificateFile cert.pem | ssl_certificate fullchain.pem |
| 私鑰 | SSLCertificateKeyFile privkey.pem | ssl_certificate_key privkey.pem |
| 證書鏈 | SSLCertificateChainFile chain.pem | 包含在 fullchain.pem 中 |
| 所需檔案 | 3 個獨立檔案 | 2 個檔案(證書鏈合併) |
Apache 2.4.8+ 也可以在 SSLCertificateFile 中使用合併的 fullchain.pem——這樣就可以省略 SSLCertificateChainFile。
續簽
當你的證書即將過期時(在此檢視):
# Replace files
sudo cp new-cert.pem /etc/ssl/gethttps/cert.pem
sudo cp new-chain.pem /etc/ssl/gethttps/chain.pem
sudo cp new-privkey.pem /etc/ssl/gethttps/privkey.pem
# Reload (not restart) — zero downtime
sudo systemctl reload apache2 # Debian/Ubuntu
sudo systemctl reload httpd # CentOS/RHEL
故障排查
”AH02572: Failed to configure certificate” / 金鑰不匹配
證書和私鑰不對應。驗證它們是否匹配:
# These two hashes must be identical
openssl x509 -noout -modulus -in /etc/ssl/gethttps/cert.pem | md5sum
openssl rsa -noout -modulus -in /etc/ssl/gethttps/privkey.pem | md5sum
如果不同,說明你使用了來自不同 GetHTTPS 會話的檔案。請從同一會話重新下載。
“AH01909: server certificate does NOT include an ID”
你的 ServerName 與證書 SAN 欄位中的任何域名都不匹配:
openssl x509 -noout -text -in /etc/ssl/gethttps/cert.pem | grep -A1 "Subject Alternative Name"
確保你的 Apache ServerName 與列出的 DNS 名稱之一完全匹配。
瀏覽器顯示”證書不受信任”
缺少中間證書鏈。驗證 SSLCertificateChainFile 指向的是 chain.pem(中間證書),而不是 cert.pem。測試證書鏈:
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | grep "Verify return code"
# "Verify return code: 0 (ok)" = good
# "Verify return code: 21 (unable to verify)" = chain incomplete
“AH00526: Syntax error on line X”
Apache 配置語法錯誤。常見原因:
- 缺少
</VirtualHost>閉合標籤 SSLCertificateChainFile拼寫錯誤- Header 值缺少引號
- 檔案路徑不存在
HTTPS 正常但顯示”不安全”
混合內容——你的頁面透過 HTTP 載入了資源。開啟 DevTools → Console → 修復 http:// 開頭的 URL。
常見問題
可以使用 fullchain.pem 代替分開的 cert + chain 嗎?
可以,在 Apache 2.4.8+ 上。使用 SSLCertificateFile /path/to/fullchain.pem 並完全移除 SSLCertificateChainFile 指令。在較舊版本的 Apache 上,你需要分開的檔案。
如何檢查我的 Apache 版本?
apachectl -v
# or
httpd -v
需要重啟 Apache 還是僅重新載入?
重新載入(systemctl reload)就夠了,且不會造成停機。重啟(systemctl restart)會斷開所有活動連線。證書更改時始終使用 reload。
Apache 能否為不同域名提供不同的證書?
可以。建立單獨的 <VirtualHost *:443> 塊,使用不同的 ServerName 和 SSLCertificate* 指令。Apache 使用 SNI(Server Name Indication)來選擇正確的證書。
Apache 是否支援 ECDSA 證書?
支援。Apache 2.4+ 處理 ECDSA 的方式與 RSA 相同——相同的指令,相同的檔案格式。GetHTTPS 預設生成 ECDSA P-256。
Apache 的 SSL 錯誤日誌在哪裡?
# Debian/Ubuntu
tail -f /var/log/apache2/error.log
# CentOS/RHEL
tail -f /var/log/httpd/ssl_error_log