Certbot 证书自动化教程 / 第 7 章:Apache 集成
第 7 章:Apache 集成
7.1 Apache 插件概述
Certbot 的 Apache 插件能够自动完成域名验证并修改 Apache 配置,实现 SSL/TLS 的一键部署。与 Nginx 插件类似,它能自动识别 Apache 虚拟主机配置并进行修改。
插件能力
| 功能 | 说明 |
|---|---|
| 自动验证 | 通过 Apache 响应 ACME HTTP-01 验证 |
| 自动配置 SSL | 修改虚拟主机配置,添加 SSL 指令 |
| HTTPS 重定向 | 自动添加 HTTP → HTTPS 重定向 |
| 模块管理 | 自动启用必要的 SSL 模块 |
| 虚拟主机识别 | 自动识别并匹配 server_name |
所需 Apache 模块
| 模块 | 用途 | 启用命令 |
|---|---|---|
mod_ssl | SSL/TLS 支持 | a2enmod ssl |
mod_rewrite | URL 重写(HTTPS 重定向) | a2enmod rewrite |
mod_headers | 响应头操作(HSTS) | a2enmod headers |
mod_socache_shmcb | OCSP Stapling 缓存 | a2enmod socache_shmcb |
7.2 安装与基本使用
安装 Apache 插件
# Debian / Ubuntu
sudo apt update
sudo apt install -y apache2 python3-certbot-apache
# CentOS / RHEL / Fedora
sudo dnf install -y httpd python3-certbot-apache
# 启用必要模块
sudo a2enmod ssl rewrite headers socache_shmcb
sudo systemctl restart apache2
基本命令
# 为单个域名申请证书并自动配置 Apache
sudo certbot --apache -d example.com
# 为多个域名申请证书
sudo certbot --apache -d example.com -d www.example.com
# 交互式选择域名
sudo certbot --apache
# 仅获取证书,不修改 Apache 配置
sudo certbot certonly --apache -d example.com
执行过程
运行 certbot --apache 后,Certbot 会:
- 读取 Apache 配置文件,识别匹配的 VirtualHost
- 通过 Apache 响应 ACME HTTP-01 验证
- 申请证书
- 创建 SSL 虚拟主机配置
- 可选:添加 HTTP → HTTPS 重定向
- 测试 Apache 配置语法
- 重新加载 Apache
7.3 Apache 配置自动修改
修改前的配置
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
修改后的配置
Certbot 会创建一个新的 SSL 虚拟主机:
# HTTP 虚拟主机(添加重定向)
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
# 新增 HTTPS 虚拟主机
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
7.4 SSL 安全加固
Certbot 生成的 SSL 配置
/etc/letsencrypt/options-ssl-apache.conf 内容:
# OCSP Stapling
SSLUseStapling On
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# Session 配置
SSLSessionCache shmcb:/var/run/ssl_scache(512000)
SSLSessionCacheTimeout 300
# 协议和密码套件
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLCompression off
增强安全配置
在 Certbot 生成配置的基础上,在 VirtualHost 中添加:
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/example.com/chain.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# OCSP Stapling(如未在全局配置中启用)
SSLUseStapling On
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# 安全响应头
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>
启用 HSTS
# 在 SSL 虚拟主机中添加
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
警告: 启用 HSTS 后,浏览器会强制使用 HTTPS 访问。确保你的站点完全支持 HTTPS 后才启用,否则会导致用户无法访问。
HSTS 参数说明
| 参数 | 说明 | 建议值 |
|---|---|---|
max-age | 浏览器缓存 HSTS 的时间(秒) | 63072000(2 年) |
includeSubDomains | 应用到所有子域名 | 视情况而定 |
preload | 可加入浏览器预加载列表 | 确认后启用 |
HSTS 预加载
申请加入浏览器 HSTS 预加载列表:
- 确保站点完全支持 HTTPS
- 设置
max-age至少为 31536000(1 年) - 包含
includeSubDomains和preload指令 - 访问 hstspreload.org 提交申请
7.5 反向代理配置
Apache 反向代理到后端应用
<VirtualHost *:443>
ServerName app.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# 启用代理模块
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# WebSocket 支持
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]
</VirtualHost>
启用必要模块
sudo a2enmod proxy proxy_http proxy_wstunnel rewrite
sudo systemctl restart apache2
7.6 虚拟主机模板
标准 HTTPS 虚拟主机模板
# /etc/apache2/sites-available/example.com.conf
# HTTP 重定向
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
# ACME 验证路径
Alias /.well-known/acme-challenge/ /var/www/certbot/.well-known/acme-challenge/
<Directory "/var/www/certbot/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
# 重定向到 HTTPS
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
# HTTPS 站点
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# SSL 配置
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/example.com/chain.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# 安全头
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
# 文档根目录
<Directory /var/www/example.com>
AllowOverride All
Require all granted
</Directory>
# 日志
ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
</VirtualHost>
启用配置
sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
7.7 多站点配置
场景:一台 Apache 托管多个 HTTPS 站点
# 为多个站点申请证书
sudo certbot --apache \
-d site1.com -d www.site1.com \
-d site2.com -d www.site2.com \
-d api.site3.com
# 分别为每个站点申请
sudo certbot --apache -d site1.com -d www.site1.com
sudo certbot --apache -d site2.com -d www.site2.com
sudo certbot --apache -d api.site3.com
使用通配符证书
# 使用 DNS 验证申请通配符证书
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
-d example.com \
-d "*.example.com"
# 手动配置多个虚拟主机使用同一个通配符证书
# /etc/apache2/sites-available/app.example.com.conf
<VirtualHost *:443>
ServerName app.example.com
DocumentRoot /var/www/app
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
<Directory /var/www/app>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
7.8 Let’s Encrypt 验证路径配置
确保 ACME 路径可访问
# 在 HTTP 虚拟主机中配置
<VirtualHost *:80>
ServerName example.com
# ACME 验证路径(HTTPS 重定向前)
Alias /.well-known/acme-challenge/ /var/www/certbot/.well-known/acme-challenge/
<Directory "/var/www/certbot/.well-known/acme-challenge/">
Options None
AllowOverride None
Require all granted
</Directory>
# 非 ACME 请求重定向到 HTTPS
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
7.9 常见问题排错
问题 1:模块未启用
AH00526: Syntax error on line XX of /etc/apache2/sites-enabled/...
Invalid command 'SSLEngine'
解决方案:
sudo a2enmod ssl
sudo systemctl restart apache2
问题 2:端口 443 未监听
no listening sockets available, shutting down
解决方案:
# 确认 Apache 配置中包含 443 端口监听
grep -r "Listen" /etc/apache2/ports.conf
# 应该有:
# Listen 80
# Listen 443
# 如果没有,编辑 ports.conf
sudo vim /etc/apache2/ports.conf
sudo systemctl restart apache2
问题 3:VirtualHost 不匹配
Certbot could not find a matching VirtualHost
解决方案:
# 检查 VirtualHost 配置
apache2ctl -S
# 确保 ServerName 与 -d 参数匹配
# 确保站点已启用
sudo a2ensite example.com.conf
问题 4:.htaccess 被忽略
解决方案:
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
sudo a2enmod rewrite
sudo systemctl restart apache2
7.10 Apache 与 Nginx 对比
| 特性 | Apache | Nginx |
|---|---|---|
| Certbot 插件支持 | ✅ | ✅ |
| 配置风格 | XML (声明式) | 指令式 |
| .htaccess 支持 | ✅ | ❌ |
| 事件驱动架构 | 有限 | ✅ 原生 |
| 内存占用 | 较高 | 较低 |
| 动态内容处理 | mod_php/mod_fcgid | 通过 FastCGI |
| Certbot 配置修改 | 创建新 VirtualHost | 直接修改 server 块 |
7.11 最佳实践
- 使用
--apache一键部署: 简单场景让 Certbot 自动处理 - 启用必要模块:
ssl、rewrite、headers、socache_shmcb - 配置 HSTS: 在确认 HTTPS 正常后逐步启用
- 使用 Include 复用配置: 将 SSL 参数放在独立文件中
- 定期检查配置语法: 使用
apache2ctl configtest - 监控证书过期: 设置提醒或使用自动化监控