第07章 - 证书部署与安装
证书申请成功后,需要将证书部署到实际的服务或系统中。acme.sh 提供了 --install-cert 命令和丰富的 deploy hooks(部署钩子),支持几乎所有主流的服务器软件和平台。
7.1 --install-cert 命令详解
7.1.1 为什么不能直接使用 ~/.acme.sh 中的文件
~/.acme.sh/<domain>/ 目录下的证书文件是 acme.sh 的内部存储,不应在 Nginx/Apache 等服务中直接引用:
- 每次续期后内部文件会被覆盖,但服务的 reload 命令需要在正确时机执行
- 内部路径格式可能随版本变化
- 无法跨机器同步(如需要将证书复制到多台服务器)
正确做法:使用 --install-cert 将证书复制到指定路径,并配置续期后自动执行的 reload 命令。
7.1.2 命令语法
acme.sh --install-cert -d <domain> \
[--cert-file <path>] # 域名证书(不含中间证书),较少使用
[--key-file <path>] # 私钥文件(必须保密)
[--fullchain-file <path>] # 完整证书链(推荐使用这个配置 HTTPS)
[--ca-file <path>] # CA 中间证书
[--reloadcmd <command>] # 证书安装/续期后执行的重载命令
--reloadcmd支持复杂命令和脚本(用引号括起来)- 所有参数都会保存到
~/.acme.sh/<domain>/<domain>.conf,后续自动续期时会自动执行
7.1.3 ECC 证书安装
申请 ECC 证书时,安装时需要加 --ecc 标志:
# 申请 ECC 证书
acme.sh --issue --dns dns_cf -d example.com -d *.example.com --keylength ec-256
# 安装 ECC 证书(注意加 --ecc)
acme.sh --install-cert -d example.com --ecc \
--key-file /etc/nginx/ssl/privkey.pem \
--fullchain-file /etc/nginx/ssl/fullchain.pem \
--reloadcmd "systemctl reload nginx"
7.2 部署到 Nginx
7.2.1 基础配置
# 创建证书目录(建议按域名分目录管理)
mkdir -p /etc/nginx/ssl/example.com
# 安装证书
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com/privkey.pem \
--fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \
--reloadcmd "systemctl reload nginx"
7.2.2 Nginx HTTPS 最佳实践配置
# /etc/nginx/conf.d/example.com.conf
# HTTP → HTTPS 重定向
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# 证书配置
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
# SSL 安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 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;
ssl_prefer_server_ciphers off;
# SSL 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 安全头部
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# 站点根目录
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
7.2.3 同域名 RSA + ECC 双证书(Nginx 1.11+)
从 Nginx 1.11.0 起,支持同一域名配置两套证书(RSA 和 ECC),Nginx 会根据客户端能力自动选择:
# 申请 RSA 证书
acme.sh --issue --dns dns_cf -d example.com -d *.example.com
# 申请 ECC 证书
acme.sh --issue --dns dns_cf -d example.com -d *.example.com --keylength ec-256
# 安装 RSA 证书
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com/rsa/privkey.pem \
--fullchain-file /etc/nginx/ssl/example.com/rsa/fullchain.pem \
--reloadcmd "systemctl reload nginx"
# 安装 ECC 证书
acme.sh --install-cert -d example.com --ecc \
--key-file /etc/nginx/ssl/example.com/ecc/privkey.pem \
--fullchain-file /etc/nginx/ssl/example.com/ecc/fullchain.pem \
--reloadcmd "systemctl reload nginx"
Nginx 双证书配置:
server {
listen 443 ssl http2;
server_name example.com;
# RSA 证书
ssl_certificate /etc/nginx/ssl/example.com/rsa/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/rsa/privkey.pem;
# ECC 证书(同时配置,Nginx 会自动选择)
ssl_certificate /etc/nginx/ssl/example.com/ecc/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/ecc/privkey.pem;
}
7.3 部署到 Apache
# 创建证书目录
mkdir -p /etc/apache2/ssl/example.com
# 安装证书
acme.sh --install-cert -d example.com \
--cert-file /etc/apache2/ssl/example.com/cert.pem \
--key-file /etc/apache2/ssl/example.com/privkey.pem \
--fullchain-file /etc/apache2/ssl/example.com/fullchain.pem \
--ca-file /etc/apache2/ssl/example.com/ca.pem \
--reloadcmd "systemctl reload apache2"
Apache HTTPS 虚拟主机配置(/etc/apache2/sites-available/example.com-ssl.conf):
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.com/cert.pem
SSLCertificateKeyFile /etc/apache2/ssl/example.com/privkey.pem
SSLCertificateChainFile /etc/apache2/ssl/example.com/fullchain.pem
# 推荐 SSL 配置
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder off
SSLSessionTickets off
Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>
7.4 部署到 HAProxy
HAProxy 需要将证书和私钥合并到单个 PEM 文件中。
# 使用 HAProxy deploy hook
export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs
export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy"
# 先申请证书
acme.sh --issue --dns dns_cf -d example.com -d *.example.com
# 部署到 HAProxy
acme.sh --deploy -d example.com --deploy-hook haproxy
HAProxy 配置:
frontend https_frontend
bind *:443 ssl crt /etc/haproxy/certs/
mode http
default_backend web_servers
7.5 通过 SSH 部署到远程服务器
acme.sh 的 SSH deploy hook 可以将证书自动推送到远程服务器,非常适合多服务器场景。
7.5.1 基础 SSH 部署
# 配置 SSH 部署参数
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_SERVER="remote-server.example.com"
export DEPLOY_SSH_PORT="22"
# 远程服务器证书存放路径
export DEPLOY_SSH_KEYFILE="/etc/nginx/ssl/example.com/privkey.pem"
export DEPLOY_SSH_FULLCHAIN="/etc/nginx/ssl/example.com/fullchain.pem"
# 证书推送后在远程服务器执行的命令
export DEPLOY_SSH_REMOTE_CMD="systemctl reload nginx"
# 执行部署
acme.sh --deploy -d example.com --deploy-hook ssh
7.5.2 使用特定 SSH 私钥
export DEPLOY_SSH_USER="deploy"
export DEPLOY_SSH_SERVER="192.168.1.100"
# 指定本地 SSH 私钥(默认使用 ~/.ssh/id_rsa)
export DEPLOY_SSH_IDENTITY="/root/.ssh/deploy_key"
export DEPLOY_SSH_KEYFILE="/etc/ssl/privkey.pem"
export DEPLOY_SSH_FULLCHAIN="/etc/ssl/fullchain.pem"
export DEPLOY_SSH_REMOTE_CMD="systemctl reload nginx"
acme.sh --deploy -d example.com --deploy-hook ssh
7.5.3 部署到多台服务器
通过 --reloadcmd 触发自定义脚本,在脚本中依次部署到多台服务器:
cat > /opt/deploy_cert.sh << 'SCRIPT'
#!/bin/bash
DOMAIN="example.com"
FULLCHAIN="/etc/ssl/example.com/fullchain.pem"
PRIVKEY="/etc/ssl/example.com/privkey.pem"
# 服务器列表
SERVERS=("server1.example.com" "server2.example.com" "server3.example.com")
for SERVER in "${SERVERS[@]}"; do
echo "Deploying to $SERVER..."
scp -i /root/.ssh/deploy_key $FULLCHAIN $PRIVKEY "root@$SERVER:/etc/nginx/ssl/"
ssh -i /root/.ssh/deploy_key "root@$SERVER" "systemctl reload nginx"
echo "Done: $SERVER"
done
SCRIPT
chmod +x /opt/deploy_cert.sh
# 安装证书并配置多服务器部署
acme.sh --install-cert -d example.com \
--fullchain-file /etc/ssl/example.com/fullchain.pem \
--key-file /etc/ssl/example.com/privkey.pem \
--reloadcmd "/opt/deploy_cert.sh"
7.6 部署到 Synology NAS
Synology NAS(群晖)是国内外广泛使用的 NAS 设备,acme.sh 有专门的 deploy hook。
7.6.1 自动部署(推荐)
# 新版 DSM 7.x(推荐使用临时管理员)
export SYNO_USE_TEMP_ADMIN=1
acme.sh --deploy -d nas.example.com --deploy-hook synology_dsm
# 旧版或手动指定账户
export SYNO_USERNAME="admin"
export SYNO_PASSWORD="your_password"
export SYNO_HOSTNAME="192.168.1.100"
export SYNO_PORT="5001"
export SYNO_SCHEME="https"
acme.sh --deploy -d nas.example.com --deploy-hook synology_dsm
7.7 部署到 Proxmox VE
Proxmox VE 是流行的开源虚拟化平台:
# 在 Proxmox 节点上执行
acme.sh --issue --dns dns_cf -d pve.example.com
# 部署到 Proxmox(使用内置 deploy hook)
export DEPLOY_PROXMOXVE_API_TOKEN_KEY="your_api_token"
export DEPLOY_PROXMOXVE_API_TOKEN_NAME="your_token_name"
export DEPLOY_PROXMOXVE_SERVER_FQDN="pve.example.com"
acme.sh --deploy -d pve.example.com --deploy-hook proxmoxve
# 或者手动安装(不使用 deploy hook)
acme.sh --install-cert -d pve.example.com \
--certpath /etc/pve/local/pveproxy-ssl.pem \
--keypath /etc/pve/local/pveproxy-ssl.key \
--capath /etc/pve/local/pveproxy-ssl.pem \
--reloadcmd "systemctl restart pveproxy"
7.8 部署到 Docker 容器
7.8.1 宿主机申请,挂载到容器
最简单的方式:在宿主机申请证书,通过 Docker Volume 挂载到容器:
# 在宿主机申请并安装证书
acme.sh --install-cert -d example.com \
--key-file /docker/nginx/ssl/privkey.pem \
--fullchain-file /docker/nginx/ssl/fullchain.pem \
--reloadcmd "docker exec nginx nginx -s reload"
Docker Compose 配置:
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- /docker/nginx/ssl:/etc/nginx/ssl:ro
- /docker/nginx/conf.d:/etc/nginx/conf.d:ro
7.8.2 acme.sh 官方 Docker 镜像
# 使用官方 Docker 镜像
docker run --rm \
-v /docker/acme.sh:/acme.sh \
-e CF_Token="your_cf_token" \
-e CF_Account_ID="your_account_id" \
neilpang/acme.sh --issue \
--dns dns_cf \
-d example.com -d *.example.com
# 安装证书
docker run --rm \
-v /docker/acme.sh:/acme.sh \
-v /docker/nginx/ssl:/ssl \
neilpang/acme.sh --install-cert \
-d example.com \
--key-file /ssl/privkey.pem \
--fullchain-file /ssl/fullchain.pem
7.9 部署到 OpenWrt 路由器
OpenWrt 是常见的嵌入式 Linux 路由器系统,可以在路由器上运行 acme.sh 申请证书(用于路由器管理界面的 HTTPS):
# OpenWrt 安装(使用 opkg 或手动)
opkg update
opkg install curl
# 安装 acme.sh
curl https://get.acme.sh | sh -s email=your@email.com
# 申请证书(使用 DNS API,因为路由器 80 端口通常不对外开放)
export CF_Token="your_cf_token"
export CF_Account_ID="your_account_id"
acme.sh --issue --dns dns_cf -d router.example.com
# 安装证书到 OpenWrt uhttpd
acme.sh --install-cert -d router.example.com \
--key-file /etc/uhttpd.key \
--fullchain-file /etc/uhttpd.crt \
--reloadcmd "/etc/init.d/uhttpd restart"
7.10 部署到 HashiCorp Vault
对于需要集中管理证书的企业环境,可以将证书存储到 HashiCorp Vault:
# 配置 Vault 连接
export VAULT_PREFIX="secret/certs"
export VAULT_ADDR="https://vault.example.com:8200"
export VAULT_TOKEN="your_vault_token"
# 部署到 Vault
acme.sh --deploy -d example.com --deploy-hook vault
# 或使用 vault_cli 方式
acme.sh --deploy -d example.com --deploy-hook vault_cli
7.11 部署到 GitLab Pages
export GITLAB_TOKEN="your_gitlab_personal_access_token"
export GITLAB_PROJECT_ID="12345678"
export GITLAB_DOMAIN="pages.example.com"
acme.sh --deploy -d pages.example.com --deploy-hook gitlab
7.12 PKCS12(PFX)格式转换
Windows IIS、Java(Tomcat、Spring Boot)等环境通常需要 PKCS12(.pfx)格式的证书。
# 生成 PFX 文件(会在 ~/.acme.sh/example.com/ 下生成 example.com.pfx)
acme.sh --toPkcs -d example.com --password your_pfx_password
# ECC 证书转换
acme.sh --toPkcs -d example.com --ecc --password your_pfx_password
# 查看生成的 PFX 文件
ls ~/.acme.sh/example.com/*.pfx
重要:必须指定
--password,否则续期时 PFX 文件不会自动更新。
7.12.1 部署到 Tomcat
# 将 PFX 文件复制到 Tomcat 目录
cp ~/.acme.sh/example.com/example.com.pfx /opt/tomcat/conf/
# 在 Tomcat server.xml 中配置:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/example.com.pfx"
certificateKeystorePassword="your_pfx_password"
type="RSA" />
</SSLHostConfig>
</Connector>
7.13 查看和管理已安装的证书
# 查看所有已颁发证书
acme.sh --list
# 查看特定域名的证书详情
acme.sh --info -d example.com
# 手动重新安装(如果需要更新 reloadcmd 等)
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/privkey.pem \
--fullchain-file /etc/nginx/ssl/fullchain.pem \
--reloadcmd "systemctl reload nginx"
# 吊销证书
acme.sh --revoke -d example.com
# 删除证书(从 acme.sh 管理中移除,不吊销)
acme.sh --remove -d example.com
7.14 小结
本章介绍了 acme.sh 的证书部署方式:
- 核心原则:始终使用
--install-cert将证书复制到目标路径,不直接使用内部存储路径 - Nginx/Apache:配置
--reloadcmd实现续期后自动重载 - HAProxy:使用专用 deploy hook 合并证书和私钥
- SSH 远程部署:支持推送到多台服务器
- 特殊环境:Synology NAS、Proxmox VE、Docker、OpenWrt 等均有对应支持
- 格式转换:通过
--toPkcs生成 Windows/Java 环境所需的 PFX 文件
下一章介绍证书的自动续期和维护管理。