证书路径设置
证书路径设置
本节介绍 TLS 证书文件在 Docker 容器和宿主机之间的路径配置。正确的路径配置是 Mosquitto TLS 正常工作的前提。学习完成后,您将能够:
- 正确配置证书文件路径
- 管理证书文件的权限
- 处理证书更新后的路径问题
- 理解 Docker volume 挂载与路径的关系
在开始本节之前,请确保:
- 已获取 Let’s Encrypt 证书
- Mosquitto 使用 Docker 部署
- 了解 Docker volume 挂载概念
Certificate Directory Structure
Section titled “Certificate Directory Structure”推荐目录结构
Section titled “推荐目录结构”/opt/mosquitto/├── config/│ ├── mosquitto.conf # Mosquitto 配置文件│ ├── passwd # 密码文件│ └── acl # 访问控制列表├── certs/│ ├── fullchain.pem # 服务器证书 + 中间证书链│ └── privkey.pem # 服务器私钥├── data/│ └── mosquitto.db # 持久化数据└── log/ └── mosquitto.log # 日志文件Docker Volume 映射
Section titled “Docker Volume 映射”# docker-compose.yml volumes 配置volumes: - ./config/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro - ./config/passwd:/mosquitto/config/passwd:ro - ./config/acl:/mosquitto/config/acl:ro - ./certs:/mosquitto/certs:ro # 证书文件 - ./data:/mosquitto/data # 数据持久化 - ./log:/mosquitto/log # 日志输出From Let’s Encrypt to Mosquitto
Section titled “From Let’s Encrypt to Mosquitto”自动复制脚本
Section titled “自动复制脚本”#!/bin/bash# 将 Let's Encrypt 证书同步到 Mosquitto 证书目录
DOMAIN="mqtt.example.com"LETSENCRYPT_DIR="/etc/letsencrypt/live/${DOMAIN}"MOSQUITTO_CERTS_DIR="/opt/mosquitto/certs"
echo "同步证书文件到 Mosquitto..."
# 检查 Let's Encrypt 证书是否存在if [ ! -f "${LETSENCRYPT_DIR}/fullchain.pem" ]; then echo "错误: Let's Encrypt 证书未找到: ${LETSENCRYPT_DIR}" exit 1fi
# 创建目标目录mkdir -p "${MOSQUITTO_CERTS_DIR}"
# 复制证书文件(使用 cat 而非 cp -L 确保内容最新)cat "${LETSENCRYPT_DIR}/fullchain.pem" > "${MOSQUITTO_CERTS_DIR}/fullchain.pem"cat "${LETSENCRYPT_DIR}/privkey.pem" > "${MOSQUITTO_CERTS_DIR}/privkey.pem"
# 设置权限chmod 644 "${MOSQUITTO_CERTS_DIR}/fullchain.pem"chmod 600 "${MOSQUITTO_CERTS_DIR}/privkey.pem"
# 设置所有者(Mosquitto Docker 容器使用 UID 1883)chown 1883:1883 "${MOSQUITTO_CERTS_DIR}/fullchain.pem"chown 1883:1883 "${MOSQUITTO_CERTS_DIR}/privkey.pem"
echo "证书同步完成"echo "请重新加载 Mosquitto: docker exec mosquitto kill -HUP 1"Certbot 续期钩子
Section titled “Certbot 续期钩子”配置 Certbot 在续期后自动同步证书:
# 创建续期后钩子sudo tee /etc/letsencrypt/renewal-hooks/post/mosquitto.sh << 'EOF'#!/bin/bash# Let's Encrypt 续期后自动同步证书到 Mosquitto
DOMAIN="mqtt.example.com"LETSENCRYPT_DIR="/etc/letsencrypt/live/${DOMAIN}"MOSQUITTO_CERTS_DIR="/opt/mosquitto/certs"
cat "${LETSENCRYPT_DIR}/fullchain.pem" > "${MOSQUITTO_CERTS_DIR}/fullchain.pem"cat "${LETSENCRYPT_DIR}/privkey.pem" > "${MOSQUITTO_CERTS_DIR}/privkey.pem"chmod 644 "${MOSQUITTO_CERTS_DIR}/fullchain.pem"chmod 600 "${MOSQUITTO_CERTS_DIR}/privkey.pem"chown 1883:1883 "${MOSQUITTO_CERTS_DIR}/fullchain.pem"chown 1883:1883 "${MOSQUITTO_CERTS_DIR}/privkey.pem"
# 重新加载 Mosquitto(发送 SIGHUP 信号)docker exec mosquitto kill -HUP 1 2>/dev/null || trueEOF
# 设置执行权限chmod +x /etc/letsencrypt/renewal-hooks/post/mosquitto.sh
# 测试续期钩子sudo certbot renew --dry-runCertificate Path in Mosquitto.conf
Section titled “Certificate Path in Mosquitto.conf”Docker 容器内路径
Section titled “Docker 容器内路径”# 注意:路径是 Docker 容器内部的路径
# 证书文件(指向 /mosquitto/certs/ 目录)cafile /mosquitto/certs/fullchain.pemcertfile /mosquitto/certs/fullchain.pemkeyfile /mosquitto/certs/privkey.pem路径映射关系:
| 宿主机路径 | Docker 容器内路径 |
|---|---|
| /opt/mosquitto/certs/ | /mosquitto/certs/ |
| /opt/mosquitto/config/mosquitto.conf | /mosquitto/config/mosquitto.conf |
Permissions
Section titled “Permissions”文件和目录权限
Section titled “文件和目录权限”# 证书目录权限drwxr-xr-x 2 root root 4096 May 18 10:00 /opt/mosquitto/certs/
# 证书文件权限-rw-r--r-- 1 1883 1883 3500 May 18 10:00 fullchain.pem # 644-rw------- 1 1883 1883 1700 May 18 10:00 privkey.pem # 600
# 配置文件权限-rw-r--r-- 1 root root 1200 May 18 10:00 mosquitto.conf # 644权限说明:
| 文件 | 权限 | 理由 |
|---|---|---|
| fullchain.pem | 644 | 证书是公开信息,Mosquitto 读取 |
| privkey.pem | 600 | 私钥机密,仅 Mosquitto 进程读取 |
| mosquitto.conf | 644 | 配置文件,包含证书路径 |
常见权限问题
Section titled “常见权限问题”# 错误: 私钥权限太大sudo chmod 600 /opt/mosquitto/certs/privkey.pem
# 错误: Mosquitto 容器无法读取# 检查 Mosquitto 内用户 IDdocker exec mosquitto id mosquitto# uid=1883(mosquitto) gid=1883(mosquitto)sudo chown -R 1883:1883 /opt/mosquitto/certs/Certificate Validation
Section titled “Certificate Validation”路径和完整性验证
Section titled “路径和完整性验证”# 1. 检查证书文件是否存在ls -la /opt/mosquitto/certs/
# 2. 验证证书文件格式openssl x509 -in /opt/mosquitto/certs/fullchain.pem -text -noout | head -20
# 3. 验证证书未过期openssl x509 -in /opt/mosquitto/certs/fullchain.pem -noout -dates# notBefore=May 18 00:00:00 2026 GMT# notAfter=Aug 16 00:00:00 2026 GMT
# 4. 验证证书域名openssl x509 -in /opt/mosquitto/certs/fullchain.pem -noout -subject# subject=CN = mqtt.example.com
# 5. 验证证书链完整性openssl verify -CAfile /opt/mosquitto/certs/fullchain.pem \ /opt/mosquitto/certs/fullchain.pem# fullchain.pem: OKCertificate Rotation
Section titled “Certificate Rotation”证书更新流程
Section titled “证书更新流程”证书更新周期(Let's Encrypt 90 天自动续期):
Day 1: 第一次获取证书Day 60: Certbot 自动检查并续期(30 天前开始尝试)Day 90: 证书过期(如果未成功续期)
自动化流程:1. Certbot 续期成功2. Renewal hook 触发: sync-certs.sh3. 证书同步到 Mosquitto certs 目录4. Mosquitto 重新加载证书(SIGHUP)5. 新客户端连接使用新证书6. 已连接的客户端继续使用旧证书(不受影响)# 手动续期并触发同步sudo certbot renew --force-renewal# 续期钩子自动执行
# 手动重新加载 Mosquittodocker exec mosquitto kill -HUP 1
# 检查 Mosquitto 日志确认证书加载docker logs mosquitto --tail 20# 输出示例:# 1726425607: OpenSSL reload: certfile /mosquitto/certs/fullchain.pemPre-sales Key Points
Section titled “Pre-sales Key Points”路径配置要点
Section titled “路径配置要点”| 要点 | 说明 | 常见错误 |
|---|---|---|
| 路径唯一性 | 配置文件使用容器内路径 | 误用宿主机路径 |
| 文件权限 | 私钥 600,证书 644 | 权限太高导致读取失败 |
| 自动同步 | 续期钩子自动复制证书 | 忘记配置导致证书过期 |
| 重新加载 | 证书更新后需重新加载 | 证书更新后未通知 Mosquitto |
Summary
Section titled “Summary”本节介绍了证书路径配置:
- 目录结构:certs/ 目录存放 fullchain.pem 和 privkey.pem
- 路径映射:宿主机 /opt/mosquitto/certs/ → 容器 /mosquitto/certs/
- 自动同步:创建同步脚本 + Certbot 续期钩子
- 权限管理:私钥 600,证书 644,所有者 1883:1883
- 验证流程:定期检查证书文件是否存在、是否过期、域名是否正确
- 证书更新:续期后自动同步并重新加载 Mosquitto